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