00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00032
00033
00034
00035 #include <stdlib.h>
00036 #include <stdio.h>
00037 #include <string.h>
00038
00039 #include <vlc/vlc.h>
00040 #include <vlc/input.h>
00041
00042 #include "audio_output.h"
00043
00044 #include "vlc_interface.h"
00045 #include "vlc_video.h"
00046 #include "video_output.h"
00047
00048 #ifdef SYS_DARWIN
00049 # include "Cocoa/Cocoa.h"
00050 #endif
00051
00052
00053
00054
00055 static void Manager( intf_thread_t *p_intf );
00056 static void RunInterface( intf_thread_t *p_intf );
00057
00058 static int SwitchIntfCallback( vlc_object_t *, char const *,
00059 vlc_value_t , vlc_value_t , void * );
00060 static int AddIntfCallback( vlc_object_t *, char const *,
00061 vlc_value_t , vlc_value_t , void * );
00062
00063 #ifdef SYS_DARWIN
00064
00065
00066
00067 @interface VLCApplication : NSApplication
00068 {
00069 }
00070
00071 @end
00072 #endif
00073
00074
00075
00076
00077
00078
00079
00087 intf_thread_t* __intf_Create( vlc_object_t *p_this, const char *psz_module )
00088 {
00089 intf_thread_t * p_intf;
00090
00091
00092 p_intf = vlc_object_create( p_this, VLC_OBJECT_INTF );
00093 if( !p_intf )
00094 {
00095 msg_Err( p_this, "out of memory" );
00096 return NULL;
00097 }
00098 p_intf->pf_request_window = NULL;
00099 p_intf->pf_release_window = NULL;
00100 p_intf->pf_control_window = NULL;
00101 p_intf->b_play = VLC_FALSE;
00102
00103
00104 p_intf->p_module = module_Need( p_intf, "interface", psz_module, 0 );
00105
00106 if( p_intf->p_module == NULL )
00107 {
00108 msg_Err( p_intf, "no suitable intf module" );
00109 vlc_object_destroy( p_intf );
00110 return NULL;
00111 }
00112
00113
00114 p_intf->b_menu = VLC_FALSE;
00115 p_intf->b_menu_change = VLC_FALSE;
00116
00117
00118 vlc_mutex_init( p_intf, &p_intf->change_lock );
00119
00120 msg_Dbg( p_intf, "interface initialized" );
00121
00122
00123 vlc_object_attach( p_intf, p_this );
00124
00125 return p_intf;
00126 }
00127
00128
00129
00130
00131
00132
00133
00142 int intf_RunThread( intf_thread_t *p_intf )
00143 {
00144 #ifdef SYS_DARWIN
00145 NSAutoreleasePool * o_pool;
00146
00147 if( p_intf->b_block )
00148 {
00149
00150
00151 if( vlc_thread_create( p_intf, "manager", Manager,
00152 VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) )
00153 {
00154 msg_Err( p_intf, "cannot spawn manager thread" );
00155 return VLC_EGENERIC;
00156 }
00157 }
00158
00159 if( p_intf->b_block && strncmp( p_intf->p_module->psz_object_name,
00160 "clivlc", 6) )
00161 {
00162 o_pool = [[NSAutoreleasePool alloc] init];
00163 [VLCApplication sharedApplication];
00164 }
00165
00166 if( p_intf->b_block &&
00167 ( !strncmp( p_intf->p_module->psz_object_name, "macosx" , 6 ) ||
00168 !strncmp( p_intf->p_vlc->psz_object_name, "clivlc", 6 ) ) )
00169 {
00170
00171 RunInterface( p_intf );
00172 p_intf->b_die = VLC_TRUE;
00173 }
00174 else
00175 {
00176
00177 if( vlc_thread_create( p_intf, "interface", RunInterface,
00178 VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) )
00179 {
00180 msg_Err( p_intf, "cannot spawn interface thread" );
00181 return VLC_EGENERIC;
00182 }
00183
00184 if( p_intf->b_block )
00185 {
00186
00187 [NSApp run];
00188 p_intf->b_die = VLC_TRUE;
00189 }
00190 }
00191 #else
00192 if( p_intf->b_block )
00193 {
00194
00195 if( vlc_thread_create( p_intf, "manager", Manager,
00196 VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) )
00197 {
00198 msg_Err( p_intf, "cannot spawn manager thread" );
00199 return VLC_EGENERIC;
00200 }
00201
00202 RunInterface( p_intf );
00203
00204 p_intf->b_die = VLC_TRUE;
00205
00206 }
00207 else
00208 {
00209
00210 if( vlc_thread_create( p_intf, "interface", RunInterface,
00211 VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) )
00212 {
00213 msg_Err( p_intf, "cannot spawn interface thread" );
00214 return VLC_EGENERIC;
00215 }
00216 }
00217 #endif
00218
00219 return VLC_SUCCESS;
00220 }
00221
00229 void intf_StopThread( intf_thread_t *p_intf )
00230 {
00231
00232 if( !p_intf->b_block )
00233 {
00234 p_intf->b_die = VLC_TRUE;
00235 }
00236
00237
00238 vlc_thread_join( p_intf );
00239 }
00240
00248 void intf_Destroy( intf_thread_t *p_intf )
00249 {
00250
00251 if( p_intf->p_module )
00252 {
00253 module_Unneed( p_intf, p_intf->p_module );
00254 }
00255
00256 vlc_mutex_destroy( &p_intf->change_lock );
00257
00258
00259 vlc_object_destroy( p_intf );
00260 }
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00284 static void Manager( intf_thread_t *p_intf )
00285 {
00286 while( !p_intf->b_die )
00287 {
00288 msleep( INTF_IDLE_SLEEP );
00289
00290 if( p_intf->p_vlc->b_die )
00291 {
00292 p_intf->b_die = VLC_TRUE;
00293 #ifdef SYS_DARWIN
00294 if( strncmp( p_intf->p_vlc->psz_object_name, "clivlc", 6 ) )
00295 {
00296 [NSApp stop: NULL];
00297 }
00298 #endif
00299 return;
00300 }
00301 }
00302 }
00303
00304
00305
00306
00307 static void RunInterface( intf_thread_t *p_intf )
00308 {
00309 static char *ppsz_interfaces[] =
00310 {
00311 "skins2", "Skins 2",
00312 "wxwidgets", "wxWidgets",
00313 NULL, NULL
00314 };
00315 char **ppsz_parser;
00316
00317 vlc_list_t *p_list;
00318 int i;
00319 vlc_value_t val, text;
00320 char *psz_intf;
00321
00322
00323 p_intf->psz_switch_intf = NULL;
00324 var_Create( p_intf, "intf-switch", VLC_VAR_STRING |
00325 VLC_VAR_HASCHOICE | VLC_VAR_ISCOMMAND );
00326 text.psz_string = _("Switch interface");
00327 var_Change( p_intf, "intf-switch", VLC_VAR_SETTEXT, &text, NULL );
00328
00329
00330 p_list = vlc_list_find( p_intf, VLC_OBJECT_MODULE, FIND_ANYWHERE );
00331 for( ppsz_parser = ppsz_interfaces; *ppsz_parser; ppsz_parser += 2 )
00332 {
00333 for( i = 0; i < p_list->i_count; i++ )
00334 {
00335 module_t *p_module = (module_t *)p_list->p_values[i].p_object;
00336 if( !strcmp( p_module->psz_object_name, ppsz_parser[0] ) )
00337 {
00338 val.psz_string = ppsz_parser[0];
00339 text.psz_string = ppsz_parser[1];
00340 var_Change( p_intf, "intf-switch", VLC_VAR_ADDCHOICE,
00341 &val, &text );
00342 break;
00343 }
00344 }
00345 }
00346 vlc_list_release( p_list );
00347
00348 var_AddCallback( p_intf, "intf-switch", SwitchIntfCallback, NULL );
00349
00350
00351 var_Create( p_intf, "intf-add", VLC_VAR_STRING |
00352 VLC_VAR_HASCHOICE | VLC_VAR_ISCOMMAND );
00353 text.psz_string = _("Add Interface");
00354 var_Change( p_intf, "intf-add", VLC_VAR_SETTEXT, &text, NULL );
00355
00356 val.psz_string = "rc"; text.psz_string = "Console";
00357 var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text );
00358 val.psz_string = "telnet"; text.psz_string = "Telnet Interface";
00359 var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text );
00360 val.psz_string = "http"; text.psz_string = "Web Interface";
00361 var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text );
00362 val.psz_string = "logger"; text.psz_string = "Debug logging";
00363 var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text );
00364 val.psz_string = "gestures"; text.psz_string = "Mouse Gestures";
00365 var_Change( p_intf, "intf-add", VLC_VAR_ADDCHOICE, &val, &text );
00366
00367 var_AddCallback( p_intf, "intf-add", AddIntfCallback, NULL );
00368
00369 do
00370 {
00371
00372 p_intf->pf_run( p_intf );
00373
00374
00375 p_intf->b_play = VLC_FALSE;
00376
00377 if( !p_intf->psz_switch_intf )
00378 {
00379 break;
00380 }
00381
00382
00383 module_Unneed( p_intf, p_intf->p_module );
00384
00385
00386 psz_intf = p_intf->psz_switch_intf;
00387 p_intf->psz_switch_intf = NULL;
00388
00389 vlc_mutex_lock( &p_intf->object_lock );
00390 p_intf->b_die = VLC_FALSE;
00391 p_intf->b_dead = VLC_FALSE;
00392 vlc_mutex_unlock( &p_intf->object_lock );
00393
00394 p_intf->p_module = module_Need( p_intf, "interface", psz_intf, 0 );
00395 free( psz_intf );
00396 }
00397 while( p_intf->p_module );
00398 }
00399
00400 static int SwitchIntfCallback( vlc_object_t *p_this, char const *psz_cmd,
00401 vlc_value_t oldval, vlc_value_t newval, void *p_data )
00402 {
00403 intf_thread_t *p_intf = (intf_thread_t *)p_this;
00404
00405 p_intf->psz_switch_intf =
00406 malloc( strlen(newval.psz_string) + sizeof(",none") );
00407 sprintf( p_intf->psz_switch_intf, "%s,none", newval.psz_string );
00408 p_intf->b_die = VLC_TRUE;
00409
00410 return VLC_SUCCESS;
00411 }
00412
00413 static int AddIntfCallback( vlc_object_t *p_this, char const *psz_cmd,
00414 vlc_value_t oldval, vlc_value_t newval, void *p_data )
00415 {
00416 intf_thread_t *p_intf;
00417 char *psz_intf = malloc( strlen(newval.psz_string) + sizeof(",none") );
00418
00419
00420 sprintf( psz_intf, "%s,none", newval.psz_string );
00421 p_intf = intf_Create( p_this->p_vlc, psz_intf );
00422 free( psz_intf );
00423 if( p_intf == NULL )
00424 {
00425 msg_Err( p_this, "interface \"%s\" initialization failed",
00426 newval.psz_string );
00427 return VLC_EGENERIC;
00428 }
00429
00430
00431 p_intf->b_block = VLC_FALSE;
00432 if( intf_RunThread( p_intf ) != VLC_SUCCESS )
00433 {
00434 vlc_object_detach( p_intf );
00435 intf_Destroy( p_intf );
00436 return VLC_EGENERIC;
00437 }
00438
00439 return VLC_SUCCESS;
00440 }
00441
00442 #ifdef SYS_DARWIN
00443
00444
00445
00446 @implementation VLCApplication
00447
00448 - (void)stop: (id)sender
00449 {
00450 NSEvent *o_event;
00451 NSAutoreleasePool *o_pool;
00452 [super stop:sender];
00453
00454 o_pool = [[NSAutoreleasePool alloc] init];
00455
00456 o_event = [NSEvent mouseEventWithType: NSLeftMouseDown
00457 location: NSMakePoint( 1, 1 ) modifierFlags: 0
00458 timestamp: 1 windowNumber: [[NSApp mainWindow] windowNumber]
00459 context: [NSGraphicsContext currentContext] eventNumber: 1
00460 clickCount: 1 pressure: 0.0];
00461 [NSApp postEvent: o_event atStart: YES];
00462 [o_pool release];
00463 }
00464
00465 - (void)terminate: (id)sender
00466 {
00467 if( [NSApp isRunning] )
00468 [NSApp stop:sender];
00469 [super terminate: sender];
00470 }
00471
00472 @end
00473 #endif
00474