[MPlayer-cygwin] slave mode + windows frontend

Anton Ragnarsson anton at infeline.org
Tue Apr 25 11:25:53 CEST 2006


On Apr 25, 2006, at 10:17, Rémy Bertot wrote:

> Hi,
>
> I'm currently trying to use mplayer in slave mode in order to build  
> a windows frontend. I don't manage to make the basis of this  
> frontend to work (basicly the stuff that CreatProcess and  
> CreatePipe, then link the stdin/stdout of Mplayer and the console),  
> since the commands i'm sending to mplayer (even if it's well  
> displayed on stdout) don't seem to be received by mplayer.
>
> While looking for a solution, I realised that the slave mode was  
> not working under 'cmd' but just with msys. When I launch mplayer  
> from the classic DOS cmd, the video is working, but the commands I  
> type in the shell don't work. In fact the strings (like 'pause\n')  
> seems to be stored only in the cmd buffer, since they appear right  
> after the prompt when I quit mplayer.
>
> I tried this under the last precompiled version of mplayer, and one  
> that I compiled myself. Is that normal, or did I skip something  
> during the compilation or in the command line (mplayer.exe -slave - 
> idle -quiet mymovie.avi)? Does it affect the program I'm writting  
> or is it something different? Here is the source code of the small  
> app (hugely inspired by createprocess tutorials), if it helps.
>
> Thanks a lot!
> RB

I've got working code for this.
And it looks pretty much like yours (guess we both got it from MSDN).
However, there are some differences, like DuplicateHandle() and stuff.

Anyway, here's my code to launch mplayer:
(_pCmd is the both mplayer.exe and the argument list)

	bool Launch(char* _pCmd)
	{
		SECURITY_ATTRIBUTES saAttr;
		saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
		saAttr.bInheritHandle = TRUE;
		saAttr.lpSecurityDescriptor = NULL;

		// Create handle for reading parent <- child
		HANDLE hChildStdoutRd, hChildStdoutWr, hChildStdoutRdDup;
		if (!::CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0))
			return false;
		if (!::DuplicateHandle(::GetCurrentProcess(), hChildStdoutRd,
		                       ::GetCurrentProcess(), &hChildStdoutRdDup,
		                       0, FALSE, DUPLICATE_SAME_ACCESS))
			return false;
		::CloseHandle(hChildStdoutRd);

		// Create handle for writing parent -> child
		HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup;
		if (!::CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0))
			return false;
	 	if (!::DuplicateHandle(::GetCurrentProcess(), hChildStdinWr,
		                       ::GetCurrentProcess(), &hChildStdinWrDup,
		                       0, FALSE, DUPLICATE_SAME_ACCESS))
			return false;
		::CloseHandle(hChildStdinWr);

		// Create process
		PROCESS_INFORMATION piProcInfo;
		STARTUPINFO siStartInfo;
		ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
		ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
		siStartInfo.cb = sizeof(STARTUPINFO);
		siStartInfo.hStdError = hChildStdoutWr;
		siStartInfo.hStdOutput = hChildStdoutWr;
		siStartInfo.hStdInput = hChildStdinRd;
		siStartInfo.dwFlags |= STARTF_USESTDHANDLES;

		BOOL bFuncRetn = ::CreateProcess(NULL,
			_pCmd, NULL, NULL, TRUE,
			CREATE_NO_WINDOW,
			NULL, NULL, &siStartInfo, &piProcInfo);

		if (bFuncRetn == 0)
			return false;

		::CloseHandle(piProcInfo.hThread);

		m_hMPlayer = piProcInfo.hProcess;
		m_hMPlayerInput = hChildStdinWrDup;
		m_hMPlayerOutput = hChildStdoutRdDup;

		::SetPriorityClass(m_hMPlayer, ABOVE_NORMAL_PRIORITY_CLASS);

		Thread::Start();
		m_bStarted = true;
		return true;
	}

to send mplayer commands:

	bool SendCommand(const char* _pCommand)
	{
		if (IsRunning())
		{
			char buf[100];
			snprintf(buf, 100, "%s\n", _pCommand);
			ulong n, len = strlen(buf);
			return (::WriteFile(m_hMPlayerInput, buf, len, &n, NULL) != 0);
		}
		return false;
	}

and to read mplayer output:
(very stupid, reads a character at a time. but it works)

	static bool ReadLine(HANDLE hFile, char* buf, int size)
	{
		ulong nRead;
		int i;
		for (i=0; i<(size-2); i++)
		{
			if (!::ReadFile(hFile, buf+i, 1, &nRead, NULL) || !nRead)
				return false;

			if (buf[i] == '\r' || buf[i] == '\n')
				break;
		}
		buf[i+1] = 0;
		return true;
	}


Good luck,
anton





>
> //----------- START ------------
> #include <windows.h>
> #include <stdio.h>
> #include <conio.h>
> #include <string.h>
> #pragma hdrstop
>
> void ErrorMessage(char *str)  //display detailed error info
> {
>  LPVOID msg;
>  FormatMessage(
>    FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
>    NULL,
>    GetLastError(),
>    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
>    (LPTSTR) &msg,
>    0,
>    NULL
>  );
>  printf("%s: %s\n",str,msg);
>  LocalFree(msg);
> }
>
> #define INFO_BUFFER_SIZE 32767
> #define bzero(a) memset(a,0,sizeof(a)) //easier -- shortcut
>
> int main(VOID)
> {
>  char buf[1024];                           //i/o buffer
>  STARTUPINFO si;
>  SECURITY_ATTRIBUTES sa;
>  SECURITY_DESCRIPTOR sd;               //security information for  
> pipes
>  PROCESS_INFORMATION pi;
>  HANDLE newstdin,newstdout,read_stdout,write_stdin;  //pipe handles
>
>  ZeroMemory( &si, sizeof(si) );
>  si.cb = sizeof(si);
>  ZeroMemory( &pi, sizeof(pi) );
>
>  sa.lpSecurityDescriptor = NULL;
>  sa.nLength = sizeof(SECURITY_ATTRIBUTES);
>  sa.bInheritHandle = true;         //allow inheritable handles
>
>  if (!CreatePipe(&newstdin,&write_stdin,&sa,0))   //create stdin pipe
>  {
>    ErrorMessage("CreatePipe");
>    getch();
>    return 0;
>  }
>  if (!CreatePipe(&read_stdout,&newstdout,&sa,0))  //create stdout pipe
>  {
>    ErrorMessage("CreatePipe");
>    getch();
>    CloseHandle(newstdin);
>    CloseHandle(write_stdin);
>    return 0;
>  }
>
>  GetStartupInfo(&si);      //set startupinfo for the spawned process
>
> /*
> *  The dwFlags member tells CreateProcess how to make the process.
> *  STARTF_USESTDHANDLES validates the hStd* members.  
> STARTF_USESHOWWINDOW
> *  validates the wShowWindow member.
> */
>  si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
>  si.wShowWindow = SW_HIDE;
>  si.hStdOutput = newstdout;
>  si.hStdError = newstdout;     //set the new handles for the child  
> process
>  si.hStdInput = newstdin;
>  //char app_args[] = "";
>  //char app_spawn[] = "C:\\WINDOWS\\system32\\cmd.exe";
>  char app_spawn[] = "D:\\Prog\\v0\\mplayer\\mplayer.exe";
>  char app_args[] = "-slave -idle -quiet D:\\Prog\\MediaRythmo\\v0\ 
> \0004.avi";
>  //spawn the child process
>  if (!CreateProcess(app_spawn,app_args,NULL,NULL,TRUE, 
> 0,NULL,NULL,&si,&pi))
>  {
>    ErrorMessage("CreateProcess");
>    getch();
>    CloseHandle(newstdin);
>    CloseHandle(newstdout);
>    CloseHandle(read_stdout);
>    CloseHandle(write_stdin);
>    return 0;
>  }
>
>  unsigned long exit=0;  //process exit code
>  unsigned long bread;   //bytes read
>  unsigned long avail;   //bytes available
>
>  bzero(buf);
>  for(;;)      //main program loop
>  {
>    GetExitCodeProcess(pi.hProcess,&exit);      //while the process  
> is running
>    if (exit != STILL_ACTIVE)
>      break;
>    PeekNamedPipe(read_stdout,buf,1023,&bread,&avail,NULL);
>    //check to see if there is any data to read from stdout
>    if (bread != 0)
>    {
>      bzero(buf);
>      if (avail > 1023)
>      {
>        while (bread >= 1023)
>        {
>          ReadFile(read_stdout,buf,1023,&bread,NULL);  //read the  
> stdout pipe
>          printf("%s",buf);
>          bzero(buf);
>        }
>      }
>      else {
>        ReadFile(read_stdout,buf,1023,&bread,NULL);
>        printf("%s",buf);
>      }
>    }
>    if (kbhit())      //check for user input.
>    {
>      bzero(buf);
>      *buf = (char)getche();
>      //printf("%c",*buf);
>      WriteFile(write_stdin,buf,1,&bread,NULL); //send it to stdin
>      if (*buf == '\r') {
>        *buf = '\n';
>        printf("%c",*buf);
>        WriteFile(write_stdin,buf,1,&bread,NULL); //send an extra  
> newline char,
>                                                  //if necessary
>      }
>    }
>  }
>
>  // Close process and thread handles.
>  CloseHandle( pi.hProcess );
>  CloseHandle( pi.hThread );
>  CloseHandle(newstdin);            //clean stuff up
>  CloseHandle(newstdout);
>  CloseHandle(read_stdout);
>  CloseHandle(write_stdin);
> }
>
> //----------- STOP -------------
>
>
>
> _______________________________________________
> MPlayer-cygwin mailing list
> MPlayer-cygwin at mplayerhq.hu
> http://mplayerhq.hu/mailman/listinfo/mplayer-cygwin




More information about the MPlayer-cygwin mailing list