a68629a5a29ec3d9f3ced54531e3924a2c822abb
[vlc.git] / modules / gui / skins / src / vlcproc.cpp
1 /*****************************************************************************
2  * vlcproc.cpp: VlcProc class
3  *****************************************************************************
4  * Copyright (C) 2003 VideoLAN
5  * $Id: vlcproc.cpp,v 1.17 2003/04/30 19:22:27 ipkiss Exp $
6  *
7  * Authors: Olivier Teulière <ipkiss@via.ecp.fr>
8  *          Emmanuel Puig    <karibu@via.ecp.fr>
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., 59 Temple Place - Suite 330, Boston, MA  02111,
23  * USA.
24  *****************************************************************************/
25
26 #ifndef BASIC_SKINS
27 #include <wx/wx.h>
28 #endif
29
30 //--- VLC -------------------------------------------------------------------
31 #include <vlc/vlc.h>
32 #include <vlc/intf.h>
33 #include <vlc/aout.h>
34 #include <vlc/vout.h>
35
36 extern "C" {
37 #include "netutils.h"
38 }
39
40 //--- SKIN ------------------------------------------------------------------
41 #include "../os_api.h"
42 #include "event.h"
43 #include "banks.h"
44 #include "theme.h"
45 #include "../os_theme.h"
46 #include "themeloader.h"
47 #include "window.h"
48 #include "vlcproc.h"
49 #include "skin_common.h"
50
51 #ifndef BASIC_SKINS
52 #include "wxdialogs.h"
53 #endif
54
55
56 //---------------------------------------------------------------------------
57 // VlcProc
58 //---------------------------------------------------------------------------
59 VlcProc::VlcProc( intf_thread_t *_p_intf )
60 {
61     p_intf = _p_intf;
62 }
63 //---------------------------------------------------------------------------
64 bool VlcProc::EventProc( Event *evt )
65 {
66     switch( evt->GetMessage() )
67     {
68         case VLC_STREAMPOS:
69             MoveStream( evt->GetParam2() );
70             return true;
71
72         case VLC_VOLUME_CHANGE:
73             ChangeVolume( evt->GetParam1(), evt->GetParam2() );
74             return true;
75
76         case VLC_FULLSCREEN:
77             FullScreen();
78             return true;
79
80         case VLC_HIDE:
81             for( list<SkinWindow *>::const_iterator win =
82                     p_intf->p_sys->p_theme->WindowList.begin();
83                  win != p_intf->p_sys->p_theme->WindowList.end(); win++ )
84             {
85                 (*win)->OnStartThemeVisible = !(*win)->IsHidden();
86             }
87             p_intf->p_sys->i_close_status = (int)evt->GetParam1();
88             OSAPI_PostMessage( NULL, WINDOW_CLOSE, 1, 0 );
89             return true;
90
91         case VLC_SHOW:
92             for( list<SkinWindow *>::const_iterator win =
93                     p_intf->p_sys->p_theme->WindowList.begin();
94                  win != p_intf->p_sys->p_theme->WindowList.end(); win++ )
95             {
96                 if( (*win)->OnStartThemeVisible )
97                     OSAPI_PostMessage( (*win), WINDOW_OPEN, 1, 0 );
98             }
99             p_intf->p_sys->b_all_win_closed = false;
100             return true;
101
102         case VLC_OPEN:
103             OpenFile( true );
104             return true;
105
106         case VLC_LOAD_SKIN:
107             LoadSkin();
108             return true;
109
110         case VLC_DROP:
111             DropFile( evt->GetParam1() );
112             return true;
113
114         case VLC_PLAY:
115             PlayStream();
116             return true;
117
118         case VLC_PAUSE:
119             PauseStream();
120             return true;
121
122         case VLC_STOP:
123             StopStream();
124             return true;
125
126         case VLC_NEXT:
127             NextStream();
128             return true;
129
130         case VLC_PREV:
131             PrevStream();
132             return true;
133
134         case VLC_PLAYLIST_ADD_FILE:
135             OpenFile( false );
136             return true;
137
138 #ifndef BASIC_SKINS
139         case VLC_LOG_SHOW:
140             p_intf->p_sys->MessagesDlg->Show(
141                 !p_intf->p_sys->MessagesDlg->IsShown() );
142             return true;
143
144         case VLC_LOG_CLEAR:
145             return true;
146
147         case VLC_PREFS_SHOW:
148             p_intf->p_sys->PrefsDlg->Show(
149                 !p_intf->p_sys->PrefsDlg->IsShown() );
150             return true;
151
152         case VLC_INFO_SHOW:
153             p_intf->p_sys->InfoDlg->Show(
154                 !p_intf->p_sys->InfoDlg->IsShown() );
155             return true;
156 #endif
157
158         case VLC_INTF_REFRESH:
159             InterfaceRefresh( (bool)evt->GetParam2() );
160             return true;
161
162         case VLC_TEST_ALL_CLOSED:
163             return EventProcEnd();
164
165         case VLC_QUIT:
166             return false;
167
168         case VLC_CHANGE_TRAY:
169             p_intf->p_sys->p_theme->ChangeTray();
170             return true;
171
172         case VLC_CHANGE_TASKBAR:
173             p_intf->p_sys->p_theme->ChangeTaskbar();
174             return true;
175
176         case VLC_NET_ADDUDP:
177             AddNetworkUDP( (int)evt->GetParam2() );
178             return true;
179
180         case VLC_NET_ADDCS:
181             AddNetworkChannelServer( (char *)evt->GetParam1() );
182             return true;
183
184         default:
185             return true;
186     }
187 }
188 //---------------------------------------------------------------------------
189 bool VlcProc::EventProcEnd()
190 {
191     if( p_intf->p_sys->b_all_win_closed )
192         return true;
193
194     list<SkinWindow *>::const_iterator win;
195
196     // If a window has been closed, test if all are closed !
197     for( win = p_intf->p_sys->p_theme->WindowList.begin();
198          win != p_intf->p_sys->p_theme->WindowList.end(); win++ )
199     {
200         if( !(*win)->IsHidden() )   // Not all windows closed
201         {
202             return true;
203         }
204     }
205
206     // All window are closed
207     switch( p_intf->p_sys->i_close_status )
208     {
209         case VLC_QUIT:
210             // Save config before exiting
211             p_intf->p_sys->p_theme->SaveConfig();
212             break;
213     }
214
215     // Send specified event
216     OSAPI_PostMessage( NULL, p_intf->p_sys->i_close_status, 0, 0 );
217
218     // Reset values
219     p_intf->p_sys->i_close_status = VLC_NOTHING;
220     p_intf->p_sys->b_all_win_closed = true;
221
222     // Return true
223     return true;
224 }
225 //---------------------------------------------------------------------------
226 bool VlcProc::IsClosing()
227 {
228     if( p_intf->b_die && p_intf->p_sys->i_close_status != VLC_QUIT )
229     {
230         p_intf->p_sys->i_close_status = VLC_QUIT;
231         OSAPI_PostMessage( NULL, VLC_HIDE, VLC_QUIT, 0 );
232     }
233     return true;
234 }
235 //---------------------------------------------------------------------------
236
237
238
239
240 //---------------------------------------------------------------------------
241 // Private methods
242 //---------------------------------------------------------------------------
243 void VlcProc::InterfaceRefresh( bool All )
244 {
245     // Shortcut pointers
246     intf_sys_t  *Sys      = p_intf->p_sys;
247     Theme       *Thema    = Sys->p_theme;
248     playlist_t  *PlayList = Sys->p_playlist;
249
250     // Refresh
251     if( PlayList != NULL )
252     {
253         // Refresh stream control controls ! :)
254         switch( PlayList->i_status )
255         {
256             case PLAYLIST_STOPPED:
257                 EnabledEvent( "time", false );
258                 EnabledEvent( "stop", false );
259                 EnabledEvent( "play", true );
260                 EnabledEvent( "pause", false );
261                 break;
262             case PLAYLIST_RUNNING:
263                 EnabledEvent( "time", true );
264                 EnabledEvent( "stop", true );
265                 EnabledEvent( "play", false );
266                 EnabledEvent( "pause", true );
267                 break;
268             case PLAYLIST_PAUSED:
269                 EnabledEvent( "time", true );
270                 EnabledEvent( "stop", true );
271                 EnabledEvent( "play", true );
272                 EnabledEvent( "pause", false );
273                 break;
274         }
275
276         // Refresh next and prev buttons
277         if( PlayList->i_index == 0 || PlayList->i_size == 1 )
278             EnabledEvent( "prev", false );
279         else
280             EnabledEvent( "prev", true );
281
282         if( PlayList->i_index == PlayList->i_size - 1 || PlayList->i_size == 1 )
283             EnabledEvent( "next", false );
284         else
285             EnabledEvent( "next", true );
286
287
288         // Update file name text
289         if( PlayList->i_index != Sys->i_index )
290         {
291             Thema->EvtBank->Get( "file_name" )->PostTextMessage(
292                 PlayList->pp_items[PlayList->i_index]->psz_name );
293         }
294
295         // Update playlists
296         if( PlayList->i_index != Sys->i_index ||
297             PlayList->i_size != Sys->i_size )
298         {
299             Thema->EvtBank->Get( "playlist_refresh" )->PostSynchroMessage();
300             Sys->i_size  = PlayList->i_size;
301             Sys->i_index = PlayList->i_index;
302         }
303     }
304     else
305     {
306         EnabledEvent( "time", false );
307         EnabledEvent( "stop",  false );
308         EnabledEvent( "play",  false );
309         EnabledEvent( "pause", false );
310         EnabledEvent( "prev",  false );
311         EnabledEvent( "next",  false );
312
313         // Update playlists
314         if( Sys->i_size > 0 )
315         {
316             Thema->EvtBank->Get( "playlist_refresh" )->PostSynchroMessage();
317             Sys->i_size  = 0;
318         }
319     }
320
321 }
322 //---------------------------------------------------------------------------
323 void VlcProc::EnabledEvent( string type, bool state )
324 {
325     OSAPI_PostMessage( NULL, CTRL_ENABLED, (unsigned int)
326         p_intf->p_sys->p_theme->EvtBank->Get( type ), (int)state );
327 }
328 //---------------------------------------------------------------------------
329
330
331
332 //---------------------------------------------------------------------------
333 // Common VLC procedures
334 //---------------------------------------------------------------------------
335 void VlcProc::LoadSkin()
336 {
337 #ifndef BASIC_SKINS
338     if( p_intf->p_sys->p_new_theme_file == NULL )
339     {
340         wxFileDialog dialog( NULL, _("Open a skin file"), "", "",
341             "Skin files (*.vlt)|*.vlt|Skin files (*.xml)|*.xml|All files|*.*",
342             wxOPEN );
343
344         if( dialog.ShowModal() == wxID_OK )
345         {
346             p_intf->p_sys->p_new_theme_file =
347                 new char[dialog.GetPath().Length()];
348
349             strcpy( p_intf->p_sys->p_new_theme_file,
350                     dialog.GetPath().c_str() );
351
352             // Tell vlc to change skin after hiding interface
353             OSAPI_PostMessage( NULL, VLC_HIDE, VLC_LOAD_SKIN, 0 );
354         }
355     }
356     else
357     {
358         // Place a new theme in the global structure, because it will
359         // be filled by the parser
360         // We save the old one to restore it in case of problem
361         Theme *oldTheme = p_intf->p_sys->p_theme;
362         p_intf->p_sys->p_theme = (Theme *)new OSTheme( p_intf );
363
364         // Run the XML parser
365         ThemeLoader *Loader = new ThemeLoader( p_intf );
366         if( Loader->Load( p_intf->p_sys->p_new_theme_file ) )
367         {
368             // Everything went well
369             msg_Dbg( p_intf, "New theme successfully loaded" );
370             delete (OSTheme *)oldTheme;
371
372             // Show the theme
373             p_intf->p_sys->p_theme->InitTheme();
374             p_intf->p_sys->p_theme->ShowTheme();
375         }
376         else
377         {
378             msg_Warn( p_intf, "A problem occurred when loading the new theme,"
379                       " restoring the previous one" );
380             delete (OSTheme *)p_intf->p_sys->p_theme;
381             p_intf->p_sys->p_theme = oldTheme;
382
383             // Show the theme
384             p_intf->p_sys->p_theme->ShowTheme();
385         }
386         delete Loader;
387
388         // Uninitialize new theme
389         delete (char *)p_intf->p_sys->p_new_theme_file;
390         p_intf->p_sys->p_new_theme_file = NULL;
391     }
392 #endif
393 }
394 //---------------------------------------------------------------------------
395 void VlcProc::OpenFile( bool play )
396 {
397 #ifndef BASIC_SKINS
398     if( p_intf->p_sys->OpenDlg->ShowModal() != wxID_OK )
399     {
400         return;
401     }
402
403     // Check if playlist is available
404     playlist_t *p_playlist = p_intf->p_sys->p_playlist;
405     if( p_playlist == NULL )
406     {
407         return;
408     }
409
410     if( play )
411     {
412         // Append and play
413         playlist_Add( p_playlist,
414                       (char *)p_intf->p_sys->OpenDlg->mrl.c_str(),
415                       PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
416
417         p_intf->p_sys->p_theme->EvtBank->Get( "play" )->SendEvent();
418     }
419     else
420     {
421         // Append only
422         playlist_Add( p_playlist,
423                         (char *)p_intf->p_sys->OpenDlg->mrl.c_str(),
424                         PLAYLIST_APPEND, PLAYLIST_END );
425     }
426
427     // Refresh interface !
428     p_intf->p_sys->p_theme->EvtBank->Get( "playlist_refresh" )
429         ->PostSynchroMessage();
430     InterfaceRefresh();
431 #endif
432 }
433 //---------------------------------------------------------------------------
434 void VlcProc::DropFile( unsigned int param )
435 {
436     // Get pointer to file
437     char *FileName = (char *)param;
438
439     // Add the new file to the playlist
440     if( p_intf->p_sys->p_playlist != NULL )
441     {
442         if( config_GetInt( p_intf, "enqueue" ) )
443         {
444             playlist_Add( p_intf->p_sys->p_playlist, FileName,
445                           PLAYLIST_APPEND, PLAYLIST_END );
446         }
447         else
448         {
449             playlist_Add( p_intf->p_sys->p_playlist, FileName,
450                           PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
451         }
452     }
453
454     // VLC_DROP must be called with a pointer to a char else it will
455     // ******** SEGFAULT ********
456     // The delete is here because the processus in asynchronous
457     delete[] FileName;
458
459     // Refresh interface
460     InterfaceRefresh();
461
462 }
463 //---------------------------------------------------------------------------
464
465
466
467
468 //---------------------------------------------------------------------------
469 // Stream Control
470 //---------------------------------------------------------------------------
471 void VlcProc::PauseStream()
472 {
473     if( p_intf->p_sys->p_input == NULL )
474         return;
475     input_SetStatus( p_intf->p_sys->p_input, INPUT_STATUS_PAUSE );
476
477     // Refresh interface
478     InterfaceRefresh();
479 }
480 //---------------------------------------------------------------------------
481 void VlcProc::PlayStream()
482 {
483     if( p_intf->p_sys->p_playlist == NULL )
484         return;
485     if( !p_intf->p_sys->p_playlist->i_size )
486         return;
487
488     playlist_Play( p_intf->p_sys->p_playlist );
489
490     // Refresh interface
491     InterfaceRefresh();
492 }
493 //---------------------------------------------------------------------------
494 void VlcProc::StopStream()
495 {
496     if( p_intf->p_sys->p_playlist == NULL )
497         return;
498     playlist_Stop( p_intf->p_sys->p_playlist );
499
500     // Refresh interface
501     InterfaceRefresh();
502 }
503 //---------------------------------------------------------------------------
504 void VlcProc::NextStream()
505 {
506     if( p_intf->p_sys->p_playlist == NULL )
507         return;
508
509     playlist_Next( p_intf->p_sys->p_playlist );
510
511     // Refresh interface
512     InterfaceRefresh();
513 }
514 //---------------------------------------------------------------------------
515 void VlcProc::PrevStream()
516 {
517     if( p_intf->p_sys->p_playlist == NULL )
518         return;
519
520     playlist_Prev( p_intf->p_sys->p_playlist );
521
522     // Refresh interface
523     InterfaceRefresh();
524 }
525 //---------------------------------------------------------------------------
526 void VlcProc::MoveStream( long Pos )
527 {
528     if( p_intf->p_sys->p_input == NULL )
529         return;
530
531     off_t i_seek = (off_t)(Pos *
532         p_intf->p_sys->p_input->stream.p_selected_area->i_size
533         / SLIDER_RANGE);
534
535     input_Seek( p_intf->p_sys->p_input, i_seek, INPUT_SEEK_SET );
536
537     // Refresh interface
538     InterfaceRefresh();
539 }
540 //---------------------------------------------------------------------------
541
542
543
544 //---------------------------------------------------------------------------
545 // Fullscreen
546 //---------------------------------------------------------------------------
547 void VlcProc::FullScreen()
548 {
549     vout_thread_t *p_vout;
550
551     if( p_intf->p_sys->p_input == NULL )
552         return;
553
554     p_vout = (vout_thread_t *)vlc_object_find( p_intf->p_sys->p_input,
555                                                VLC_OBJECT_VOUT, FIND_CHILD );
556     if( p_vout == NULL )
557         return;
558
559     p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
560     vlc_object_release( p_vout );
561 }
562 //---------------------------------------------------------------------------
563
564
565
566 //---------------------------------------------------------------------------
567 // Volume Control
568 //---------------------------------------------------------------------------
569 void VlcProc::ChangeVolume( unsigned int msg, long param )
570 {
571     audio_volume_t volume;
572     switch( msg )
573     {
574         case VLC_VOLUME_MUTE:
575             aout_VolumeMute( p_intf, NULL );
576             break;
577         case VLC_VOLUME_UP:
578             aout_VolumeUp( p_intf, 1, NULL );
579             break;
580         case VLC_VOLUME_DOWN:
581             aout_VolumeDown( p_intf, 1, NULL );
582             break;
583         case VLC_VOLUME_SET:
584             aout_VolumeSet( p_intf, param * AOUT_VOLUME_MAX / SLIDER_RANGE );
585             break;
586     }
587     aout_VolumeGet( p_intf, &volume );
588
589 }
590 //---------------------------------------------------------------------------
591
592
593 //---------------------------------------------------------------------------
594 // Network
595 //---------------------------------------------------------------------------
596 void VlcProc::AddNetworkUDP( int port )
597 {
598     config_PutInt( p_intf, "network-channel", VLC_FALSE );
599
600     // Build source name
601     char *s_port = new char[5];
602     sprintf( s_port, "%i", port );
603     string source = "udp:@:" + (string)s_port;
604     delete[] s_port;
605
606     playlist_Add( p_intf->p_sys->p_playlist, (char *)source.c_str(),
607         PLAYLIST_APPEND, PLAYLIST_END );
608
609     // Refresh interface !
610     p_intf->p_sys->p_theme->EvtBank->Get( "playlist_refresh" )
611         ->PostSynchroMessage();
612     InterfaceRefresh();
613 }
614 //---------------------------------------------------------------------------
615 void VlcProc::AddNetworkChannelServer( char *server )
616 {
617     char *name = new char[MAX_PARAM_SIZE];
618     int  port = 0;
619
620     // Scan the server address
621     int scan = sscanf( server, "%[^:]:%i", name, &port );
622
623     if( scan != 2)
624     {
625         msg_Err( p_intf, "Invalid channel server: %s", server );
626         delete[] name;
627         return;
628     }
629
630     config_PutInt( p_intf, "network-channel", VLC_TRUE );
631     config_PutPsz( p_intf, "channel-server", name );
632     config_PutInt( p_intf, "channel-port", port );
633
634     if( p_intf->p_vlc->p_channel == NULL )
635     {
636         network_ChannelCreate( p_intf );
637     }
638
639     delete[] name;
640 }
641 //---------------------------------------------------------------------------
642