]> git.sesse.net Git - vlc/blob - modules/gui/wxwindows/timer.cpp
input.c: doxygenize vlc_input_item_GetInfo
[vlc] / modules / gui / wxwindows / timer.cpp
1 /*****************************************************************************
2  * timer.cpp : wxWindows plugin for vlc
3  *****************************************************************************
4  * Copyright (C) 2000-2003 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             vlc_mutex_lock( &p_playlist->object_lock );
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             vlc_mutex_unlock( &p_playlist->object_lock );
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             b_old_seekable = VLC_FALSE;
136             b_disc_shown = VLC_FALSE;
137
138             char *psz_now_playing = vlc_input_item_GetInfo(
139                 p_intf->p_sys->p_input->input.p_item,
140                 _("Meta-information"), _( "Now Playing" ) );
141             if( psz_now_playing && *psz_now_playing )
142             {
143                 p_main_interface->statusbar->SetStatusText(
144                     wxU(psz_now_playing) + wxT( " - " ) +
145                     wxU(p_intf->p_sys->p_input->input.p_item->psz_name), 2 );
146             }
147             else
148             {
149                 p_main_interface->statusbar->SetStatusText(
150                     wxU(p_intf->p_sys->p_input->input.p_item->psz_name), 2 );
151             }
152             free( psz_now_playing );
153
154             p_main_interface->TogglePlayButton( PLAYING_S );
155 #ifdef wxHAS_TASK_BAR_ICON
156             if( p_main_interface->p_systray )
157             {
158                 p_main_interface->p_systray->UpdateTooltip( wxU(p_intf->p_sys->p_input->input.p_item->psz_name) + wxString(wxT(" - ")) + wxU(_("Playing")));
159             }
160 #endif
161             i_old_playing_status = PLAYING_S;
162         }
163     }
164     else if( p_intf->p_sys->p_input->b_dead )
165     {
166         /* Hide slider and Disc Buttons */
167         p_main_interface->disc_frame->Hide();
168         p_main_interface->slider_sizer->Hide(
169             p_main_interface->disc_frame );
170         p_main_interface->slider_sizer->Layout();
171         p_main_interface->slider_sizer->Fit( p_main_interface->slider_frame );
172
173         p_main_interface->slider_frame->Hide();
174         p_main_interface->frame_sizer->Hide(
175             p_main_interface->slider_frame );
176         p_main_interface->frame_sizer->Layout();
177         p_main_interface->frame_sizer->Fit( p_main_interface );
178
179         p_main_interface->TogglePlayButton( PAUSE_S );
180         i_old_playing_status = PAUSE_S;
181
182         p_main_interface->statusbar->SetStatusText( wxT(""), 0 );
183         p_main_interface->statusbar->SetStatusText( wxT(""), 2 );
184
185 #ifdef wxHAS_TASK_BAR_ICON
186         if( p_main_interface->p_systray )
187         {
188             p_main_interface->p_systray->UpdateTooltip( wxString(wxT("VLC media player - ")) + wxU(_("Stopped")) );
189         }
190 #endif
191         vlc_object_release( p_intf->p_sys->p_input );
192         p_intf->p_sys->p_input = NULL;
193     }
194
195     if( p_intf->p_sys->p_input )
196     {
197         input_thread_t *p_input = p_intf->p_sys->p_input;
198         vlc_value_t val;
199
200         if( !p_input->b_die )
201         {
202             vlc_value_t pos;
203
204             /* New input or stream map change */
205             p_intf->p_sys->b_playing = 1;
206
207             /* Update the item name */
208             char *psz_now_playing = vlc_input_item_GetInfo(
209                 p_intf->p_sys->p_input->input.p_item,
210                 _("Meta-information"), _( "Now Playing" ) );
211             if( psz_now_playing && *psz_now_playing )
212             {
213                 p_main_interface->statusbar->SetStatusText(
214                     wxU(psz_now_playing) + wxT( " - " ) +
215                     wxU(p_intf->p_sys->p_input->input.p_item->psz_name), 2 );
216             }
217             else
218             {
219                 p_main_interface->statusbar->SetStatusText(
220                     wxU(p_intf->p_sys->p_input->input.p_item->psz_name), 2 );
221             }
222             free( psz_now_playing );
223
224             /* Manage the slider */
225             /* FIXME --fenrir */
226             /* Change the name of b_old_seekable into b_show_bar or something like that */
227             var_Get( p_input, "position", &pos );
228
229             var_Change( p_input, "title", VLC_VAR_CHOICESCOUNT, &val, NULL );
230             if( val.i_int > 0 && !b_disc_shown )
231             {
232                 b_disc_shown = VLC_TRUE;
233                 vlc_value_t val;
234
235                     #define HELP_MENU N_("Menu")
236                     #define HELP_PCH N_("Previous chapter")
237                     #define HELP_NCH N_("Next chapter")
238                     #define HELP_PTR N_("Previous track")
239                     #define HELP_NTR N_("Next track")
240
241                 var_Change( p_input, "chapter", VLC_VAR_CHOICESCOUNT, &val,
242                             NULL );
243
244                 if( val.i_int > 0 )
245                 {
246                     p_main_interface->disc_menu_button->Show();
247                     p_main_interface->disc_sizer->Show(
248                         p_main_interface->disc_menu_button );
249                     p_main_interface->disc_sizer->Layout();
250                     p_main_interface->disc_sizer->Fit(
251                         p_main_interface->disc_frame );
252
253                     p_main_interface->disc_menu_button->SetToolTip(
254                         wxU(_( HELP_MENU ) ) );
255                     p_main_interface->disc_prev_button->SetToolTip(
256                         wxU(_( HELP_PCH ) ) );
257                     p_main_interface->disc_next_button->SetToolTip(
258                         wxU(_( HELP_NCH ) ) );
259                 }
260                 else
261                 {
262                     p_main_interface->disc_menu_button->Hide();
263                     p_main_interface->disc_sizer->Hide(
264                         p_main_interface->disc_menu_button );
265
266                     p_main_interface->disc_prev_button->SetToolTip(
267                         wxU(_( HELP_PTR ) ) );
268                     p_main_interface->disc_next_button->SetToolTip(
269                         wxU(_( HELP_NTR ) ) );
270                 }
271
272                 p_main_interface->disc_frame->Show();
273                 p_main_interface->slider_sizer->Show(
274                     p_main_interface->disc_frame );
275             }
276
277             if( ! b_old_seekable )
278             {
279                 if( pos.f_float > 0.0 )
280                 {
281                     /* Done like this, as it's the only way to know if the */
282                     /* slider has to be displayed */
283                     b_old_seekable = VLC_TRUE;
284                     p_main_interface->slider_frame->Show();
285                     p_main_interface->frame_sizer->Show(
286                         p_main_interface->slider_frame );
287                     p_main_interface->frame_sizer->Layout();
288                     p_main_interface->frame_sizer->Fit( p_main_interface );
289                 }
290             }
291
292             if( p_intf->p_sys->b_playing && b_old_seekable )
293             {
294                 /* Update the slider if the user isn't dragging it. */
295                 if( p_intf->p_sys->b_slider_free )
296                 {
297                     char psz_time[ MSTRTIME_MAX_SIZE ];
298                     char psz_total[ MSTRTIME_MAX_SIZE ];
299                     vlc_value_t time;
300                     mtime_t i_seconds;
301
302                     /* Update the value */
303                     if( pos.f_float >= 0.0 )
304                     {
305                         p_intf->p_sys->i_slider_pos =
306                             (int)(SLIDER_MAX_POS * pos.f_float);
307
308                         p_main_interface->slider->SetValue(
309                             p_intf->p_sys->i_slider_pos );
310
311                         var_Get( p_intf->p_sys->p_input, "time", &time );
312                         i_seconds = time.i_time / 1000000;
313                         secstotimestr ( psz_time, i_seconds );
314
315                         var_Get( p_intf->p_sys->p_input, "length",  &time );
316                         i_seconds = time.i_time / 1000000;
317                         secstotimestr ( psz_total, i_seconds );
318
319                         p_main_interface->statusbar->SetStatusText(
320                             wxU(psz_time) + wxString(wxT(" / ")) +
321                             wxU(psz_total), 0 );
322                     }
323                 }
324             }
325 #if 0
326         vlc_mutex_lock( &p_input->stream.stream_lock );
327             if( p_intf->p_sys->p_input->stream.b_seekable && !b_old_seekable )
328             {
329                 /* Done like this because b_seekable is set slightly after
330                  * the new input object is available. */
331                 b_old_seekable = VLC_TRUE;
332                 p_main_interface->slider_frame->Show();
333                 p_main_interface->frame_sizer->Show(
334                     p_main_interface->slider_frame );
335                 p_main_interface->frame_sizer->Layout();
336                 p_main_interface->frame_sizer->Fit( p_main_interface );
337             }
338             if( p_input->stream.b_seekable && p_intf->p_sys->b_playing )
339             {
340                 /* Update the slider if the user isn't dragging it. */
341                 if( p_intf->p_sys->b_slider_free )
342                 {
343                     vlc_value_t pos;
344                     char psz_time[ MSTRTIME_MAX_SIZE ];
345                     char psz_total[ MSTRTIME_MAX_SIZE ];
346                     vlc_value_t time;
347                     mtime_t i_seconds;
348
349                     /* Update the value */
350                     var_Get( p_input, "position", &pos );
351                     if( pos.f_float >= 0.0 )
352                     {
353                         p_intf->p_sys->i_slider_pos =
354                             (int)(SLIDER_MAX_POS * pos.f_float);
355
356                         p_main_interface->slider->SetValue(
357                             p_intf->p_sys->i_slider_pos );
358
359                         var_Get( p_intf->p_sys->p_input, "time", &time );
360                         i_seconds = time.i_time / 1000000;
361                         secstotimestr ( psz_time, i_seconds );
362
363                         var_Get( p_intf->p_sys->p_input, "length",  &time );
364                         i_seconds = time.i_time / 1000000;
365                         secstotimestr ( psz_total, i_seconds );
366
367                         p_main_interface->statusbar->SetStatusText(
368                             wxU(psz_time) + wxString(wxT(" / ")) +
369                             wxU(psz_total), 0 );
370                     }
371                 }
372             }
373         vlc_mutex_unlock( &p_input->stream.stream_lock );
374 #endif
375             /* Take care of the volume, etc... */
376             p_main_interface->Update();
377
378             /* Manage Playing status */
379             var_Get( p_input, "state", &val );
380             if( i_old_playing_status != val.i_int )
381             {
382                 if( val.i_int == PAUSE_S )
383                 {
384                     p_main_interface->TogglePlayButton( PAUSE_S );
385                 }
386                 else
387                 {
388                     p_main_interface->TogglePlayButton( PLAYING_S );
389                 }
390 #ifdef wxHAS_TASK_BAR_ICON
391                 if( p_main_interface->p_systray )
392                 {
393                     if( val.i_int == PAUSE_S )
394                     {
395                         p_main_interface->p_systray->UpdateTooltip( wxU(p_intf->p_sys->p_input->input.p_item->psz_name) + wxString(wxT(" - ")) + wxU(_("Paused")));
396                     }
397                     else
398                     {
399                         p_main_interface->p_systray->UpdateTooltip( wxU(p_intf->p_sys->p_input->input.p_item->psz_name) + wxString(wxT(" - ")) + wxU(_("Playing")));
400                     }
401                 }
402 #endif
403                 i_old_playing_status = val.i_int;
404             }
405
406             /* Manage Speed status */
407             var_Get( p_input, "rate", &val );
408             if( i_old_rate != val.i_int )
409             {
410                 p_main_interface->statusbar->SetStatusText(
411                     wxString::Format(wxT("x%.2f"),
412                     (float)INPUT_RATE_DEFAULT / val.i_int ), 1 );
413                 i_old_rate = val.i_int;
414             }
415         }
416
417     }
418     else if( p_intf->p_sys->b_playing && !p_intf->b_die )
419     {
420         p_intf->p_sys->b_playing = 0;
421         p_main_interface->TogglePlayButton( PAUSE_S );
422         i_old_playing_status = PAUSE_S;
423     }
424
425     /* Show the interface, if requested */
426     if( p_intf->p_sys->b_intf_show )
427     {
428         p_main_interface->Raise();
429         p_intf->p_sys->b_intf_show = VLC_FALSE;
430     }
431
432     if( p_intf->b_die )
433     {
434         vlc_mutex_unlock( &p_intf->change_lock );
435
436         /* Prepare to die, young Skywalker */
437         p_main_interface->Close(TRUE);
438         return;
439     }
440
441     vlc_mutex_unlock( &p_intf->change_lock );
442 }
443
444 /*****************************************************************************
445  * PopupMenuCB: callback triggered by the intf-popupmenu playlist variable.
446  *  We don't show the menu directly here because we don't want the
447  *  caller to block for a too long time.
448  *****************************************************************************/
449 static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
450                         vlc_value_t old_val, vlc_value_t new_val, void *param )
451 {
452     intf_thread_t *p_intf = (intf_thread_t *)param;
453
454     if( p_intf->p_sys->pf_show_dialog )
455     {
456         p_intf->p_sys->pf_show_dialog( p_intf, INTF_DIALOG_POPUPMENU,
457                                        new_val.b_bool, 0 );
458     }
459
460     return VLC_SUCCESS;
461 }
462
463 /*****************************************************************************
464  * IntfShowCB: callback triggered by the intf-show playlist variable.
465  *****************************************************************************/
466 static int IntfShowCB( vlc_object_t *p_this, const char *psz_variable,
467                        vlc_value_t old_val, vlc_value_t new_val, void *param )
468 {
469     intf_thread_t *p_intf = (intf_thread_t *)param;
470     p_intf->p_sys->b_intf_show = VLC_TRUE;
471
472     return VLC_SUCCESS;
473 }