MPC-HC 1.7.8 箭头鼠标指针版
MPC-HC (Media Player Classic Home Cinema) 的默认鼠标指针问题严重困扰着我,在没有换操作系统时就一直仍然在用很老的 MPC 6.4。但现在系统已经都换到 Win 7 及 Win 8.1 的 64 位操作系统了,播放器是时候该换了。

结合 MPC-HC 官网上有人提交的一个 bug,我对 MPC-HC 的源代码进行了一些搜索和修改,最后搞定了一共 4 处需要修改的默认鼠标指针设置,接下来上图。

这是官方原版的鼠标指针样式,视频画面上是箭头,底下控制部分都是手形鼠标指针:



这是修改后版本的鼠标指针样式,和 MPC 一致,画面上是手形鼠标指针,底下控制部分都是箭头:



这是修改后版本的关于对话框,1.7.8-arrow 版:



修改版本的下载地址如下:

新浪微盘: MPC-HC.1.7.8-arrow.x86.zip (32 位)
新浪微盘: MPC-HC.1.7.8-arrow.x64.zip (64 位)

Dropbox: MPC-HC.1.7.8-arrow.x86.zip (32 位)
Dropbox: MPC-HC.1.7.8-arrow.x64.zip (64 位)

修改的细节如下,其中就涉及到视频画面上鼠标指针修改的 MouseTouch.cpp 中的这个位置最难找:

  1. deab46f52abe74b76317dadb7db5d8db3d7b1248
  2.  src/mpc-hc/MouseTouch.cpp    | 2 +-
  3.  src/mpc-hc/PlayerSeekBar.cpp | 2 +-
  4.  src/mpc-hc/PlayerToolBar.cpp | 2 +-
  5.  src/mpc-hc/VolumeCtrl.cpp    | 2 +-
  6.  4 files changed, 4 insertions(+), 4 deletions(-)
  7.  
  8. diff --git a/src/mpc-hc/MouseTouch.cpp b/src/mpc-hc/MouseTouch.cpp
  9. index 0162ec5..9fd0b93 100644
  10. --- a/src/mpc-hc/MouseTouch.cpp
  11. +++ b/src/mpc-hc/MouseTouch.cpp
  12. @@ -433,7 +433,7 @@ bool CMouse::SelectCursor(const CPoint& screenPoint, const CPoint& clientPoint,
  13.      }
  14.  
  15.      if (!bHidden || bHiddenAndMoved || !bCanHide) {
  16. -        m_cursor = Cursor::ARROW;
  17. +        m_cursor = Cursor::HAND;
  18.          if (bCanHide) {
  19.              if (!m_bMouseHiderStarted || screenPoint != m_mouseHiderStartScreenPoint) {
  20.                  StartMouseHider(screenPoint);
  21. diff --git a/src/mpc-hc/PlayerSeekBar.cpp b/src/mpc-hc/PlayerSeekBar.cpp
  22. index 9a57246..86ac612 100644
  23. --- a/src/mpc-hc/PlayerSeekBar.cpp
  24. +++ b/src/mpc-hc/PlayerSeekBar.cpp
  25. @@ -39,7 +39,7 @@ CPlayerSeekBar::CPlayerSeekBar(CMainFrame* pMainFrame)
  26.      , m_bHasDuration(false)
  27.      , m_rtHoverPos(0)
  28.      , m_bHovered(false)
  29. -    , m_cursor(AfxGetApp()->LoadStandardCursor(IDC_HAND))
  30. +    , m_cursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW))
  31.      , m_bDraggingThumb(false)
  32.      , m_tooltipState(TOOLTIP_HIDDEN)
  33.      , m_bIgnoreLastTooltipPoint(true)
  34. diff --git a/src/mpc-hc/PlayerToolBar.cpp b/src/mpc-hc/PlayerToolBar.cpp
  35. index 9dfa476..586049b 100644
  36. --- a/src/mpc-hc/PlayerToolBar.cpp
  37. +++ b/src/mpc-hc/PlayerToolBar.cpp
  38. @@ -332,7 +332,7 @@ BOOL CPlayerToolBar::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
  39.  
  40.          int i = getHitButtonIdx(point);
  41.          if (i >= 0 && !(GetButtonStyle(i) & (TBBS_SEPARATOR | TBBS_DISABLED))) {
  42. -            ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_HAND));
  43. +            ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
  44.              ret = TRUE;
  45.          }
  46.      }
  47. diff --git a/src/mpc-hc/VolumeCtrl.cpp b/src/mpc-hc/VolumeCtrl.cpp
  48. index bd41188..592f4c8 100644
  49. --- a/src/mpc-hc/VolumeCtrl.cpp
  50. +++ b/src/mpc-hc/VolumeCtrl.cpp
  51. @@ -194,7 +194,7 @@ void CVolumeCtrl::HScroll(UINT nSBCode, UINT nPos)
  52.  
  53.  BOOL CVolumeCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
  54.  {
  55. -    ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_HAND));
  56. +    ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
  57.      return TRUE;
  58.  }
当前语言: 中文 (简体) · also available in: English
Gender Guesser v0.10.0 已发布
这个版本变化比较大,类的方法、概率计算算法和词典的规模都有了改进和提升。

从 PHP Classes 下载:
http://www.phpclasses.org/package/2701-PHP-Guess-the-gender-of-Chinese-names.html

更新日志:
  • 去除 getOffset(), getTendencyByOffset() 和 getTendency() 方法
  • 新增 getMaleProbability() 方法,可直接得到为男性姓名的概率值
  • 将 getLexiconName() 方法改为 getLexiconComment(),用于获取词典的注释信息
  • 默认词典的原始数据量上升到 1700 万条 (上一版本为 2 万条)
  • 默认词典有完整和基础两个版本,所包含的字符数量不同

演示地址:
http://demo.wudilabs.org/lab/gender_guesser/

PPT 下载:
http://blog.wudilabs.org/uploads/gender_guesser_ppt_by_wudi.pdf
当前语言: 中文 (简体) · also available in: English
今天把几个本地的 Git 版本库推送到了 GitHub 上面
https://github.com/wudicgi?tab=repositories
当前语言: 中文 (简体) · also available in: English
Gender Guesser v0.05.0 已发布
从 PHP Classes 下载:
http://www.phpclasses.org/package/2701-PHP-Guess-the-gender-of-Chinese-names.html

更新日志:
  • 该版本起仅支持 PHP 5 环境,且需要开启 mbstring 扩展
  • 词典数据改为以 PHP 序列化数据方式存储
  • 默认词典由 20,933 个姓名性别数据生成 (上一版本为 5,561 个)
  • 默认词典同时包含简体中文和繁体中文的字符

演示地址:
http://demo.wudilabs.org/lab/gender_guesser/
当前语言: 中文 (简体) · also available in: English
查找附近地点的算法 —— Geohash
Geohash 是一个有名的用于搜索附近地点的算法。今天在实验室的例会上,我讲了一下这个算法的思想和 C 语言实现。现在将幻灯片的 PDF 发布出来,以供参考。

下载: http://blog.wudilabs.org/uploads/geohash_ppt_by_wudi.pdf





如果你下载看了的话,会发现其中有一个 C 语言的实现。目前这个库的基本功能都已经完成了,待整理完善后,我会连同一个不使用 malloc 动态内存分配的 NMEA 解析库一块发布出来。
当前语言: 中文 (简体) · also available in: English
在 C# 中通过 ffmpeg.exe 获取媒体文件的音频波形数据
以前这个功能我是通过 NAudio 实现的,需要把媒体文件的音频轨提取成单独的 WAV 文件才能获取到波形数据。即使借助 RAM Disk,速度也依然很慢。

忍受了一段时间后,昨天又搜了一遍 C# 下可用的音频处理类库,依然没有更好的选择。最后想到在视频转码和截图时常用的 mencoder, ffmpeg 等跨平台的命令行工具了。看了一下 ffmpeg 支持 stdout 输出,貌似可用。

最开始尝试了输出 WAV 格式的二进制流到 stdout,结果发现输出格式为 WAV 时,ffmpeg 会先在头部写一个占位的大小信息,在整个流输出结束后,再 seek 到那个位置改写大小信息 (来源)。这样当输出不是直接写入到文件,而是以 stdout 流直接输出时,这个改写操作就不能进行了,最后得到的 WAV 格式的数据流中的信息有错误,也就无法使用了。

使用 WAV 格式只是因为对它比较熟悉,毕竟是常见的最基本的直接存储型的音频文件格式了。但在翻阅 ffmpeg 文档后,发现它支持的格式非常多和灵活,可以选择直接输出整型或浮点数的波形数据,而不带额外的头信息。这正方便我用 C# 处理,最终我选择了最适用于后续处理的 Little Endian 32 位浮点数格式,也就是调用 ffmpeg.exe 时给定 "-f f32le" 参数。"-ar 44100 -ac 1" 参数则使输出固定为单声道 44100Hz 采样率的数据。

最后,完整的代码如下。Main() 方法中调用 ffmpeg.exe 将 test.mp4 的音频轨以单声道,44100Hz 采样率,32 位浮点数的形式输出到 stdout,由 ProcessStream() 对流 proc.StandardOutput.BaseStream 进行读取,最终由 ProcessBuffer() 方法获取每一个单精度浮点数。

  1. using System.Diagnostics;
  2. using System.IO;
  3.  
  4. // ...
  5.  
  6. static void Main(string[] args)
  7. {
  8.     // ...
  9.     string path = @"E:\Media\test.mp4";
  10.  
  11.     Process proc = new Process();
  12.     proc.StartInfo.FileName = @"E:\ffmpeg\ffmpeg.exe";
  13.     proc.StartInfo.Arguments = "-i \"" + path + "\" -vn -ar 44100 -ac 1 -f f32le -";
  14.     proc.StartInfo.CreateNoWindow = true;
  15.     proc.StartInfo.UseShellExecute = false;
  16.     proc.StartInfo.RedirectStandardOutput = true;
  17.     proc.StartInfo.RedirectStandardError = true;
  18.     proc.ErrorDataReceived += new DataReceivedEventHandler(proc_ErrorDataReceived);
  19.     proc.Start();
  20.     proc.BeginErrorReadLine();
  21.     ProcessStream(proc.StandardOutput.BaseStream);
  22.  
  23.     proc.WaitForExit(10000); // 10s
  24.     if (!proc.HasExited)
  25.     {
  26.         proc.Kill();
  27.         Environment.Exit(1);
  28.     }
  29.     // ...
  30. }
  31.  
  32. static void proc_ErrorDataReceived(object sender, DataReceivedEventArgs e)
  33. {
  34.     if (e.Data != null)
  35.     {
  36.         // Console.WriteLine(e.Data);
  37.         // do nothing
  38.     }
  39. }
  40.  
  41. static void ProcessStream(Stream stream)
  42. {
  43.     int didread;
  44.     int offset = 0;
  45.     byte[] buffer = new byte[sizeof(Single) * (1024 + 1)];
  46.  
  47.     int length, residual_length;
  48.  
  49.     while ((didread = stream.Read(buffer, offset, sizeof(Single) * 1024)) != 0)
  50.     {
  51.         length = offset + didread;
  52.         residual_length = length % sizeof(Single);
  53.  
  54.         if (residual_length == 0) {
  55.             ProcessBuffer(buffer, length);
  56.             offset = 0;
  57.         } else {
  58.             length -= residual_length;
  59.             ProcessBuffer(buffer, length);
  60.             Array.Copy(buffer, length, buffer, 0, residual_length);
  61.             offset = residual_length;
  62.         }
  63.     }
  64. }
  65.  
  66. static void ProcessBuffer(byte[] buffer, int length)
  67. {
  68.     int index = 0;
  69.     float sample_value;
  70.  
  71.     while (index < length)
  72.     {
  73.         sample_value = BitConverter.ToSingle(buffer, index);
  74.         index += sizeof(Single);
  75.         // to deal with sample_value
  76.     }
  77. }
  78.  
  79. // ...
当前语言: 中文 (简体) · also available in: English
更多条目: [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] ... [24]
« 上一页 · 下一页 »