]> git.sesse.net Git - vlc/blob - modules/gui/wxwindows/timer.cpp
* modules/gui/wxwindows: small cleanup + renamed wxwin-size-to-video into wxwin-autosize.
[vlc] / modules / gui / wxwindows / timer.cpp
1 /*****************************************************************************
2  * timer.cpp : wxWindows plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2000-2005 VideoLAN
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>                                      /* malloc(), free() */
28 #include <errno.h>                                                 /* ENOMEM */
29 #include <string.h>                                            /* strerror() */
30 #include <stdio.h>
31
32 #include <vlc/vlc.h>
33 #include <vlc/aout.h>
34 #include <vlc/intf.h>
35
36 #include "vlc_meta.h"
37
38 #include "wxwindows.h"
39 #include <wx/timer.h>
40
41 //void DisplayStreamDate( wxControl *, intf_thread_t *, int );
42
43 /* Callback prototypes */
44 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
45                         vlc_value_t old_val, vlc_value_t new_val, void *param );
46 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
47                        vlc_value_t old_val, vlc_value_t new_val, void *param );
48
49 /*****************************************************************************
50  * Constructor.
51  *****************************************************************************/
52 Timer::Timer( intf_thread_t *_p_intf, Interface *_p_main_interface )
53 {
54     p_intf = _p_intf;
55     p_main_interface = _p_main_interface;
56     b_init = 0;
57     i_old_playing_status = PAUSE_S;
58     i_old_rate = INPUT_RATE_DEFAULT;
59
60     /* Register callback for the intf-popupmenu variable */
61     playlist_t *p_playlist =
62         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
63                                        FIND_ANYWHERE );
64     if( p_playlist != NULL )
65     {
66         var_AddCallback( p_playlist, "intf-popupmenu", PopupMenuCB, p_intf );
67         var_AddCallback( p_playlist, "intf-show", IntfShowCB, p_intf );
68         vlc_object_release( p_playlist );
69     }
70
71     Start( 100 /*milliseconds*/, wxTIMER_CONTINUOUS );
72 }
73
74 Timer::~Timer()
75 {
76     /* Unregister callback */
77     playlist_t *p_playlist =
78         (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
79                                        FIND_ANYWHERE );
80     if( p_playlist != NULL )
81     {
82         var_DelCallback( p_playlist, "intf-popupmenu", PopupMenuCB, p_intf );
83         var_DelCallback( p_playlist, "intf-show", IntfShowCB, p_intf );
84         vlc_object_release( p_playlist );
85     }
86
87     vlc_mutex_lock( &p_intf->change_lock );
88     if( p_intf->p_sys->p_input ) vlc_object_release( p_intf->p_sys->p_input );
89     p_intf->p_sys->p_input = NULL;
90     vlc_mutex_unlock( &p_intf->change_lock );
91 }
92
93 /*****************************************************************************
94  * Private methods.
95  *****************************************************************************/
96
97 /*****************************************************************************
98  * Manage: manage main thread messages
99  *****************************************************************************
100  * In this function, called approx. 10 times a second, we check what the
101  * main program wanted to tell us.
102  *****************************************************************************/
103 void Timer::Notify()
104 {
105 #if defined( __WXMSW__ ) /* Work-around a bug with accelerators */
106     if( !b_init )
107     {
108         p_main_interface->Init();
109         b_init = VLC_TRUE;
110     }
111 #endif
112
113     vlc_mutex_lock( &p_intf->change_lock );
114
115     /* Update the input */
116     if( p_intf->p_sys->p_input == NULL )
117     {
118         playlist_t *p_playlist =
119             (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
120                                            FIND_ANYWHERE );
121         if( p_playlist != NULL )
122         {
123             LockPlaylist( p_intf->p_sys, p_playlist );
124             p_intf->p_sys->p_input = p_playlist->p_input;
125             if( p_intf->p_sys->p_input )
126                 vlc_object_yield( p_intf->p_sys->p_input );
127             UnlockPlaylist( p_intf->p_sys, p_playlist );
128             vlc_object_release( p_playlist );
129         }
130
131         /* Refresh interface */
132         if( p_intf->p_sys->p_input )
133         {
134             p_main_interface->slider->SetValue( 0 );
135
136             char *psz_now_playing = vlc_input_item_GetInfo(
137                 p_intf->p_sys->p_input->input.p_item,
138                 _("Meta-information"), _( "Now Playing" ) );
139             if( psz_now_playing && *psz_now_playing )
140             {
141                 p_main_interface->statusbar->SetStatusText(
142                     wxString(wxU(psz_now_playing)) + wxT( " - " ) +
143                     wxU(p_intf->p_sys->p_input->input.p_item->psz_name), 2 );
144             }
145             else
146             {
147                 p_main_interface->statusbar->SetStatusText(
148                     wxU(p_intf->p_sys->p_input->input.p_item->psz_name), 2 );
149             }
150             free( psz_now_playing );
151
152             p_main_interface->TogglePlayButton( PLAYING_S );
153 #ifdef wxHAS_TASK_BAR_ICON
154             if( p_main_interface->p_systray )
155             {
156                 p_main_interface->p_systray->UpdateTooltip( wxU(p_intf->p_sys->p_input->input.p_item->psz_name) + wxString(wxT(" - ")) + wxU(_("Playing")));
157             }
158 #endif
159             i_old_playing_status = PLAYING_S;
160         }
161     }
162     else if( p_intf->p_sys->p_input->b_dead )
163     {
164         //controls auto-hide after a timer
165         p_main_interface->m_controls_timer.Start(1000, wxTIMER_ONE_SHOT);
166
167         p_main_interface->TogglePlayButton( PAUSE_S );
168         i_old_playing_status = PAUSE_S;
169
170         p_main_interface->statusbar->SetStatusText( wxT(""), 0 );
171         p_main_interface->statusbar->SetStatusText( wxT(""), 2 );
172
173 #ifdef wxHAS_TASK_BAR_ICON
174         if( p_main_interface->p_systray )
175         {
176             p_main_interface->p_systray->UpdateTooltip( wxString(wxT("VLC media player - ")) + wxU(_("Stopped")) );
177         }
178 #endif
179         vlc_object_release( p_intf->p_sys->p_input );
180         p_intf->p_sys->p_input = NULL;
181     }
182
183     if( p_intf->p_sys->p_input )
184     {
185         input_thread_t *p_input = p_intf->p_sys->p_input;
186         vlc_value_t val;
187
188         if( !p_input->b_die )
189         {
190             vlc_value_t pos;
191
192             //prevent the controls from auto-hiding
193             p_main_interface->m_controls_timer.Stop();
194
195             /* New input or stream map change */
196             p_intf->p_sys->b_playing = 1;
197
198             /* Update the item name */
199             char *psz_now_playing = vlc_input_item_GetInfo(
200                 p_intf->p_sys->p_input->input.p_item,
201                 _("Meta-information"), _( "Now Playing" ) );
202             if( psz_now_playing && *psz_now_playing )
203             {
204                 p_main_interface->statusbar->SetStatusText(
205                     wxString(wxU(psz_now_playing)) + wxT( " - " ) +
206                     wxU(p_intf->p_sys->p_input->input.p_item->psz_name), 2 );
207             }
208             else
209             {
210                 p_main_interface->statusbar->SetStatusText(
211                     wxU(p_intf->p_sys->p_input->input.p_item->psz_name), 2 );
212             }
213             free( psz_now_playing );
214
215             /* Manage the slider */
216             var_Get( p_input, "position", &pos );
217
218             var_Change( p_input, "title", VLC_VAR_CHOICESCOUNT, &val, NULL );
219             if( val.i_int > 0 && !p_main_interface->disc_menu_button->IsShown() )
220             {
221                 vlc_value_t val;
222
223                     #define HELP_MENU N_("Menu")
224                     #define HELP_PCH N_("Previous chapter")
225                     #define HELP_NCH N_("Next chapter")
226                     #define HELP_PTR N_("Previous track")
227                     #define HELP_NTR N_("Next track")
228
229                 var_Change( p_input, "chapter", VLC_VAR_CHOICESCOUNT, &val,
230                             NULL );
231
232                 if( val.i_int > 0 )
233                 {
234                     p_main_interface->disc_menu_button->Show();
235                     p_main_interface->disc_sizer->Show(
236                         p_main_interface->disc_menu_button );
237                     p_main_interface->disc_sizer->Layout();
238                     p_main_interface->disc_sizer->Fit(
239                         p_main_interface->disc_frame );
240                     p_main_interface->disc_menu_button->SetToolTip(
241                         wxU(_( HELP_MENU ) ) );
242                     p_main_interface->disc_prev_button->SetToolTip(
243                         wxU(_( HELP_PCH ) ) );
244                     p_main_interface->disc_next_button->SetToolTip(
245                         wxU(_( HELP_NCH ) ) );
246                 }
247                 else
248                 {
249                     p_main_interface->disc_menu_button->Hide();
250                     p_main_interface->disc_sizer->Hide(
251                         p_main_interface->disc_menu_button );
252
253                     p_main_interface->disc_prev_button->SetToolTip(
254                         wxU(_( HELP_PTR ) ) );
255                     p_main_interface->disc_next_button->SetToolTip(
256                         wxU(_( HELP_NTR ) ) );
257                 }
258
259                 p_main_interface->ShowDiscFrame();
260             }
261
262
263             if( pos.f_float > 0.0 )
264                   {
265                 /* Show the slider if it's position is significant */
266                 p_main_interface->ShowSlider();
267             }
268             else
269             {
270                 p_main_interface->m_slider_timer.Start(1000, wxTIMER_ONE_SHOT);
271             }
272
273             if( p_intf->p_sys->b_playing && p_main_interface->slider_frame->IsShown() )
274             {
275                 /* Update the slider if the user isn't dragging it. */
276                 if( p_intf->p_sys->b_slider_free )
277                 {
278                     char psz_time[ MSTRTIME_MAX_SIZE ];
279                     char psz_total[ MSTRTIME_MAX_SIZE ];
280                     vlc_value_t time;
281                     mtime_t i_seconds;
282
283                     /* Update the value */
284                     if( pos.f_float >= 0.0 )
285                     {
286                         p_intf->p_sys->i_slider_pos =
287                             (int)(SLIDER_MAX_POS * pos.f_float);
288
289                         p_main_interface->slider->SetValue(
290                             p_intf->p_sys->i_slider_pos );
291
292                         var_Get( p_intf->p_sys->p_input, "time", &time );
293                         i_seconds = time.i_time / 1000000;
294                         secstotimestr ( psz_time, i_seconds );
295
296                         var_Get( p_intf->p_sys->p_input, "length",  &time );
297                         i_seconds = time.i_time / 1000000;
298                         secstotimestr ( psz_total, i_seconds );
299
300                         p_main_interface->statusbar->SetStatusText(
301                             wxU(psz_time) + wxString(wxT(" / ")) +
302                             wxU(psz_total), 0 );
303                     }
304                 }
305             }
306 #if 0
307         vlc_mutex_lock( &p_input->stream.stream_lock );
308             if( p_intf->p_sys->p_input->stream.b_seekable &&
309                 !p_main_interface->slider_frame->IsShown() )
310             {
311                 /* Done like this because b_seekable is set slightly after
312                  * the new input object is available. */
313                 p_main_interface->ShowSlider();
314             }
315             if( p_input->stream.b_seekable && p_intf->p_sys->b_playing )
316             {
317                 /* Update the slider if the user isn't dragging it. */
318                 if( p_intf->p_sys->b_slider_free )
319                 {
320                     vlc_value_t pos;
321                     char psz_time[ MSTRTIME_MAX_SIZE ];
322                     char psz_total[ MSTRTIME_MAX_SIZE ];
323                     vlc_value_t time;
324                     mtime_t i_seconds;
325
326                     /* Update the value */
327                     var_Get( p_input, "position", &pos );
328                     if( pos.f_float >= 0.0 )
329                     {
330                         p_intf->p_sys->i_slider_pos =
331                             (int)(SLIDER_MAX_POS * pos.f_float);
332
333                         p_main_interface->slider->SetValue(
334                             p_intf->p_sys->i_slider_pos );
335
336                         var_Get( p_intf->p_sys->p_input, "time", &time );
337                         i_seconds = time.i_time / 1000000;
338                         secstotimestr ( psz_time, i_seconds );
339
340                         var_Get( p_intf->p_sys->p_input, "length",  &time );
341                         i_seconds = time.i_time / 1000000;
342                         secstotimestr ( psz_total, i_seconds );
343
344                         p_main_interface->statusbar->SetStatusText(
345                             wxU(psz_time) + wxString(wxT(" / ")) +
346                             wxU(psz_total), 0 );
347                     }
348                 }
349             }
350         vlc_mutex_unlock( &p_input->stream.stream_lock );
351 #endif
352             /* Take care of the volume, etc... */
353             p_main_interface->Update();
354
355             /* Manage Playing status */
356             var_Get( p_input, "state", &val );
357             if( i_old_playing_status != val.i_int )
358             {
359                 if( val.i_int == PAUSE_S )
360                 {
361                     p_main_interface->TogglePlayButton( PAUSE_S );
362                 }
363                 else
364                 {
365                     p_main_interface->TogglePlayButton( PLAYING_S );
366                 }
367 #ifdef wxHAS_TASK_BAR_ICON
368                 if( p_main_interface->p_systray )
369                 {
370                     if( val.i_int == PAUSE_S )
371                     {
372                         p_main_interface->p_systray->UpdateTooltip( wxU(p_intf->p_sys->p_input->input.p_item->psz_name) + wxString(wxT(" - ")) + wxU(_("Paused")));
373                     }
374                     else
375                     {
376                         p_main_interface->p_systray->UpdateTooltip( wxU(p_intf->p_sys->p_input->input.p_item->psz_name) + wxString(wxT(" - ")) + wxU(_("Playing")));
377                     }
378                 }
379 #endif
380                 i_old_playing_status = val.i_int;
381             }
382
383             /* Manage Speed status */
384             var_Get( p_input, "rate", &val );
385             if( i_old_rate != val.i_int )
386             {
387                 p_main_interface->statusbar->SetStatusText(
388                     wxString::Format(wxT("x%.2f"),
389                     (float)INPUT_RATE_DEFAULT / val.i_int ), 1 );
390                 i_old_rate = val.i_int;
391             }
392         }
393     }
394     else if( p_intf->p_sys->b_playing && !p_intf->b_die )
395     {
396         p_intf->p_sys->b_playing = 0;
397         p_main_interface->TogglePlayButton( PAUSE_S );
398         i_old_playing_status = PAUSE_S;
399     }
400
401     /* Show the interface, if requested */
402     if( p_intf->p_sys->b_intf_show )
403     {
404         p_main_interface->Raise();
405         p_intf->p_sys->b_intf_show = VLC_FALSE;
406     }
407
408     if( p_intf->b_die )
409     {
410         vlc_mutex_unlock( &p_intf->change_lock );
411
412         /* Prepare to die, young Skywalker */
413         p_main_interface->Close(TRUE);
414         return;
415     }
416
417     vlc_mutex_unlock( &p_intf->change_lock );
418 }
419
420 /*****************************************************************************
421  * PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
422  *  We don't show the menu directly here because we don't want the
423  *  caller to block for a too long time.
424  *****************************************************************************/
425 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
426                         vlc_value_t old_val, vlc_value_t new_val, void *param )
427 {
428     intf_thread_t *p_intf = (intf_thread_t *)param;
429
430     if( p_intf->p_sys->pf_show_dialog )
431     {
432         p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU,
433                                        new_val.b_bool, 0 );
434     }
435
436     return VLC_SUCCESS;
437 }
438
439
440 /*****************************************************************************
441  * IntfShowCB: callback triggered by the intf-show playlist variable.
442  *****************************************************************************/
443 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
444                        vlc_value_t old_val, vlc_value_t new_val, void *param )
445 {
446     intf_thread_t *p_intf = (intf_thread_t *)param;
447     p_intf->p_sys->b_intf_show = VLC_TRUE;
448
449     return VLC_SUCCESS;
450 }