1 /*****************************************************************************
2 * slider_manager.cpp : Manage an input slider
3 *****************************************************************************
4 * Copyright (C) 2000-2005 the VideoLAN team
7 * Authors: Gildas Bazin <gbazin@videolan.org>
8 * Clément Stenac <zorglub@videolan.org>
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 #include "input_manager.hpp"
26 #include "interface.hpp"
31 /* include the toolbar graphics */
32 #include "bitmaps/prev.xpm"
33 #include "bitmaps/next.xpm"
34 #include "bitmaps/playlist.xpm"
36 /* IDs for the controls */
39 SliderScroll_Event = wxID_HIGHEST,
46 BEGIN_EVENT_TABLE(InputManager, wxPanel)
48 EVT_COMMAND_SCROLL(SliderScroll_Event, InputManager::OnSliderUpdate)
50 /* Disc Buttons events */
51 EVT_BUTTON(DiscMenu_Event, InputManager::OnDiscMenu)
52 EVT_BUTTON(DiscPrev_Event, InputManager::OnDiscPrev)
53 EVT_BUTTON(DiscNext_Event, InputManager::OnDiscNext)
58 #define STATUS_PLAYING 1
59 #define STATUS_PAUSE 2
61 /*****************************************************************************
63 *****************************************************************************/
64 InputManager::InputManager( intf_thread_t *_p_intf, Interface *_p_main_intf,
69 p_main_intf = _p_main_intf;
71 i_old_playing_status = STATUS_STOP;
72 i_old_rate = INPUT_RATE_DEFAULT;
73 b_slider_free = VLC_TRUE;
74 i_input_hide_delay = 0;
77 slider = new wxSlider( this, SliderScroll_Event, 0, 0, SLIDER_MAX_POS );
78 /* Add mouse click on slider */
79 slider->Connect( wxEVT_LEFT_DOWN,
80 wxMouseEventHandler( InputManager::OnSliderClick ),
83 /* Create disc buttons */
84 disc_frame = new wxPanel( this );
86 disc_menu_button = new wxBitmapButton( disc_frame, DiscMenu_Event,
87 wxBitmap( playlist_xpm ) );
88 disc_prev_button = new wxBitmapButton( disc_frame, DiscPrev_Event,
89 wxBitmap( prev_xpm ) );
90 disc_next_button = new wxBitmapButton( disc_frame, DiscNext_Event,
91 wxBitmap( next_xpm ) );
93 disc_sizer = new wxBoxSizer( wxHORIZONTAL );
94 disc_sizer->Add( disc_menu_button, 1, wxEXPAND | wxLEFT | wxRIGHT, 1 );
95 disc_sizer->Add( disc_prev_button, 1, wxEXPAND | wxLEFT | wxRIGHT, 1 );
96 disc_sizer->Add( disc_next_button, 1, wxEXPAND | wxLEFT | wxRIGHT, 1 );
97 disc_frame->SetSizer( disc_sizer );
100 /* Add everything to the panel */
101 sizer = new wxBoxSizer( wxHORIZONTAL );
103 sizer->Add( slider, 1, wxEXPAND | wxALL, 5 );
104 sizer->Add( disc_frame, 0, wxALL, 2 );
106 /* Hide by default */
107 sizer->Hide( disc_frame );
108 sizer->Hide( slider );
114 InputManager::~InputManager()
116 vlc_mutex_lock( &p_intf->change_lock );
117 if( p_intf->p_sys->p_input ) vlc_object_release( p_intf->p_sys->p_input );
118 p_intf->p_sys->p_input = NULL;
119 vlc_mutex_unlock( &p_intf->change_lock );
122 /*****************************************************************************
124 *****************************************************************************/
125 vlc_bool_t InputManager::IsPlaying()
127 return (p_input && !p_input->b_die);
130 /*****************************************************************************
132 *****************************************************************************/
133 void InputManager::UpdateInput()
135 playlist_t *p_playlist =
136 (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
138 if( p_playlist != NULL )
140 LockPlaylist( p_intf->p_sys, p_playlist );
141 p_input = p_intf->p_sys->p_input = p_playlist->p_input;
142 if( p_intf->p_sys->p_input )
143 vlc_object_yield( p_intf->p_sys->p_input );
144 UnlockPlaylist( p_intf->p_sys, p_playlist );
145 vlc_object_release( p_playlist );
149 void InputManager::UpdateNowPlaying()
151 char *psz_now_playing = p_input->input.p_item->p_meta->psz_nowplaying ?
152 strdup( p_input->input.p_item->p_meta->psz_nowplaying ):
154 if( psz_now_playing && *psz_now_playing )
156 p_main_intf->statusbar->SetStatusText(
157 wxString(wxU(psz_now_playing)) + wxT( " - " ) +
158 wxU(p_input->input.p_item->psz_name), 2 );
162 p_main_intf->statusbar->SetStatusText(
163 wxU(p_input->input.p_item->psz_name), 2 );
165 free( psz_now_playing );
168 void InputManager::UpdateButtons( vlc_bool_t b_play )
172 if( i_old_playing_status == STATUS_STOP ) return;
174 i_old_playing_status = STATUS_STOP;
175 p_main_intf->TogglePlayButton( PAUSE_S );
176 p_main_intf->statusbar->SetStatusText( wxT(""), 0 );
177 p_main_intf->statusbar->SetStatusText( wxT(""), 2 );
179 /* wxCocoa pretends to support this, but at least 2.6.x doesn't */
181 #ifdef wxHAS_TASK_BAR_ICON
182 if( p_main_intf->p_systray )
184 p_main_intf->p_systray->UpdateTooltip(
185 wxString(wxT("VLC media player - ")) + wxU(_("Stopped")) );
193 /* Manage Playing status */
195 var_Get( p_input, "state", &val );
196 val.i_int = val.i_int == PAUSE_S ? STATUS_PAUSE : STATUS_PLAYING;
197 if( i_old_playing_status != val.i_int )
199 i_old_playing_status = val.i_int;
200 p_main_intf->TogglePlayButton( val.i_int == STATUS_PAUSE ?
201 PAUSE_S : PLAYING_S );
203 /* wxCocoa pretends to support this, but at least 2.6.x doesn't */
205 #ifdef wxHAS_TASK_BAR_ICON
206 if( p_main_intf->p_systray )
208 p_main_intf->p_systray->UpdateTooltip(
209 wxU(p_input->input.p_item->psz_name) + wxString(wxT(" - ")) +
210 (val.i_int == PAUSE_S ? wxU(_("Paused")) : wxU(_("Playing"))));
217 void InputManager::UpdateDiscButtons()
220 var_Change( p_input, "title", VLC_VAR_CHOICESCOUNT, &val, NULL );
221 if( val.i_int > 0 && !disc_frame->IsShown() )
225 #define HELP_MENU N_("Menu")
226 #define HELP_PCH N_("Previous chapter")
227 #define HELP_NCH N_("Next chapter")
228 #define HELP_PTR N_("Previous track")
229 #define HELP_NTR N_("Next track")
231 var_Change( p_input, "chapter", VLC_VAR_CHOICESCOUNT, &val, NULL );
235 disc_menu_button->Show();
236 disc_sizer->Show( disc_menu_button );
237 disc_sizer->Layout();
238 disc_sizer->Fit( disc_frame );
239 disc_menu_button->SetToolTip( wxU(_( HELP_MENU ) ) );
240 disc_prev_button->SetToolTip( wxU(_( HELP_PCH ) ) );
241 disc_next_button->SetToolTip( wxU(_( HELP_NCH ) ) );
245 disc_menu_button->Hide();
246 disc_sizer->Hide( disc_menu_button );
247 disc_prev_button->SetToolTip( wxU(_( HELP_PTR ) ) );
248 disc_next_button->SetToolTip( wxU(_( HELP_NTR ) ) );
253 else if( val.i_int == 0 && disc_frame->IsShown() )
259 void InputManager::HideSlider()
264 void InputManager::HideDiscFrame()
266 ShowDiscFrame( false );
269 void InputManager::UpdateTime()
271 char psz_time[ MSTRTIME_MAX_SIZE ], psz_total[ MSTRTIME_MAX_SIZE ];
274 i_seconds = var_GetTime( p_intf->p_sys->p_input, "length" ) / 1000000;
275 secstotimestr( psz_total, i_seconds );
277 i_seconds = var_GetTime( p_intf->p_sys->p_input, "time" ) / 1000000;
278 secstotimestr( psz_time, i_seconds );
280 p_main_intf->statusbar->SetStatusText(
281 wxU(psz_time) + wxString(wxT(" / ")) +wxU(psz_total), 0 );
284 void InputManager::Update()
286 /* Update the input */
287 if( p_input == NULL )
293 slider->SetValue( 0 );
295 else if( !i_input_hide_delay )
297 i_input_hide_delay = mdate() + 200000;
299 else if( i_input_hide_delay < mdate() )
301 if( disc_frame->IsShown() ) HideDiscFrame();
302 if( slider->IsShown() ) HideSlider();
303 i_input_hide_delay = 0;
306 else if( p_input->b_dead )
308 UpdateButtons( VLC_FALSE );
309 vlc_object_release( p_input );
314 i_input_hide_delay = 0;
317 if( p_input && !p_input->b_die )
319 vlc_value_t pos, len;
322 UpdateButtons( VLC_TRUE );
326 /* Really manage the slider */
327 var_Get( p_input, "position", &pos );
328 var_Get( p_input, "length", &len );
330 if( pos.f_float > 0 && !slider->IsShown() ) ShowSlider();
331 else if( pos.f_float <= 0 && slider->IsShown() ) HideSlider();
333 /* Update the slider if the user isn't dragging it. */
334 if( slider->IsShown() && b_slider_free )
336 i_slider_pos = (int)(SLIDER_MAX_POS * pos.f_float);
337 slider->SetValue( i_slider_pos );
340 /* Manage Speed status */
342 var_Get( p_input, "rate", &val );
343 if( i_old_rate != val.i_int )
345 p_main_intf->statusbar->SetStatusText(
346 wxString::Format(wxT("x%.2f"),
347 (float)INPUT_RATE_DEFAULT / val.i_int ), 1 );
348 i_old_rate = val.i_int;
353 /*****************************************************************************
355 *****************************************************************************/
356 void InputManager::OnDiscMenu( wxCommandEvent& WXUNUSED(event) )
358 input_thread_t *p_input =
359 (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
363 vlc_value_t val; val.i_int = 2;
365 var_Set( p_input, "title 0", val);
366 vlc_object_release( p_input );
370 void InputManager::OnDiscPrev( wxCommandEvent& WXUNUSED(event) )
372 input_thread_t *p_input =
373 (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
377 int i_type = var_Type( p_input, "prev-chapter" );
378 vlc_value_t val; val.b_bool = VLC_TRUE;
380 var_Set( p_input, ( i_type & VLC_VAR_TYPE ) != 0 ?
381 "prev-chapter" : "prev-title", val );
383 vlc_object_release( p_input );
387 void InputManager::OnDiscNext( wxCommandEvent& WXUNUSED(event) )
389 input_thread_t *p_input =
390 (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
394 int i_type = var_Type( p_input, "next-chapter" );
395 vlc_value_t val; val.b_bool = VLC_TRUE;
397 var_Set( p_input, ( i_type & VLC_VAR_TYPE ) != 0 ?
398 "next-chapter" : "next-title", val );
400 vlc_object_release( p_input );
404 void InputManager::OnSliderUpdate( wxScrollEvent& event )
406 vlc_mutex_lock( &p_intf->change_lock );
409 if( event.GetEventType() == wxEVT_SCROLL_THUMBRELEASE
410 || event.GetEventType() == wxEVT_SCROLL_ENDSCROLL )
413 if( i_slider_pos != event.GetPosition() && p_intf->p_sys->p_input )
416 pos.f_float = (float)event.GetPosition() / (float)SLIDER_MAX_POS;
417 var_Set( p_intf->p_sys->p_input, "position", pos );
421 b_slider_free = VLC_TRUE;
425 b_slider_free = VLC_FALSE;
426 if( p_intf->p_sys->p_input ) UpdateTime();
431 vlc_mutex_unlock( &p_intf->change_lock );
434 void InputManager::OnSliderClick( wxMouseEvent& event )
436 wxSlider* slider = wxStaticCast( event.GetEventObject(), wxSlider );
437 int i_min = slider->GetMin();
438 int i_max = slider->GetMax();
439 int i_pos = event.GetPosition().x;
440 int i_dim = slider->GetClientSize().x;
441 int i_val = i_min + ( i_pos * ( i_max - i_min + 1 ) ) / i_dim;
443 if( i_pos < 0 || i_pos >= i_dim ) return;
445 vlc_mutex_lock( &p_intf->change_lock );
447 slider->SetValue( i_val );
449 if( i_slider_pos != i_val && p_intf->p_sys->p_input )
452 pos.f_float = (float)i_val / (float)SLIDER_MAX_POS;
453 var_Set( p_intf->p_sys->p_input, "position", pos );
456 vlc_mutex_unlock( &p_intf->change_lock );
461 void InputManager::ShowSlider( bool show )
463 if( !!show == !!slider->IsShown() ) return;
465 UpdateVideoWindow( p_intf, p_main_intf->video_window );
467 sizer->Show( slider, show );
470 wxCommandEvent intf_event( wxEVT_INTF, 0 );
471 p_main_intf->AddPendingEvent( intf_event );
474 void InputManager::ShowDiscFrame( bool show )
476 if( !!show == !!disc_frame->IsShown() ) return;
478 UpdateVideoWindow( p_intf, p_main_intf->video_window );
480 sizer->Show( disc_frame, show );
483 wxCommandEvent intf_event( wxEVT_INTF, 0 );
484 p_main_intf->AddPendingEvent( intf_event );