win32_specific.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:13k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * win32_specific.c: Win32 specific features
  3.  *****************************************************************************
  4.  * Copyright (C) 2001-2004 the VideoLAN team
  5.  * $Id: a596502a0a5fb3f7c328fc645e74aee592718c65 $
  6.  *
  7.  * Authors: Samuel Hocevar <sam@zoy.org>
  8.  *          Gildas Bazin <gbazin@videolan.org>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  23.  *****************************************************************************/
  24. #ifdef HAVE_CONFIG_H
  25. # include "config.h"
  26. #endif
  27. #define UNICODE
  28. #include <vlc_common.h>
  29. #include "../libvlc.h"
  30. #include <vlc_playlist.h>
  31. #include <vlc_charset.h>
  32. #include "../extras/getopt.h"
  33. #if !defined( UNDER_CE )
  34. #   include <io.h>
  35. #   include <fcntl.h>
  36. #   include  <mmsystem.h>
  37. #endif
  38. #include <winsock.h>
  39. /*****************************************************************************
  40.  * system_Init: initialize winsock and misc other things.
  41.  *****************************************************************************/
  42. void system_Init( libvlc_int_t *p_this, int *pi_argc, const char *ppsz_argv[] )
  43. {
  44.     WSADATA Data;
  45.     /* Get our full path */
  46.     char psz_path[MAX_PATH];
  47.     char *psz_vlc;
  48.     wchar_t psz_wpath[MAX_PATH];
  49.     if( GetModuleFileName( NULL, psz_wpath, MAX_PATH ) )
  50.     {
  51.         WideCharToMultiByte( CP_ACP, 0, psz_wpath, -1,
  52.                              psz_path, MAX_PATH, NULL, NULL );
  53.     }
  54.     else psz_path[0] = '';
  55.     if( (psz_vlc = strrchr( psz_path, '\' )) ) *psz_vlc = '';
  56. #ifndef HAVE_RELEASE
  57.     {
  58.         /* remove trailing .libs from executable dir path if seen,
  59.            we assume we are running vlc through libtool wrapper in build dir */
  60.         int offset  = strlen(psz_path)-sizeof("\.libs")+1;
  61.         if( offset > 0 )
  62.         {
  63.             psz_vlc = psz_path+offset;
  64.             if( ! strcmp(psz_vlc, "\.libs") ) *psz_vlc = '';
  65.         }
  66.     }
  67. #endif
  68.     psz_vlcpath = strdup( psz_path );
  69.     /* Set the default file-translation mode */
  70. #if !defined( UNDER_CE )
  71.     _fmode = _O_BINARY;
  72.     _setmode( _fileno( stdin ), _O_BINARY ); /* Needed for pipes */
  73.     timeBeginPeriod(5);
  74. #endif
  75.     /* Call mdate() once to make sure it is initialized properly */
  76.     mdate();
  77.     /* WinSock Library Init. */
  78.     if( !WSAStartup( MAKEWORD( 2, 2 ), &Data ) )
  79.     {
  80.         /* Aah, pretty useless check, we should always have Winsock 2.2
  81.          * since it appeared in Win98. */
  82.         if( LOBYTE( Data.wVersion ) != 2 || HIBYTE( Data.wVersion ) != 2 )
  83.             /* We could not find a suitable WinSock DLL. */
  84.             WSACleanup( );
  85.         else
  86.             /* Everything went ok. */
  87.             return;
  88.     }
  89.     /* Let's try with WinSock 1.1 */
  90.     if( !WSAStartup( MAKEWORD( 1, 1 ), &Data ) )
  91.     {
  92.         /* Confirm that the WinSock DLL supports 1.1.*/
  93.         if( LOBYTE( Data.wVersion ) != 1 || HIBYTE( Data.wVersion ) != 1 )
  94.             /* We could not find a suitable WinSock DLL. */
  95.             WSACleanup( );
  96.         else
  97.             /* Everything went ok. */
  98.             return;
  99.     }
  100.     fprintf( stderr, "error: can't initialize WinSocksn" );
  101. }
  102. /*****************************************************************************
  103.  * system_Configure: check for system specific configuration options.
  104.  *****************************************************************************/
  105. static unsigned __stdcall IPCHelperThread( void * );
  106. LRESULT CALLBACK WMCOPYWNDPROC( HWND, UINT, WPARAM, LPARAM );
  107. static vlc_object_t *p_helper = NULL;
  108. static unsigned long hIPCHelper;
  109. static HANDLE hIPCHelperReady;
  110. typedef struct
  111. {
  112.   int argc;
  113.   int enqueue;
  114.   char data[];
  115. } vlc_ipc_data_t;
  116. void system_Configure( libvlc_int_t *p_this, int *pi_argc, const char *ppsz_argv[] )
  117. {
  118. #if !defined( UNDER_CE )
  119.     /* Raise default priority of the current process */
  120. #ifndef ABOVE_NORMAL_PRIORITY_CLASS
  121. #   define ABOVE_NORMAL_PRIORITY_CLASS 0x00008000
  122. #endif
  123.     if( config_GetInt( p_this, "high-priority" ) )
  124.     {
  125.         if( SetPriorityClass( GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS )
  126.              || SetPriorityClass( GetCurrentProcess(), HIGH_PRIORITY_CLASS ) )
  127.         {
  128.             msg_Dbg( p_this, "raised process priority" );
  129.         }
  130.         else
  131.         {
  132.             msg_Dbg( p_this, "could not raise process priority" );
  133.         }
  134.     }
  135.     if( config_GetInt( p_this, "one-instance" )
  136.         || ( config_GetInt( p_this, "one-instance-when-started-from-file" )
  137.              && config_GetInt( p_this, "started-from-file" ) ) )
  138.     {
  139.         HANDLE hmutex;
  140.         msg_Info( p_this, "one instance mode ENABLED");
  141.         /* Use a named mutex to check if another instance is already running */
  142.         if( !( hmutex = CreateMutex( 0, TRUE, L"VLC ipc "VERSION ) ) )
  143.         {
  144.             /* Failed for some reason. Just ignore the option and go on as
  145.              * normal. */
  146.             msg_Err( p_this, "one instance mode DISABLED "
  147.                      "(mutex couldn't be created)" );
  148.             return;
  149.         }
  150.         if( GetLastError() != ERROR_ALREADY_EXISTS )
  151.         {
  152.             /* We are the 1st instance. */
  153.             static const char typename[] = "ipc helper";
  154.             p_helper =
  155.                 vlc_custom_create( p_this, sizeof(vlc_object_t),
  156.                                    VLC_OBJECT_GENERIC, typename );
  157.             /* Run the helper thread */
  158.             hIPCHelperReady = CreateEvent( NULL, FALSE, FALSE, NULL );
  159.             hIPCHelper = _beginthreadex( NULL, 0, IPCHelperThread, p_helper,
  160.                                          0, NULL );
  161.             if( hIPCHelper )
  162.                 WaitForSingleObject( hIPCHelperReady, INFINITE );
  163.             else
  164.             {
  165.                 msg_Err( p_this, "one instance mode DISABLED "
  166.                          "(IPC helper thread couldn't be created)" );
  167.                 vlc_object_release (p_helper);
  168.                 p_helper = NULL;
  169.             }
  170.             vlc_object_attach (p_helper, p_this);
  171.             CloseHandle( hIPCHelperReady );
  172.             /* Initialization done.
  173.              * Release the mutex to unblock other instances */
  174.             ReleaseMutex( hmutex );
  175.         }
  176.         else
  177.         {
  178.             /* Another instance is running */
  179.             HWND ipcwindow;
  180.             /* Wait until the 1st instance is initialized */
  181.             WaitForSingleObject( hmutex, INFINITE );
  182.             /* Locate the window created by the IPC helper thread of the
  183.              * 1st instance */
  184.             if( !( ipcwindow = FindWindow( 0, L"VLC ipc "VERSION ) ) )
  185.             {
  186.                 msg_Err( p_this, "one instance mode DISABLED "
  187.                          "(couldn't find 1st instance of program)" );
  188.                 ReleaseMutex( hmutex );
  189.                 return;
  190.             }
  191.             /* We assume that the remaining parameters are filenames
  192.              * and their input options */
  193.             if( *pi_argc - 1 >= optind )
  194.             {
  195.                 COPYDATASTRUCT wm_data;
  196.                 int i_opt;
  197.                 vlc_ipc_data_t *p_data;
  198.                 size_t i_data = sizeof (*p_data);
  199.                 for( i_opt = optind; i_opt < *pi_argc; i_opt++ )
  200.                 {
  201.                     i_data += sizeof (size_t);
  202.                     i_data += strlen( ppsz_argv[ i_opt ] ) + 1;
  203.                 }
  204.                 p_data = malloc( i_data );
  205.                 p_data->argc = *pi_argc - optind;
  206.                 p_data->enqueue = config_GetInt( p_this, "playlist-enqueue" );
  207.                 i_data = 0;
  208.                 for( i_opt = optind; i_opt < *pi_argc; i_opt++ )
  209.                 {
  210.                     size_t i_len = strlen( ppsz_argv[ i_opt ] ) + 1;
  211.                     /* Windows will never switch to an architecture
  212.                      * with stronger alignment requirements, right. */
  213.                     *((size_t *)(p_data->data + i_data)) = i_len;
  214.                     i_data += sizeof (size_t);
  215.                     memcpy( &p_data->data[i_data], ppsz_argv[ i_opt ], i_len );
  216.                     i_data += i_len;
  217.                 }
  218.                 i_data += sizeof (*p_data);
  219.                 /* Send our playlist items to the 1st instance */
  220.                 wm_data.dwData = 0;
  221.                 wm_data.cbData = i_data;
  222.                 wm_data.lpData = p_data;
  223.                 SendMessage( ipcwindow, WM_COPYDATA, 0, (LPARAM)&wm_data );
  224.             }
  225.             /* Initialization done.
  226.              * Release the mutex to unblock other instances */
  227.             ReleaseMutex( hmutex );
  228.             /* Bye bye */
  229.             system_End( p_this );
  230.             exit( 0 );
  231.         }
  232.     }
  233. #endif
  234. }
  235. static unsigned __stdcall IPCHelperThread( void *data )
  236. {
  237.     vlc_object_t *p_this = data;
  238.     HWND ipcwindow;
  239.     MSG message;
  240.     ipcwindow =
  241.         CreateWindow( L"STATIC",                     /* name of window class */
  242.                   L"VLC ipc "VERSION,               /* window title bar text */
  243.                   0,                                         /* window style */
  244.                   0,                                 /* default X coordinate */
  245.                   0,                                 /* default Y coordinate */
  246.                   0,                                         /* window width */
  247.                   0,                                        /* window height */
  248.                   NULL,                                  /* no parent window */
  249.                   NULL,                            /* no menu in this window */
  250.                   GetModuleHandle(NULL),  /* handle of this program instance */
  251.                   NULL );                               /* sent to WM_CREATE */
  252.     SetWindowLongPtr( ipcwindow, GWLP_WNDPROC, (LRESULT)WMCOPYWNDPROC );
  253.     SetWindowLongPtr( ipcwindow, GWLP_USERDATA, (LONG_PTR)p_this );
  254.     /* Signal the creation of the thread and events queue */
  255.     SetEvent( hIPCHelperReady );
  256.     while( GetMessage( &message, NULL, 0, 0 ) )
  257.     {
  258.         TranslateMessage( &message );
  259.         DispatchMessage( &message );
  260.     }
  261.     return 0;
  262. }
  263. LRESULT CALLBACK WMCOPYWNDPROC( HWND hwnd, UINT uMsg, WPARAM wParam,
  264.                                 LPARAM lParam )
  265. {
  266.     if( uMsg == WM_COPYDATA )
  267.     {
  268.         COPYDATASTRUCT *pwm_data = (COPYDATASTRUCT*)lParam;
  269.         vlc_object_t *p_this;
  270.         playlist_t *p_playlist;
  271.         p_this = (vlc_object_t *)
  272.             (uintptr_t)GetWindowLongPtr( hwnd, GWLP_USERDATA );
  273.         if( !p_this ) return 0;
  274.         /* Add files to the playlist */
  275.         p_playlist = pl_Hold( p_this );
  276.         if( !p_playlist ) return 0;
  277.         if( pwm_data->lpData )
  278.         {
  279.             char **ppsz_argv;
  280.             vlc_ipc_data_t *p_data = (vlc_ipc_data_t *)pwm_data->lpData;
  281.             size_t i_data = 0;
  282.             int i_argc = p_data->argc, i_opt, i_options;
  283.             ppsz_argv = (char **)malloc( i_argc * sizeof(char *) );
  284.             for( i_opt = 0; i_opt < i_argc; i_opt++ )
  285.             {
  286.                 ppsz_argv[i_opt] = p_data->data + i_data + sizeof(int);
  287.                 i_data += sizeof(int) + *((int *)(p_data->data + i_data));
  288.             }
  289.             for( i_opt = 0; i_opt < i_argc; i_opt++ )
  290.             {
  291.                 i_options = 0;
  292.                 /* Count the input options */
  293.                 while( i_opt + i_options + 1 < i_argc &&
  294.                        *ppsz_argv[ i_opt + i_options + 1 ] == ':' )
  295.                 {
  296.                     i_options++;
  297.                 }
  298.                 playlist_AddExt( p_playlist, ppsz_argv[i_opt],
  299.                   NULL, PLAYLIST_APPEND |
  300.                         ( ( i_opt || p_data->enqueue ) ? 0 : PLAYLIST_GO ),
  301.                   PLAYLIST_END, -1,
  302.                   i_options,
  303.                   (char const **)( i_options ? &ppsz_argv[i_opt+1] : NULL ),
  304.                   VLC_INPUT_OPTION_TRUSTED,
  305.                   true, pl_Unlocked );
  306.                 i_opt += i_options;
  307.             }
  308.             free( ppsz_argv );
  309.         }
  310.         vlc_object_release( p_playlist );
  311.     }
  312.     return DefWindowProc( hwnd, uMsg, wParam, lParam );
  313. }
  314. /*****************************************************************************
  315.  * system_End: terminate winsock.
  316.  *****************************************************************************/
  317. void system_End( libvlc_int_t *p_this )
  318. {
  319.     HWND ipcwindow;
  320.     if( p_this )
  321.     {
  322.         free( psz_vlcpath );
  323.         psz_vlcpath = NULL;
  324.     }
  325.     if( ( ipcwindow = FindWindow( 0, L"VLC ipc "VERSION ) ) != 0 )
  326.     {
  327.         SendMessage( ipcwindow, WM_QUIT, 0, 0 );
  328.     }
  329.     if (p_helper && p_helper->p_parent == VLC_OBJECT(p_this) )
  330.     {
  331.         /* FIXME: thread-safety... */
  332.         vlc_object_detach (p_helper);
  333.         vlc_object_release (p_helper);
  334.         p_helper = NULL;
  335.     }
  336. #if !defined( UNDER_CE )
  337.     timeEndPeriod(5);
  338. #endif
  339.     WSACleanup();
  340. }