编写一个MPlayer的外壳

MPlayer是一个很强大的播放器,在播放文件方面比VLC要更强大一点。只是MPlayer默认没有界面,是一个控制台程序,使用并不方便;于是很多人为MPlayer编写了各种各样的外壳程序,来方便使用,例如目前比较流行的SMplayer。
   
    和VLC、Xine不太一样,MPlayer采用控制台的输入输出来和外壳程序打交道。而VLC和Xine则提供了一堆API,相对比较容易一些。于是编 写一个MPlayer的基本的方法,就是重定向MPlayer的标准输入输出到管道,通过读取MPlayer的输出来分析MPlayer的信息和状态,通 过向MPlayer的标准输入发送命令来控制播放。MPlayer的命令行参数相当复杂,需要仔细阅读其文档和代码。
    向MPlayer发送的命令可以参考 http://www.mplayerhq.hu/DOCS/tech/slave.txt
    MPlayer的man page看这里     http://www.mplayerhq.hu/DOCS/man/en/mplayer.1.html
    SMplayer的源代码                  https://smplayer.svn.sourceforge.net/svnroot/smplayer
    Roger打算把MPlayer嵌入某个软件中,所以也开始写一个MPlayer的外壳程序,还没写多少,很简陋,但是已经可以跑起来了,下面给出控制部分的代码,界面部分是MFC的,就不放出来了。
    最开始的想法是问答式的,在需要某个状态时向MPlayer发命令,然后阻塞等待MPlayer返回,这样效率比较低,就改成了现在这样子,有一个后台线程负责接收

Mplayer的输出并进行分析,状态变量都在类实例里面保存一份,这样就不必等待,比较快一点。
    在编写中遇到的一些问题:
    1. 显示到某个窗口上,-wid 窗口句柄值 -vo directx:noaccel,如果不禁用加速则显示不出来;但是smplayer不禁用也可以,真神奇。
    2. -identify可以让MPlayer在开始播放之后显示一堆信息,很方便
    3. 似乎没有办法获取音量?于是自己维护了一个,每次启动后设置一下
    4. 设置MPlayer的working dir很重要,一方面截屏的图片保存在那里,另外像-vo jpeg:outdir=这样的选项Windows下没法设全路径,也要靠当前目录。
   
   
/* MPlayer.h */

#ifndef _MPLAYER_H_
#define _MPLAYER_H_

#include <windows.h>
#include <stdio.h>

#define WM_MFACE (WM_USER+0×101)

#define LOG_MPLAYER      (0)
#define LOG_USER         (1)
#define LOG_APP          (2)

#define VERBOSE_QUIET    (3)
#define VERBOSE_ERR      (2)
#define VERBOSE_WARN     (1)
#define VERBOSE_DBG      (0)

#define LOG_DEBUG        (0)
#define LOG_WARNING      (1)
#define LOG_ERROR        (2)

#define STATUS_STOP      (0)
#define STATUS_STOPING   (1)
#define STATUS_STARTING  (2)
#define STATUS_PLAY      (3)
#define STATUS_PAUSE     (4)

#define DBG(who, msg)  Log(who, LOG_DEBUG, msg, __LINE__, __FILE__)
#define WARN(who, msg) Log(who, LOG_WARNING, msg, __LINE__, __FILE__)
#define ERR(who, msg)  Log(who, LOG_ERROR, msg, __LINE__, __FILE__)

#define META_MAX_NAME_LEN  31
#define META_MAX_VALUE_LEN 255
#define MAX_META           64
typedef struct _meta
{
  char name [META_MAX_NAME_LEN+1];
  char value[META_MAX_VALUE_LEN+1];
}meta;

class MPlayer 
{

public:

  MPlayer ();
  ~MPlayer();

  void SetMPlayerPath (LPCSTR szMplayerPath)
  {
    strncpy (m_strMPlayerPath, szMplayerPath, MAX_PATH);
  }

  void SetWorkingPath (LPCSTR szWorkingPath)
  {
    strncpy (m_strWorkingPath, szWorkingPath, MAX_PATH);
  }

  void SetMediaPath (LPCSTR szMediaPath)
  {
    strncpy (m_strMediaPath, szMediaPath, 1024);
  }

  void SetParam (LPCSTR szParam)
  {
    strncpy (m_strParam, szParam, 255);
  }

  void SetNotifyWindow (HANDLE hWnd, DWORD dwMessage = WM_MFACE)
  {
    m_hNotifyWindow = hWnd;
    m_dwMessage = dwMessage;
  }

  void SetDisplayWindow (HANDLE hWnd)
  {
    m_hDisplayWindow = hWnd;
  }

  void SetVo (const char* szVout)
  {
    strncpy (m_strVout, szVout, 255);
  }

  void SetAo (const char* szAout)
  {
    strncpy (m_strAout, szAout, 255);
  }

  LPCSTR GetParam ()
  {
    return m_strParam;
  }

  LPCSTR GetMediaPath ()
  {
    return m_strMediaPath;
  }

  double GetFPS ()
  {
    return m_lfFPS;
  }

  const char* GetVideoFormat ()
  {
    return m_strVideoFormat;
  }

  const char* GetAudioFormat ()
  {
    return m_strAudioFormat;
  }

  const char* GetVideoCodec ()
  {
    return m_strVideoCodec;
  }

  const char* GetAudioCodec ()
  {
    return m_strAudioCodec;
  }

  const char* GetMPlayerVersion ()
  {
    return m_strVersion;
  }

  double GetMediaLength ()
  {
    return m_lfMediaLength;
  }

  int GetPos ()
  {
    return m_iPos;
  }

  int GetVideoWidth ()
  {
    return m_iVideoWidth;
  }

  int GetVideoHeight ()
  {
    return m_iVideoHeight;
  }

  int SetVerbose (int verbose)
  {
    if (verbose < VERBOSE_DBG)   verbose = VERBOSE_DBG;
    if (verbose > VERBOSE_QUIET) verbose = VERBOSE_QUIET;
    m_iVerbose = verbose;
    return m_iVerbose;
  }

  int GetMetaCount ()
  {
    return m_iMetas;
  }

  const char* GetMetaName (int nIndex)
  {
    if (nIndex >= 0 && nIndex < m_iMetas)
    {
      return m_arryMetas[nIndex].name;
    }
    else
    {
      return NULL;
    }
  }

  const char* GetMetaValue (int nIndex)
  {
    if (nIndex >= 0 && nIndex < m_iMetas)
    {
      return m_arryMetas[nIndex].value;
    }
    else
    {
      return NULL;
    }
  }
 
  int  Play ();
  int  Stop ();
  int  Pause ();
  int  Seek (int Pos);
  int  GetVolume ();
  int  SetVolume (int Volume);
  int  SetMute (int Mute);
  int  GetMute ();
  int  GetTitle (char* buf, int nBuf);
  int  GetAlbum (char* buf, int nBuf);
  int  GetArtist (char* buf, int nBuf);
  int  GetComment (char* buf, int nBuf);
  int  GetGenre (char* buf, int nBuf);
  int  GetStatus () { return m_iStatus; }
  int  FullScreen ();
  int  Snapshot ();
  const char* GetMeta (const char* szName);
  int  CreateSnapshots (LPCSTR szDir, int nInterval = 60, int nCount = 0);
 

private:

  int  CreateMPlayerProcess();
  int  SendCommand (LPCSTR szCommand);
  void Log (int who, int level, LPCSTR message, int line, const char* file);
  void KillMPlayer ();
  void Notify (int param);
  void ResetStatus ();
  int  GetMPlayerMessages ();
  void ProcessMessage (LPCSTR szMsg);
  const char* hasString (const char* szMsg, const char* style);
  static DWORD WINAPI WorkThread (PVOID pThis);
  DWORD WorkThreadFunc ();

  // config
  char m_strMPlayerPath [MAX_PATH+1];
  char m_strWorkingPath [MAX_PATH+1];
  char m_strMediaPath   [1025];
  char m_strParam       [256];
  char m_strVout        [256];
  char m_strAout        [256];
  int  m_iVerbose;

  HANDLE m_hMPlayerProcess;
  HANDLE m_hWorkingThread;
  HANDLE m_hPipeRead;
  HANDLE m_hPipeWrite;
  HANDLE m_hNotifyWindow;
  HANDLE m_hDisplayWindow;
  DWORD  m_dwMessage;

  // status
  double m_lfMediaLength;
  int    m_iPos;
  int    m_iVolume;
  int    m_iVideoWidth;
  int    m_iVideoHeight;
  int    m_iAudioBitrate;
  double m_lfFPS;
  char   m_strVideoFormat [16];
  char   m_strAudioFormat [16];
  char   m_strVideoCodec [16];
  char   m_strAudioCodec [16];
  char   m_strDemuxer [16];
  char   m_strVersion [128];
  bool   m_bMute;
  int    m_iStatus; // TODO: protect this var for multithread readwrite
  meta   m_arryMetas[MAX_META];
  int    m_iMetas;
};

#endif //_MPLAYER_H_

 

/* MPlayer.cpp */

#include “MPlayer.h”
#include <conio.h>
#define ZeroString(str) ZeroMemory (str, sizeof (str))

#define MP_MUST_PLAYING(errCode)               /
if (m_iStatus != STATUS_PLAY) {                /
  WARN (LOG_APP, “MPlayer is not playing!”); /
  return (errCode);                          /
}

MPlayer::MPlayer()
{
  strcpy (m_strVout, “directx:noaccel”);
  strcpy (m_strAout, “dsound”);
  m_dwMessage       = WM_MFACE;
  m_hMPlayerProcess = INVALID_HANDLE_VALUE;
  m_hPipeRead       = INVALID_HANDLE_VALUE;
  m_hPipeWrite      = INVALID_HANDLE_VALUE;
  m_hNotifyWindow   = INVALID_HANDLE_VALUE;
  m_hDisplayWindow  = INVALID_HANDLE_VALUE;
  m_hWorkingThread  = INVALID_HANDLE_VALUE;
  m_iVolume         = 100;
  m_iVerbose        = VERBOSE_ERR;
  ZeroString (m_strParam);
  ZeroString (m_strMediaPath);
  ZeroString (m_strWorkingPath);
  ResetStatus ();
  DBG (LOG_APP, “MPlayer object created”);
}

MPlayer::~MPlayer()
{
  if (m_iStatus != STATUS_STOP)
  {
    Stop ();
  }
}

void MPlayer::ResetStatus ()
{
  m_iStatus         = STATUS_STOP;
  m_bMute           = false;
  m_lfMediaLength   = 0.0;
  m_iVideoWidth     = 0;
  m_iVideoHeight    = 0;
  m_iPos            = 0;
  m_iAudioBitrate   = 0;
  m_lfFPS           = 0.0;
  m_iMetas          = 0;
  ZeroString (m_strVideoFormat);
  ZeroString (m_strAudioFormat);
  ZeroString (m_strDemuxer);
  ZeroString (m_strVideoCodec);
  ZeroString (m_strAudioCodec);
  ZeroString (m_strVersion);
  ZeroString (m_arryMetas);
}

int MPlayer::Play ()
{
  int ret;
  if (m_iStatus != STATUS_STOP)
  {
    Stop ();
  }
  m_iStatus = STATUS_STARTING;
  ret = CreateMPlayerProcess ();
  if (ret)
  {
    m_iStatus = STATUS_STOP;
    return ret;
  }
  m_hWorkingThread = CreateThread (0, 0, MPlayer::WorkThread, (PVOID)this, 0, 0);
  if (!m_hWorkingThread)
  {
    ERR (LOG_APP, “Failed to create working thread!”);
    Stop ();
    return 1;
  }
  return 0;
}

int MPlayer::Stop ()
{
  if (m_iStatus != STATUS_STOP)
  {
    m_iStatus = STATUS_STOPING;
    Sleep (300); /* wait for work thread quit*/
    SendCommand (”quit”);
    KillMPlayer ();
  }
  else
  {
    WARN (LOG_APP, “Already stopped”);
  }
  return 0;
}

int MPlayer::Pause ()
{
  if (m_iStatus == STATUS_PLAY)
  {
    DBG (LOG_APP, “Pause”);
    SendCommand (”pause”);
    m_iStatus = STATUS_PAUSE;
  }
  else if (m_iStatus == STATUS_PAUSE)
  {
    DBG (LOG_APP, “Continue play”);
    SendCommand (”pause”);
    m_iStatus = STATUS_PLAY;
  }
  return 0;
}

int MPlayer::FullScreen ()
{
  MP_MUST_PLAYING (1);
  SendCommand (”vo_fullscreen”);
  return 0;
}

int MPlayer::GetVolume ()
{
  MP_MUST_PLAYING (0);
  return m_iVolume;
}

int MPlayer::SetVolume (int Vol)
{
  MP_MUST_PLAYING (1);
  char buf[256];
  if (Vol > 100) Vol = 100;
  if (Vol < 0)   Vol = 0;
  m_iVolume = Vol;
  sprintf (buf, “volume %d 1″, Vol);
  SendCommand (buf);
  m_bMute = false;
  return 0;
}

int MPlayer::GetMute ()
{
  MP_MUST_PLAYING (0);
  return m_bMute ? 1 : 0;
}

int MPlayer::SetMute(int Mute)
{
  MP_MUST_PLAYING (1);
  char buf[256];
  sprintf (buf, “mute %d”, Mute?1:0);
  SendCommand (buf);
  m_bMute = Mute ? true : false;
  return 0;
}

int MPlayer::Snapshot ()
{
  MP_MUST_PLAYING (1);
  SendCommand (”screenshot 0″);
  return 0;
}

int MPlayer::GetTitle (char* buf, int nBuf)
{
  MP_MUST_PLAYING (1);
  return 1;
}

int MPlayer::GetAlbum (char* buf, int nBuf)
{
  MP_MUST_PLAYING (1);
  return 1;
}

int MPlayer::GetArtist (char* buf, int nBuf)
{
  MP_MUST_PLAYING (1);
  return 1;
}

int MPlayer::GetComment (char* buf, int nBuf)
{
  MP_MUST_PLAYING (1);
  return 1;
}

int MPlayer::GetGenre (char* buf, int nBuf)
{
  MP_MUST_PLAYING (1);
  return 1;
}

int MPlayer::Seek (int nPos)
{
  MP_MUST_PLAYING (1);
  char buf[256];
  sprintf (buf, “seek %d 2″, nPos);
  SendCommand (buf);
  return 0;
}

void MPlayer::Log (int who, int level, LPCSTR message, int line, const char* file)
{
  char* szWho[3]   = {”MPlayer”, “Input”, “App”};
  char* szLevel[3] = {”Debug”, “Warning”, “Error”};
  if (level >= m_iVerbose)
  {
    printf (”[%s] %s %s L%d: %s/n”, szWho[who%3], szLevel[level%3], file, line, message);
  }
}

int MPlayer::CreateMPlayerProcess()
{
  HANDLE h1, h2;
  SECURITY_ATTRIBUTES sa;
  PROCESS_INFORMATION pi;
  STARTUPINFO         si;
  char param [1024];
  char buf[256];

  DBG (LOG_APP, “Creating MPlayer Process”);
  strcpy (param, m_strMPlayerPath);
  strcat (param, ” /”");

  strcat (param, m_strMediaPath);
  strcat (param, “/” “);

  if (m_hDisplayWindow != INVALID_HANDLE_VALUE)
  {
    sprintf (buf, “-wid %d”, (int)m_hDisplayWindow);
    strcat (param, buf);
    strcat (param, ” “);
  }

  sprintf (buf, “-vo %s -slave -quiet -identify -vf screenshot -ao %s”, m_strVout, m_strAout);
  strcat (param, buf);
  strcat (param, ” “);

  strcat (param, m_strParam);

  ZeroMemory (&sa, sizeof(sa));
  sa.nLength               = sizeof (sa);
  sa.bInheritHandle        = TRUE;

  if (!CreatePipe (&m_hPipeRead, &h1, &sa,0))
  {
    ERR (LOG_APP, “Error createing pipe!”);
    return GetLastError();
  }
  if (!CreatePipe (&h2, &m_hPipeWrite, &sa, 0))
  {
    ERR (LOG_APP, “Error createing pipe!”);
    return GetLastError();
  }

  ZeroMemory (&si, sizeof(si));
  si.dwFlags     = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
  si.wShowWindow = SW_HIDE;
  si.hStdInput   = h2;
  si.hStdOutput  = si.hStdError = h1;

  ZeroMemory (&pi, sizeof(pi));

  if (!CreateProcess (m_strMPlayerPath, param, 0, 0, TRUE, 0, 0,
    *m_strWorkingPath ? m_strWorkingPath : NULL, &si, &pi))
  {
    return GetLastError();
  }
  CloseHandle (h1);
  CloseHandle (h2);
  CloseHandle (pi.hThread);
  m_hMPlayerProcess = pi.hProcess;
  DBG (LOG_APP, “MPlayer Started!”);
  return 0;
}

int MPlayer::CreateSnapshots (LPCSTR szDir, int nInterval, int nCount)
{
  PROCESS_INFORMATION pi;
  STARTUPINFO         si;
  char param [1024];
  char buf[256];
  char curdir[256];

  strcpy (param, m_strMPlayerPath);
  strcpy (curdir, m_strMPlayerPath);
  if(strrchr (curdir, ‘//’))
  {
    *strrchr (curdir, ‘//’) = 0;
  }
  strcat (param, ” /”");
  strcat (param, m_strMediaPath);
  strcat (param, “/” “);

  sprintf (buf, “-ao null -framedrop -frames %d -sstep %d -vo jpeg:outdir=/”%s/” “,
    nCount, nInterval, szDir);
  strcat (param, buf);

  ZeroMemory (&si, sizeof(si));
  si.dwFlags     = STARTF_USESHOWWINDOW;
  si.wShowWindow = SW_HIDE;
  ZeroMemory (&pi, sizeof(pi));

  if (!CreateProcess (m_strMPlayerPath, param,0,0,TRUE,0,0,curdir,&si,&pi))
  {
    return GetLastError();
  }
  DBG (LOG_APP, “MPlayer Started!”);
  CloseHandle (pi.hThread);
  if (WAIT_TIMEOUT == WaitForSingleObject (pi.hProcess, 20000))
  {
    DBG (LOG_APP, “Timeout …Terminate MPlayer!”);
    TerminateProcess (pi.hProcess, 0);
    CloseHandle (pi.hProcess);
    return 1;
  }
  CloseHandle (pi.hProcess);
  DBG (LOG_APP, “Finish Snapshots!”);
  return 0;
}

int MPlayer::SendCommand (LPCSTR szCommand)
{
  DWORD dwWriten;
  char buf[512];

  if (m_iStatus == STATUS_STOP)
  {
    WARN (LOG_APP, “Send command when mplayer is stopped”);
    return 1;
  }
  sprintf (buf, “%s/n”, szCommand);
  DBG (LOG_USER, buf);
  if (!WriteFile (m_hPipeWrite, buf, strlen (buf), &dwWriten, NULL))
  {
    ERR (LOG_APP, “Error Writing Pipe!”);
    KillMPlayer ();
    Notify (1);
    return 1;
  }
  return 0;
}

void MPlayer::KillMPlayer ()
{
  int delay = 1000;
  DWORD ret;

  DBG (LOG_APP, “Try to stop mplayer”);
  ret = WaitForSingleObject (m_hMPlayerProcess, delay);
  if (ret == WAIT_TIMEOUT)
  {
    DBG (LOG_APP, “Terminate mplayer process”);
    TerminateProcess (m_hMPlayerProcess, 0);
  }
  DBG (LOG_APP, “mplayer stopped”);

//  Don’t kill myself
//  DBG (LOG_APP, “Try to stop working thread”);
//  ret = WaitForSingleObject (m_hWorkingThread, delay);
//  if (ret == WAIT_TIMEOUT)
//  {
//    DBG (LOG_APP, “Terminate working thread”);
//    TerminateThread (m_hWorkingThread, 0);
//  }
//  DBG (LOG_APP, “Working thread stopped”);

  CloseHandle (m_hMPlayerProcess);
  CloseHandle (m_hPipeRead);
  CloseHandle (m_hPipeWrite);
  ResetStatus ();
 
}

DWORD WINAPI MPlayer::WorkThread (PVOID pThis)
{
  // just convert static member function to non-static function
  MPlayer* self = (MPlayer*)pThis;
  return self->WorkThreadFunc ();
}

DWORD MPlayer::WorkThreadFunc ()
{
  DBG (LOG_APP, “Work thread start”);
  const int bufSize = 4096;
  const char* pMessage;
  char buf[bufSize + 1] = {0};
  const char seps[]   = “/r/n”;
  DWORD ret = 0, dwPeeked = 0, dwRead = 0;
  DWORD dwTime = 0;
  while (m_iStatus != STATUS_STOPING)
  {
    /* Update current position */
    if (GetTickCount() - dwTime > 500)
    {
      SendCommand (”get_time_pos”);
      dwTime = GetTickCount ();
    }

    ret = PeekNamedPipe (m_hPipeRead, NULL, 0, 0, &dwPeeked, 0);
    if (!ret)
    {
      if (m_iStatus == STATUS_STOPING)
      {
        //Stopping, simply quit
        break;
      }
      ERR (LOG_APP, “Error peeking pipe!”);
      KillMPlayer ();
      Notify (1);
      break;
    }
    if(dwPeeked)
    {
      if (dwPeeked > bufSize)
      {
        dwPeeked = bufSize;
      }
      ret = ReadFile (m_hPipeRead, buf, dwPeeked, &dwRead, 0);
      if(!ret)
      {
        if (m_iStatus == STATUS_STOPING)
        {
          //Stopping, simply quit
          break;
        }
        ERR (LOG_APP, “Error reading pipe!”);
        KillMPlayer ();
        Notify (1);
        break;
      }
      buf [dwRead] = 0;
      // TODO: consider a message not in one buffer
      pMessage = strtok (buf, seps );
      while (pMessage != NULL)
      {
        ProcessMessage (pMessage);
        pMessage = strtok( NULL, seps );
      }
      continue;
    }
    else
    {
      Sleep (100);
    }
  }
  DBG (LOG_APP, “Work thread about to quit”);
  return 0;
}

const char* MPlayer::hasString (const char* szMsg, const char* style)
{
  int n = strlen (style);
  if (strnicmp(szMsg, style, n))
  {
    return NULL;
  }
  else
  {
    return szMsg+n;
  }
}

void MPlayer::ProcessMessage(LPCSTR szMsg)
{
  //DBG (LOG_MPLAYER, szMsg);
  const char* pData;
  if (pData = hasString (szMsg, “MPlayer “))
  {
    DBG (LOG_MPLAYER, szMsg);
    strncpy (m_strVersion, szMsg, sizeof (m_strVersion) - 1);
    return;
  }
  if (pData = hasString (szMsg, “ID_DEMUXER=”))
  {
    DBG (LOG_MPLAYER, szMsg);
    strncpy (m_strDemuxer, pData, sizeof (m_strDemuxer) - 1);
    return;
  }
  if (pData = hasString (szMsg, “ID_VIDEO_FORMAT=”))
  {
    DBG (LOG_MPLAYER, szMsg);
    strncpy (m_strVideoFormat, pData, sizeof (m_strVideoFormat) - 1);
    return;
  }
  if (pData = hasString (szMsg, “ID_VIDEO_CODEC=”))
  {
    DBG (LOG_MPLAYER, szMsg);
    strncpy (m_strVideoCodec, pData, sizeof (m_strVideoCodec) - 1);
    return;
  }
  if (pData = hasString (szMsg, “ID_AUDIO_FORMAT=”))
  {
    DBG (LOG_MPLAYER, szMsg);
    strncpy (m_strAudioFormat, pData, sizeof (m_strAudioFormat) - 1);
    return;
  }
  if (pData = hasString (szMsg, “ID_AUDIO_CODEC=”))
  {
    DBG (LOG_MPLAYER, szMsg);
    strncpy (m_strAudioCodec, pData, sizeof (m_strAudioCodec) - 1);
    return;
  }
  if (pData = hasString (szMsg, “ID_VIDEO_WIDTH=”))
  {
    DBG (LOG_MPLAYER, szMsg);
    m_iVideoWidth = atoi (pData);
    return;
  }
  if (pData = hasString (szMsg, “ID_VIDEO_HEIGHT=”))
  {
    DBG (LOG_MPLAYER, szMsg);
    m_iVideoHeight = atoi (pData);
    return;
  }
  if (pData = hasString (szMsg, “ID_VIDEO_FPS=”))
  {
    DBG (LOG_MPLAYER, szMsg);
    m_lfFPS = atof (pData);
    return;
  }
  if (pData = hasString (szMsg, “ID_AUDIO_BITRATE=”))
  {
    DBG (LOG_MPLAYER, szMsg);
    m_iAudioBitrate = atoi (pData);
    return;
  }
  if (pData = hasString (szMsg, “ID_LENGTH=”))
  {
    DBG (LOG_MPLAYER, szMsg);
    m_lfMediaLength = atof (pData);
    return;
  }
  if (pData = hasString (szMsg, “Starting playback…”))
  {
    DBG (LOG_MPLAYER, szMsg);
    m_iStatus = STATUS_PLAY;
    SetVolume (m_iVolume);
    return;
  }
  if (pData = hasString (szMsg, “ANS_TIME_POSITION=”))
  {
    DBG (LOG_MPLAYER, szMsg);
    m_iPos = atoi (pData);
    return;
  }
  if (pData = hasString (szMsg, “Exiting…”))
  {
    DBG (LOG_MPLAYER, szMsg);
    return;
  }
  if (pData = hasString (szMsg, “ID_CLIP_INFO_NAME”))
  {
    DBG (LOG_MPLAYER, szMsg);
    int n = atoi (pData);
    if (n >= MAX_META)
    {
      WARN (LOG_APP, “Reach max meta count!”);
      return;
    }
    if (m_iMetas <= n)
    {
      m_iMetas = n + 1;
    }
    strncpy (m_arryMetas[n].name, pData+2, META_MAX_NAME_LEN);
    return;
  }
  if (pData = hasString (szMsg, “ID_CLIP_INFO_VALUE”))
  {
    DBG (LOG_MPLAYER, szMsg);
    int n = atoi (pData);
    if (n >= MAX_META)
    {
      WARN (LOG_APP, “Reach max meta count!”);
      return;
    }
    if (m_iMetas <= n)
    {
      m_iMetas = n + 1;
    }
    strncpy (m_arryMetas[n].value, pData+2, META_MAX_VALUE_LEN);
    return;
  }
}

void MPlayer::Notify (int param)
{
  if (m_hNotifyWindow != INVALID_HANDLE_VALUE)
  {
    PostMessage ((HWND)m_hNotifyWindow, m_dwMessage, param, 0);
  }
}
/* test code */
int main (int argc, char** argv)
{
  MPlayer mp;
  mp.SetVerbose(VERBOSE_DBG);
  mp.SetMPlayerPath (”D://Program//MPlayer-1.0rc2//MPlayer.exe”);
  mp.SetMediaPath (”D://cygwin//1.rmvb”);
  mp.Play ();
  DWORD t1 = GetTickCount();
  while (mp.GetStatus() != STATUS_PLAY) Sleep (10);
  printf (”(%d ms) Video [%s] %d x %d/n”, GetTickCount() - t1, mp.GetVideoFormat(), mp.GetVideoWidth(), mp.GetVideoHeight());
  mp.SetVerbose(VERBOSE_ERR);
  while (!_kbhit())
  {
    printf (”Playing: %d/%d/r”, mp.GetPos(), (int)mp.GetMediaLength());
    Sleep (500);
  }
  getch ();
  return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值