]> git.sesse.net Git - vlc/blob - modules/gui/skins2/src/vlcproc.cpp
Copyright fixes
[vlc] / modules / gui / skins2 / src / vlcproc.cpp
1 /*****************************************************************************
2  * vlcproc.cpp
3  *****************************************************************************
4  * Copyright (C) 2003 VideoLAN (Centrale Réseaux) and its contributors
5  * $Id$
6  *
7  * Authors: Cyril Deguet     <asmax@via.ecp.fr>
8  *          Olivier Teulière <ipkiss@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, USA.
23  *****************************************************************************/
24
25 #include <vlc/aout.h>
26 #include <vlc/vout.h>
27
28 #include "vlcproc.hpp"
29 #include "os_factory.hpp"
30 #include "os_timer.hpp"
31 #include "var_manager.hpp"
32 #include "theme.hpp"
33 #include "window_manager.hpp"
34 #include "../commands/async_queue.hpp"
35 #include "../commands/cmd_change_skin.hpp"
36 #include "../commands/cmd_show_window.hpp"
37 #include "../commands/cmd_quit.hpp"
38 #include "../commands/cmd_vars.hpp"
39 #include "../utils/var_bool.hpp"
40
41
42 VlcProc *VlcProc::instance( intf_thread_t *pIntf )
43 {
44     if( pIntf->p_sys->p_vlcProc == NULL )
45     {
46         pIntf->p_sys->p_vlcProc = new VlcProc( pIntf );
47     }
48
49     return pIntf->p_sys->p_vlcProc;
50 }
51
52
53 void VlcProc::destroy( intf_thread_t *pIntf )
54 {
55     if( pIntf->p_sys->p_vlcProc )
56     {
57         delete pIntf->p_sys->p_vlcProc;
58         pIntf->p_sys->p_vlcProc = NULL;
59     }
60 }
61
62
63 VlcProc::VlcProc( intf_thread_t *pIntf ): SkinObject( pIntf ), m_pVout( NULL )
64 {
65     // Create a timer to poll the status of the vlc
66     OSFactory *pOsFactory = OSFactory::instance( pIntf );
67     m_pTimer = pOsFactory->createOSTimer( Callback( this, &doManage ) );
68     m_pTimer->start( 100, false );
69
70     // Create and register VLC variables
71     VarManager *pVarManager = VarManager::instance( getIntf() );
72
73 #define REGISTER_VAR( var, type, name ) \
74     var = VariablePtr( new type( getIntf() ) ); \
75     pVarManager->registerVar( var, name );
76     REGISTER_VAR( m_cPlaylist, Playlist, "playlist" )
77     pVarManager->registerVar( getPlaylistVar().getPositionVarPtr(),
78                               "playlist.slider" );
79     REGISTER_VAR( m_cVarRandom, VarBoolImpl, "playlist.isRandom" )
80     REGISTER_VAR( m_cVarLoop, VarBoolImpl, "playlist.isLoop" )
81     REGISTER_VAR( m_cVarRepeat, VarBoolImpl, "playlist.isRepeat" )
82     REGISTER_VAR( m_cVarTime, StreamTime, "time" )
83     REGISTER_VAR( m_cVarVolume, Volume, "volume" )
84     REGISTER_VAR( m_cVarMute, VarBoolImpl, "vlc.isMute" )
85     REGISTER_VAR( m_cVarPlaying, VarBoolImpl, "vlc.isPlaying" )
86     REGISTER_VAR( m_cVarStopped, VarBoolImpl, "vlc.isStopped" )
87     REGISTER_VAR( m_cVarPaused, VarBoolImpl, "vlc.isPaused" )
88     REGISTER_VAR( m_cVarSeekable, VarBoolImpl, "vlc.isSeekable" )
89 #undef REGISTER_VAR
90     m_cVarStreamName = VariablePtr( new VarText( getIntf(), false ) );
91     pVarManager->registerVar( m_cVarStreamName, "streamName" );
92     m_cVarStreamURI = VariablePtr( new VarText( getIntf(), false ) );
93     pVarManager->registerVar( m_cVarStreamURI, "streamURI" );
94
95     // XXX WARNING XXX
96     // The object variable callbacks are called from other VLC threads,
97     // so they must put commands in the queue and NOT do anything else
98     // (X11 calls are not reentrant)
99
100     // Called when the playlist changes
101     var_AddCallback( pIntf->p_sys->p_playlist, "intf-change",
102                      onIntfChange, this );
103     // Called when a playlist item is added
104     // TODO: properly handle item-append
105     var_AddCallback( pIntf->p_sys->p_playlist, "item-append",
106                      onIntfChange, this );
107     // Called when a playlist item is deleted
108     // TODO: properly handle item-deleted
109     var_AddCallback( pIntf->p_sys->p_playlist, "item-deleted",
110                      onIntfChange, this );
111     // Called when the "interface shower" wants us to show the skin
112     var_AddCallback( pIntf->p_sys->p_playlist, "intf-show",
113                      onIntfShow, this );
114     // Called when the current played item changes
115     var_AddCallback( pIntf->p_sys->p_playlist, "playlist-current",
116                      onPlaylistChange, this );
117     // Called when a playlist item changed
118     var_AddCallback( pIntf->p_sys->p_playlist, "item-change",
119                      onItemChange, this );
120     // Called when our skins2 demux wants us to load a new skin
121     var_AddCallback( pIntf, "skin-to-load", onSkinToLoad, this );
122
123     // Callbacks for vout requests
124     getIntf()->pf_request_window = &getWindow;
125     getIntf()->pf_release_window = &releaseWindow;
126     getIntf()->pf_control_window = &controlWindow;
127
128     getIntf()->p_sys->p_input = NULL;
129 }
130
131
132 VlcProc::~VlcProc()
133 {
134     m_pTimer->stop();
135     delete( m_pTimer );
136     if( getIntf()->p_sys->p_input )
137     {
138         vlc_object_release( getIntf()->p_sys->p_input );
139     }
140
141     // Callbacks for vout requests
142     getIntf()->pf_request_window = NULL;
143     getIntf()->pf_release_window = NULL;
144     getIntf()->pf_control_window = NULL;
145
146     var_DelCallback( getIntf()->p_sys->p_playlist, "intf-change",
147                      onIntfChange, this );
148     var_DelCallback( getIntf()->p_sys->p_playlist, "item-append",
149                      onIntfChange, this );
150     var_DelCallback( getIntf()->p_sys->p_playlist, "item-deleted",
151                      onIntfChange, this );
152     var_DelCallback( getIntf()->p_sys->p_playlist, "intf-show",
153                      onIntfShow, this );
154     var_DelCallback( getIntf()->p_sys->p_playlist, "playlist-current",
155                      onPlaylistChange, this );
156     var_DelCallback( getIntf()->p_sys->p_playlist, "item-change",
157                      onItemChange, this );
158     var_DelCallback( getIntf(), "skin-to-load", onSkinToLoad, this );
159 }
160
161
162 void VlcProc::registerVoutWindow( void *pVoutWindow )
163 {
164     m_handleSet.insert( pVoutWindow );
165     // Reparent the vout window
166     if( m_pVout )
167     {
168         if( vout_Control( m_pVout, VOUT_REPARENT ) != VLC_SUCCESS )
169             vout_Control( m_pVout, VOUT_CLOSE );
170     }
171 }
172
173
174 void VlcProc::unregisterVoutWindow( void *pVoutWindow )
175 {
176     m_handleSet.erase( pVoutWindow );
177 }
178
179
180 void VlcProc::dropVout()
181 {
182     if( m_pVout )
183     {
184         if( vout_Control( m_pVout, VOUT_REPARENT ) != VLC_SUCCESS )
185             vout_Control( m_pVout, VOUT_CLOSE );
186         m_pVout = NULL;
187     }
188 }
189
190
191 void VlcProc::manage()
192 {
193     // Did the user requested to quit vlc ?
194     if( getIntf()->b_die || getIntf()->p_vlc->b_die )
195     {
196         CmdQuit *pCmd = new CmdQuit( getIntf() );
197         AsyncQueue *pQueue = AsyncQueue::instance( getIntf() );
198         pQueue->push( CmdGenericPtr( pCmd ) );
199     }
200
201     // Get the VLC variables
202     StreamTime *pTime = (StreamTime*)m_cVarTime.get();
203     Volume *pVolume = (Volume*)m_cVarVolume.get();
204     VarBoolImpl *pVarPlaying = (VarBoolImpl*)m_cVarPlaying.get();
205     VarBoolImpl *pVarStopped = (VarBoolImpl*)m_cVarStopped.get();
206     VarBoolImpl *pVarPaused = (VarBoolImpl*)m_cVarPaused.get();
207     VarBoolImpl *pVarSeekable = (VarBoolImpl*)m_cVarSeekable.get();
208     VarBoolImpl *pVarMute = (VarBoolImpl*)m_cVarMute.get();
209     VarBoolImpl *pVarRandom = (VarBoolImpl*)m_cVarRandom.get();
210     VarBoolImpl *pVarLoop = (VarBoolImpl*)m_cVarLoop.get();
211     VarBoolImpl *pVarRepeat = (VarBoolImpl*)m_cVarRepeat.get();
212
213     // Refresh sound volume
214     audio_volume_t volume;
215     aout_VolumeGet( getIntf(), &volume );
216     pVolume->set( (double)volume / AOUT_VOLUME_MAX );
217     // Set the mute variable
218     pVarMute->set( volume == 0 );
219
220     // Update the input
221     if( getIntf()->p_sys->p_input == NULL )
222     {
223         getIntf()->p_sys->p_input = (input_thread_t *)vlc_object_find(
224             getIntf(), VLC_OBJECT_INPUT, FIND_ANYWHERE );
225     }
226     else if( getIntf()->p_sys->p_input->b_dead )
227     {
228         vlc_object_release( getIntf()->p_sys->p_input );
229         getIntf()->p_sys->p_input = NULL;
230     }
231
232     input_thread_t *pInput = getIntf()->p_sys->p_input;
233
234     if( pInput && !pInput->b_die )
235     {
236         // Refresh time variables
237         vlc_value_t pos;
238         var_Get( pInput, "position", &pos );
239         pTime->set( pos.f_float, false );
240
241         // Get the status of the playlist
242         playlist_status_t status =
243             getIntf()->p_sys->p_playlist->status.i_status;
244
245         pVarPlaying->set( status == PLAYLIST_RUNNING );
246         pVarStopped->set( status == PLAYLIST_STOPPED );
247         pVarPaused->set( status == PLAYLIST_PAUSED );
248
249         pVarSeekable->set( pos.f_float != 0.0 );
250     }
251     else
252     {
253         pVarPlaying->set( false );
254         pVarPaused->set( false );
255         pVarStopped->set( true );
256         pVarSeekable->set( false );
257         pTime->set( 0, false );
258     }
259
260     // Refresh the random variable
261     vlc_value_t val;
262     var_Get( getIntf()->p_sys->p_playlist, "random", &val );
263     pVarRandom->set( val.b_bool );
264
265     // Refresh the loop variable
266     var_Get( getIntf()->p_sys->p_playlist, "loop", &val );
267     pVarLoop->set( val.b_bool );
268
269     // Refresh the repeat variable
270     var_Get( getIntf()->p_sys->p_playlist, "repeat", &val );
271     pVarRepeat->set( val.b_bool );
272 }
273
274
275 void VlcProc::doManage( SkinObject *pObj )
276 {
277     VlcProc *pThis = (VlcProc*)pObj;
278     pThis->manage();
279 }
280
281
282 int VlcProc::onIntfChange( vlc_object_t *pObj, const char *pVariable,
283                            vlc_value_t oldVal, vlc_value_t newVal,
284                            void *pParam )
285 {
286     VlcProc *pThis = (VlcProc*)pParam;
287
288     // Update the stream variable
289     playlist_t *p_playlist = (playlist_t*)pObj;
290     pThis->updateStreamName(p_playlist);
291
292     // Create a playlist notify command
293     CmdNotifyPlaylist *pCmd = new CmdNotifyPlaylist( pThis->getIntf() );
294
295     // Push the command in the asynchronous command queue
296     AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
297     pQueue->remove( "notify playlist" );
298     pQueue->push( CmdGenericPtr( pCmd ) );
299
300     return VLC_SUCCESS;
301 }
302
303
304 int VlcProc::onIntfShow( vlc_object_t *pObj, const char *pVariable,
305                          vlc_value_t oldVal, vlc_value_t newVal,
306                          void *pParam )
307 {
308     if (newVal.i_int)
309     {
310         VlcProc *pThis = (VlcProc*)pParam;
311
312         // Create a raise all command
313         CmdRaiseAll *pCmd = new CmdRaiseAll( pThis->getIntf(),
314             pThis->getIntf()->p_sys->p_theme->getWindowManager() );
315
316         // Push the command in the asynchronous command queue
317         AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
318         pQueue->remove( "raise all windows" );
319         pQueue->push( CmdGenericPtr( pCmd ) );
320     }
321
322     return VLC_SUCCESS;
323 }
324
325
326 int VlcProc::onItemChange( vlc_object_t *pObj, const char *pVariable,
327                            vlc_value_t oldVal, vlc_value_t newVal,
328                            void *pParam )
329 {
330     VlcProc *pThis = (VlcProc*)pParam;
331
332     // Update the stream variable
333     playlist_t *p_playlist = (playlist_t*)pObj;
334     pThis->updateStreamName(p_playlist);
335
336     // Create a playlist notify command
337     // TODO: selective update
338     CmdNotifyPlaylist *pCmd = new CmdNotifyPlaylist( pThis->getIntf() );
339
340     // Push the command in the asynchronous command queue
341     AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
342     pQueue->remove( "notify playlist" );
343     pQueue->push( CmdGenericPtr( pCmd ) );
344
345     return VLC_SUCCESS;
346 }
347
348
349 int VlcProc::onPlaylistChange( vlc_object_t *pObj, const char *pVariable,
350                                vlc_value_t oldVal, vlc_value_t newVal,
351                                void *pParam )
352 {
353     VlcProc *pThis = (VlcProc*)pParam;
354
355     AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
356
357     // Update the stream variable
358     playlist_t *p_playlist = (playlist_t*)pObj;
359     pThis->updateStreamName(p_playlist);
360
361     // Create a playlist notify command
362     // TODO: selective update
363     CmdNotifyPlaylist *pCmd = new CmdNotifyPlaylist( pThis->getIntf() );
364
365     // Push the command in the asynchronous command queue
366     pQueue->remove( "notify playlist" );
367     pQueue->push( CmdGenericPtr( pCmd ) );
368
369     return VLC_SUCCESS;
370 }
371
372
373 int VlcProc::onSkinToLoad( vlc_object_t *pObj, const char *pVariable,
374                            vlc_value_t oldVal, vlc_value_t newVal,
375                            void *pParam )
376 {
377     VlcProc *pThis = (VlcProc*)pParam;
378
379     // Create a playlist notify command
380     CmdChangeSkin *pCmd =
381         new CmdChangeSkin( pThis->getIntf(), newVal.psz_string );
382
383     // Push the command in the asynchronous command queue
384     AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
385     pQueue->remove( "change skin" );
386     pQueue->push( CmdGenericPtr( pCmd ) );
387
388     return VLC_SUCCESS;
389 }
390
391
392 void VlcProc::updateStreamName( playlist_t *p_playlist )
393 {
394     if( p_playlist->p_input )
395     {
396         VarText &rStreamName = getStreamNameVar();
397         VarText &rStreamURI = getStreamURIVar();
398         // XXX: we should not need to access p_input->psz_source directly, a
399         // getter should be provided by VLC core
400         string name = p_playlist->p_input->input.p_item->psz_name;
401         // XXX: This should be done in VLC core, not here...
402         // Remove path information if any
403         OSFactory *pFactory = OSFactory::instance( getIntf() );
404         string::size_type pos = name.rfind( pFactory->getDirSeparator() );
405         if( pos != string::npos )
406         {
407             name = name.substr( pos + 1, name.size() - pos + 1 );
408         }
409         UString srcName( getIntf(), name.c_str() );
410         UString srcURI( getIntf(),
411                          p_playlist->p_input->input.p_item->psz_uri );
412
413         // Create commands to update the stream variables
414         CmdSetText *pCmd1 = new CmdSetText( getIntf(), rStreamName, srcName );
415         CmdSetText *pCmd2 = new CmdSetText( getIntf(), rStreamURI, srcURI );
416         // Push the commands in the asynchronous command queue
417         AsyncQueue *pQueue = AsyncQueue::instance( getIntf() );
418         pQueue->push( CmdGenericPtr( pCmd1 ) );
419         pQueue->push( CmdGenericPtr( pCmd2 ) );
420     }
421 }
422
423
424 void *VlcProc::getWindow( intf_thread_t *pIntf, vout_thread_t *pVout,
425                           int *pXHint, int *pYHint,
426                           unsigned int *pWidthHint,
427                           unsigned int *pHeightHint )
428 {
429     VlcProc *pThis = pIntf->p_sys->p_vlcProc;
430     pThis->m_pVout = pVout;
431     if( pThis->m_handleSet.empty() )
432     {
433         return NULL;
434     }
435     else
436     {
437         return *pThis->m_handleSet.begin();
438     }
439 }
440
441
442 void VlcProc::releaseWindow( intf_thread_t *pIntf, void *pWindow )
443 {
444     VlcProc *pThis = pIntf->p_sys->p_vlcProc;
445     pThis->m_pVout = NULL;
446 }
447
448
449 int VlcProc::controlWindow( intf_thread_t *pIntf, void *pWindow,
450                             int query, va_list args )
451 {
452     return VLC_SUCCESS;
453 }
454