]> git.sesse.net Git - vlc/blob - src/os2/specific.c
omxil: factorize FreeBuffers and AllocateBuffers
[vlc] / src / os2 / specific.c
1 /*****************************************************************************
2  * specific.c: OS/2 specific features
3  *****************************************************************************
4  * Copyright (C) 2010 KO Myung-Hun
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2.1 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19  *****************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
24
25 #include <vlc_common.h>
26 #include "../libvlc.h"
27 #include <vlc_playlist.h>
28 #include <vlc_interface.h>
29 #include <vlc_url.h>
30
31 #include <fcntl.h>
32 #include <io.h>
33
34 #define VLC_IPC_PIPE "\\PIPE\\VLC\\IPC\\"VERSION
35
36 #define IPC_CMD_GO      0x00
37 #define IPC_CMD_ENQUEUE 0x01
38 #define IPC_CMD_QUIT    0xFF
39
40 extern int _fmode_bin;
41
42 static HPIPE hpipeIPC     = NULLHANDLE;
43 static int   tidIPCFirst  = -1;
44 static int   tidIPCHelper = -1;
45
46 static void IPCHelperThread( void *arg )
47 {
48     libvlc_int_t *libvlc = arg;
49
50     ULONG  ulCmd;
51     int    i_argc;
52     char **ppsz_argv;
53     size_t i_len;
54     ULONG  cbActual;
55     int    i_options;
56
57     /* Add files to the playlist */
58     playlist_t *p_playlist;
59
60     do
61     {
62         DosConnectNPipe( hpipeIPC );
63
64         /* Read command */
65         DosRead( hpipeIPC, &ulCmd, sizeof( ulCmd ), &cbActual );
66         if( ulCmd == IPC_CMD_QUIT )
67             continue;
68
69         /* Read a count of arguments */
70         DosRead( hpipeIPC, &i_argc, sizeof( i_argc ), &cbActual );
71
72         ppsz_argv = malloc( i_argc * sizeof( *ppsz_argv ));
73
74         for( int i_opt = 0; i_opt < i_argc; i_opt++ )
75         {
76             /* Read a length of argv */
77             DosRead( hpipeIPC, &i_len, sizeof( i_len ), &cbActual );
78
79             ppsz_argv[ i_opt ] = malloc( i_len );
80
81             /* Read argv */
82             DosRead( hpipeIPC, ppsz_argv[ i_opt ], i_len, &cbActual );
83         }
84
85         p_playlist = libvlc_priv(libvlc)->playlist;
86
87         for( int i_opt = 0; i_opt < i_argc;)
88         {
89             i_options = 0;
90
91             /* Count the input options */
92             while( i_opt + i_options + 1 < i_argc &&
93                    *ppsz_argv[ i_opt + i_options + 1 ] == ':' )
94                 i_options++;
95
96
97             if( p_playlist )
98             {
99                 playlist_AddExt( p_playlist, ppsz_argv[ i_opt ], NULL,
100                                  PLAYLIST_APPEND |
101                                  (( i_opt || ulCmd == IPC_CMD_ENQUEUE ) ?
102                                      0 : PLAYLIST_GO ),
103                                  PLAYLIST_END, -1, i_options,
104                                  ( char const ** )
105                                      ( i_options ? &ppsz_argv[ i_opt + 1 ] :
106                                                    NULL ),
107                                  VLC_INPUT_OPTION_TRUSTED,
108                                  true, pl_Unlocked );
109             }
110
111             for( ; i_options >= 0; i_options-- )
112                 free( ppsz_argv[ i_opt++ ]);
113         }
114
115         free( ppsz_argv );
116     } while( !DosDisConnectNPipe( hpipeIPC ) && ulCmd != IPC_CMD_QUIT );
117
118     DosClose( hpipeIPC );
119     hpipeIPC = NULLHANDLE;
120
121     tidIPCFirst  = -1;
122     tidIPCHelper = -1;
123 }
124
125 void system_Init( void )
126 {
127     /* Set the default file-translation mode */
128     _fmode_bin = 1;
129     setmode( fileno( stdin ), O_BINARY ); /* Needed for pipes */
130 }
131
132 void system_Configure( libvlc_int_t *p_this, int i_argc, const char *const ppsz_argv[] )
133 {
134     if( var_InheritBool( p_this, "high-priority" ) )
135     {
136         if( !DosSetPriority( PRTYS_PROCESS, PRTYC_REGULAR, PRTYD_MAXIMUM, 0 ) )
137         {
138             msg_Dbg( p_this, "raised process priority" );
139         }
140         else
141         {
142             msg_Dbg( p_this, "could not raise process priority" );
143         }
144     }
145
146     if( var_InheritBool( p_this, "one-instance" )
147         || ( var_InheritBool( p_this, "one-instance-when-started-from-file" )
148              && var_InheritBool( p_this, "started-from-file" ) ) )
149     {
150         HPIPE hpipe;
151         ULONG ulAction;
152         ULONG rc;
153
154         msg_Info( p_this, "one instance mode ENABLED");
155
156         /* Use a named pipe to check if another instance is already running */
157         for(;;)
158         {
159             rc = DosOpen( VLC_IPC_PIPE, &hpipe, &ulAction, 0, 0,
160                           OPEN_ACTION_OPEN_IF_EXISTS,
161                           OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE |
162                           OPEN_FLAGS_FAIL_ON_ERROR,
163                           NULL );
164
165             if( rc == ERROR_PIPE_BUSY )
166                 DosWaitNPipe( VLC_IPC_PIPE, -1 );
167             else
168                 break;
169         }
170
171         if( rc )
172         {
173             rc = DosCreateNPipe( VLC_IPC_PIPE,  &hpipeIPC,
174                                  NP_ACCESS_DUPLEX,
175                                  NP_WAIT | NP_TYPE_MESSAGE |
176                                  NP_READMODE_MESSAGE | 0x01,
177                                  32768, 32768, 0 );
178             if( rc )
179             {
180                 /* Failed to create a named pipe. Just ignore the option and
181                  * go on as normal. */
182                 msg_Err( p_this, "one instance mode DISABLED "
183                          "(a named pipe couldn't be created)" );
184                 return;
185             }
186
187             /* We are the 1st instance. */
188
189             /* Save the tid of the first instance */
190             tidIPCFirst = _gettid();
191
192             /* Run the helper thread */
193             tidIPCHelper = _beginthread( IPCHelperThread, NULL, 1024 * 1024,
194                                          p_this );
195             if( tidIPCHelper == -1 )
196             {
197                 msg_Err( p_this, "one instance mode DISABLED "
198                          "(IPC helper thread couldn't be created)");
199
200                 tidIPCFirst = -1;
201             }
202         }
203         else
204         {
205             /* Another instance is running */
206             ULONG ulCmd = var_InheritBool( p_this, "playlist-enqueue") ?
207                               IPC_CMD_ENQUEUE : IPC_CMD_GO;
208             ULONG cbActual;
209
210             /* Write a command */
211             DosWrite( hpipe, &ulCmd, sizeof( ulCmd ), &cbActual );
212
213             /* We assume that the remaining parameters are filenames
214              * and their input options */
215
216             /* Write a count of arguments */
217             DosWrite( hpipe, &i_argc, sizeof( i_argc ), &cbActual );
218
219             for( int i_opt = 0; i_opt < i_argc; i_opt++ )
220             {
221                 /* We need to resolve relative paths in this instance */
222                 char *mrl;
223                 if( strstr( ppsz_argv[ i_opt ], "://" ))
224                     mrl = strdup( ppsz_argv[ i_opt ] );
225                 else
226                     mrl = vlc_path2uri( ppsz_argv[ i_opt ], NULL );
227
228                 if( !mrl )
229                     mrl = ( char * )ppsz_argv[ i_opt ];
230
231                 size_t i_len = strlen( mrl ) + 1;
232
233                 /* Write a length of an argument */
234                 DosWrite( hpipe, &i_len, sizeof( i_len ), &cbActual );
235
236                 /* Write an argument */
237                 DosWrite( hpipe, mrl, i_len, &cbActual );
238
239                 if( mrl != ppsz_argv[ i_opt ])
240                     free( mrl );
241             }
242
243             /* Close a named pipe of a client side */
244             DosClose( hpipe );
245
246             /* Bye bye */
247             system_End();
248             exit( 0 );
249         }
250     }
251 }
252
253 /**
254  * Cleans up after system_Init() and system_Configure().
255  */
256 void system_End(void)
257 {
258     if( tidIPCFirst == _gettid())
259     {
260         HPIPE hpipe;
261         ULONG ulAction;
262         ULONG cbActual;
263         ULONG rc;
264
265         do
266         {
267             rc = DosOpen( VLC_IPC_PIPE, &hpipe, &ulAction, 0, 0,
268                           OPEN_ACTION_OPEN_IF_EXISTS,
269                           OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE |
270                           OPEN_FLAGS_FAIL_ON_ERROR,
271                           NULL );
272
273             if( rc == ERROR_PIPE_BUSY )
274                 DosWaitNPipe( VLC_IPC_PIPE, -1 );
275             else if( rc )
276                 DosSleep( 1 );
277         } while( rc );
278
279         /* Ask for IPCHelper to quit */
280         ULONG ulCmd = IPC_CMD_QUIT;
281         DosWrite( hpipe, &ulCmd, sizeof( ulCmd ), &cbActual );
282
283         DosClose( hpipe );
284
285         TID tid = tidIPCHelper;
286         DosWaitThread( &tid, DCWW_WAIT );
287     }
288 }
289