X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fgui%2Fqt4%2Finput_manager.cpp;h=5a48df962e4583c07f951a8068d1de24e1cde754;hb=9ac719c31809fb4f72abe7e6c98e6a9db0bc2cf5;hp=82bdb04729e4d0b6f05979f5ee385b582b1cf51d;hpb=9d5e75a7a5643a2144dc561fc246a7a3ca7e5fb0;p=vlc diff --git a/modules/gui/qt4/input_manager.cpp b/modules/gui/qt4/input_manager.cpp index 82bdb04729..5a48df962e 100644 --- a/modules/gui/qt4/input_manager.cpp +++ b/modules/gui/qt4/input_manager.cpp @@ -29,6 +29,7 @@ #include "input_manager.hpp" #include +#include #include @@ -36,10 +37,26 @@ static int ItemChanged( vlc_object_t *, const char *, vlc_value_t, vlc_value_t, void * ); +static int LeafToParent( vlc_object_t *, const char *, + vlc_value_t, vlc_value_t, void * ); static int PLItemChanged( vlc_object_t *, const char *, vlc_value_t, vlc_value_t, void * ); +static int PLItemAppended( vlc_object_t *, const char *, + vlc_value_t, vlc_value_t, void * ); +static int PLItemRemoved( vlc_object_t *, const char *, + vlc_value_t, vlc_value_t, void * ); static int VolumeChanged( vlc_object_t *, const char *, vlc_value_t, vlc_value_t, void * ); +static int SoundMuteChanged( vlc_object_t *, const char *, + vlc_value_t, vlc_value_t, void * ); + +static int RandomChanged( vlc_object_t *, const char *, + vlc_value_t, vlc_value_t, void * ); +static int LoopChanged( vlc_object_t *, const char *, + vlc_value_t, vlc_value_t, void * ); +static int RepeatChanged( vlc_object_t *, const char *, + vlc_value_t, vlc_value_t, void * ); + static int InputEvent( vlc_object_t *, const char *, vlc_value_t, vlc_value_t, void * ); @@ -61,6 +78,7 @@ InputManager::InputManager( QObject *parent, intf_thread_t *_p_intf) : oldName = ""; artUrl = ""; p_input = NULL; + p_input_vbi = NULL; i_rate = 0; p_item = NULL; b_video = false; @@ -93,12 +111,14 @@ void InputManager::setInput( input_thread_t *_p_input ) UpdateVout(); addCallbacks(); p_item = input_GetItem( p_input ); + emit rateChanged( INPUT_RATE_DEFAULT / var_GetFloat( p_input, "rate" ) ); } else { p_input = NULL; p_item = NULL; - emit rateChanged( INPUT_RATE_DEFAULT ); + assert( !p_input_vbi ); + emit rateChanged( INPUT_RATE_DEFAULT / var_InheritFloat( p_intf, "rate" ) ); } } @@ -119,11 +139,17 @@ void InputManager::delInput() timeA = 0; timeB = 0; + if( p_input_vbi ) + { + vlc_object_release( p_input_vbi ); + p_input_vbi = NULL; + } + vlc_object_release( p_input ); p_input = NULL; emit positionUpdated( -1.0, 0 ,0 ); - emit rateChanged( INPUT_RATE_DEFAULT ); /* TODO: Do we want this ? */ + emit rateChanged( INPUT_RATE_DEFAULT / var_InheritFloat( p_intf, "rate" ) ); emit nameChanged( "" ); emit chapterChanged( 0 ); emit titleChanged( 0 ); @@ -141,6 +167,8 @@ void InputManager::delInput() emit encryptionChanged( false ); emit recordingStateChanged( false ); + + emit cachingChanged( 1 ); } /* Convert the event from the callbacks in actions */ @@ -149,16 +177,12 @@ void InputManager::customEvent( QEvent *event ) int i_type = event->type(); IMEvent *ple = static_cast(event); + if( i_type == ItemChanged_Type ) + UpdateMeta( ple->p_item ); + if( !hasInput() ) return; -#ifndef NDEBUG - if( i_type != PositionUpdate_Type && - i_type != StatisticsUpdate_Type && - i_type != ItemChanged_Type ) - msg_Dbg( p_intf, "New Event: type %i", i_type ); -#endif - /* Actions */ switch( i_type ) { @@ -177,7 +201,6 @@ void InputManager::customEvent( QEvent *event ) UpdateArt(); /* Update duration of file */ } - UpdateMeta( ple->p_item->i_id ); break; case ItemStateChanged_Type: // TODO: Fusion with above state @@ -363,10 +386,11 @@ static int VbiEvent( vlc_object_t *, const char *, void InputManager::UpdatePosition() { /* Update position */ - int i_length, i_time; /* Int is enough, since we store seconds */ + int i_length; + int64_t i_time; float f_pos; i_length = var_GetTime( p_input , "length" ) / 1000000; - i_time = var_GetTime( p_input , "time") / 1000000; + i_time = var_GetTime( p_input , "time"); f_pos = var_GetFloat( p_input , "position" ); emit positionUpdated( f_pos, i_time, i_length ); } @@ -375,6 +399,7 @@ void InputManager::UpdateNavigation() { /* Update navigation status */ vlc_value_t val; val.i_int = 0; + vlc_value_t val2; val2.i_int = 0; if( hasInput() ) var_Change( p_input, "title", VLC_VAR_CHOICESCOUNT, &val, NULL ); @@ -384,10 +409,9 @@ void InputManager::UpdateNavigation() emit titleChanged( true ); msg_Dbg( p_intf, "Title %i", val.i_int ); /* p_input != NULL since val.i_int != 0 */ - val.i_int = 0; - var_Change( p_input, "chapter", VLC_VAR_CHOICESCOUNT, &val, NULL ); - emit chapterChanged( (val.i_int > 0) ); - msg_Dbg( p_intf, "Chapter: %i", val.i_int ); + var_Change( p_input, "chapter", VLC_VAR_CHOICESCOUNT, &val2, NULL ); + emit chapterChanged( (val2.i_int > 1) || ( val2.i_int > 0 && val.i_int > 1 ) ); + msg_Dbg( p_intf, "Chapter: %i", val2.i_int ); } else emit titleChanged( false ); @@ -407,7 +431,7 @@ void InputManager::UpdateStatus() void InputManager::UpdateRate() { /* Update Rate */ - int i_new_rate = var_GetInteger( p_input, "rate"); + int i_new_rate = INPUT_RATE_DEFAULT / var_GetFloat( p_input, "rate" ); if( i_new_rate != i_rate ) { i_rate = i_new_rate; @@ -490,21 +514,23 @@ void InputManager::UpdateTeletext() int i_page = 100; bool b_transparent = false; - vlc_object_t *p_vbi = (vlc_object_t *) - vlc_object_find_name( p_input, "zvbi", FIND_CHILD ); + if( p_input_vbi ) + { + var_DelCallback( p_input_vbi, "vbi-page", VbiEvent, this ); + vlc_object_release( p_input_vbi ); + } - if( p_vbi ) + if( input_GetEsObjects( p_input, i_teletext_es, &p_input_vbi, NULL, NULL ) ) + p_input_vbi = NULL; + + if( p_input_vbi ) { - /* We deleted it (if not here, it does not harm), because - * var_AddCallback will silently add a duplicated one */ - var_DelCallback( p_vbi, "vbi-page", VbiEvent, this ); /* This callback is not remove explicitly, but interfaces * are guaranted to outlive input */ - var_AddCallback( p_vbi, "vbi-page", VbiEvent, this ); + var_AddCallback( p_input_vbi, "vbi-page", VbiEvent, this ); - i_page = var_GetInteger( p_vbi, "vbi-page" ); - b_transparent = !var_GetBool( p_vbi, "vbi-opaque" ); - vlc_object_release( p_vbi ); + i_page = var_GetInteger( p_input_vbi, "vbi-page" ); + b_transparent = !var_GetBool( p_input_vbi, "vbi-opaque" ); } emit newTelexPageSet( i_page ); emit teletextTransparencyActivated( b_transparent ); @@ -562,7 +588,7 @@ void InputManager::UpdateCaching() if( f_newCache != f_cache ) { f_cache = f_newCache; - /* Update rate */ + /* Update cache */ emit cachingChanged( f_cache ); } } @@ -571,9 +597,7 @@ void InputManager::requestArtUpdate() { if( hasInput() ) { - playlist_t *p_playlist = pl_Hold( p_intf ); - playlist_AskForArtEnqueue( p_playlist, input_GetItem( p_input ), pl_Unlocked ); - pl_Release( p_intf ); + playlist_AskForArtEnqueue( pl_Get(p_intf), input_GetItem( p_input ) ); } else { @@ -583,21 +607,39 @@ void InputManager::requestArtUpdate() } } -void InputManager::UpdateArt() +const QString InputManager::decodeArtURL( input_item_t *p_item ) { - QString url; + assert( p_item ); - if( hasInput() ) + char *psz_art = input_item_GetArtURL( p_item ); + if( psz_art ) { - char *psz_art = input_item_GetArtURL( input_GetItem( p_input ) ); - url = qfu( psz_art ); + char *psz = make_path( psz_art ); free( psz_art ); + psz_art = psz; } - url = url.replace( "file://", QString("" ) ); + +#if 0 /* Taglib seems to define a attachment://, It won't work yet */ - url = url.replace( "attachment://", QString("" ) ); + url = url.replace( "attachment://", "" ); +#endif + return qfu( psz_art ? psz_art : "" ); +} + +void InputManager::UpdateArt() +{ + QString url; + + if( hasInput() ) + url = decodeArtURL( input_GetItem( p_input ) ); + + /* the art hasn't changed, no need to update */ + if(artUrl == url) + return; + /* Update Art meta */ - emit artChanged( url ); + artUrl = url; + emit artChanged( artUrl ); } inline void InputManager::UpdateStats() @@ -605,9 +647,9 @@ inline void InputManager::UpdateStats() emit statisticsUpdated( input_GetItem( p_input ) ); } -inline void InputManager::UpdateMeta( int id ) +inline void InputManager::UpdateMeta( input_item_t *p_item ) { - emit metaChanged( id ); + emit metaChanged( p_item ); } inline void InputManager::UpdateMeta() @@ -642,6 +684,7 @@ void InputManager::sliderUpdate( float new_pos ) { if( hasInput() ) var_SetFloat( p_input, "position", new_pos ); + emit seekRequested( new_pos ); } /* User togglePlayPause */ @@ -661,8 +704,8 @@ void InputManager::sectionPrev() if( hasInput() ) { int i_type = var_Type( p_input, "next-chapter" ); - var_SetVoid( p_input, (i_type & VLC_VAR_TYPE) != 0 ? - "prev-chapter":"prev-title" ); + var_TriggerCallback( p_input, (i_type & VLC_VAR_TYPE) != 0 ? + "prev-chapter":"prev-title" ); } } @@ -671,8 +714,8 @@ void InputManager::sectionNext() if( hasInput() ) { int i_type = var_Type( p_input, "next-chapter" ); - var_SetVoid( p_input, (i_type & VLC_VAR_TYPE) != 0 ? - "next-chapter":"next-title" ); + var_TriggerCallback( p_input, (i_type & VLC_VAR_TYPE) != 0 ? + "next-chapter":"next-title" ); } } @@ -705,20 +748,14 @@ void InputManager::sectionMenu() /* Set a new Teletext Page */ void InputManager::telexSetPage( int page ) { - if( hasInput() ) + if( hasInput() && p_input_vbi ) { const int i_teletext_es = var_GetInteger( p_input, "teletext-es" ); if( i_teletext_es >= 0 ) { - vlc_object_t *p_vbi = (vlc_object_t *) vlc_object_find_name( p_input, - "zvbi", FIND_CHILD ); - if( p_vbi ) - { - var_SetInteger( p_vbi, "vbi-page", page ); - vlc_object_release( p_vbi ); - emit newTelexPageSet( page ); - } + var_SetInteger( p_input_vbi, "vbi-page", page ); + emit newTelexPageSet( page ); } } } @@ -726,16 +763,10 @@ void InputManager::telexSetPage( int page ) /* Set the transparency on teletext */ void InputManager::telexSetTransparency( bool b_transparentTelextext ) { - if( hasInput() ) + if( hasInput() && p_input_vbi ) { - vlc_object_t *p_vbi = (vlc_object_t *) vlc_object_find_name( p_input, - "zvbi", FIND_CHILD ); - if( p_vbi ) - { - var_SetBool( p_vbi, "vbi-opaque", !b_transparentTelextext ); - vlc_object_release( p_vbi ); - emit teletextTransparencyActivated( b_transparentTelextext ); - } + var_SetBool( p_input_vbi, "vbi-opaque", !b_transparentTelextext ); + emit teletextTransparencyActivated( b_transparentTelextext ); } } @@ -768,21 +799,21 @@ void InputManager::reverse() { if( hasInput() ) { - int i_rate = var_GetInteger( p_input, "rate" ); - var_SetInteger( p_input, "rate", -i_rate ); + float f_rate = var_GetFloat( p_input, "rate" ); + var_SetFloat( p_input, "rate", -f_rate ); } } void InputManager::slower() { if( hasInput() ) - var_SetVoid( p_input, "rate-slower" ); + var_TriggerCallback( p_input, "rate-slower" ); } void InputManager::faster() { if( hasInput() ) - var_SetVoid( p_input, "rate-faster" ); + var_TriggerCallback( p_input, "rate-faster" ); } void InputManager::littlefaster() @@ -798,18 +829,19 @@ void InputManager::littleslower() void InputManager::normalRate() { if( hasInput() ) - var_SetInteger( p_input, "rate", INPUT_RATE_DEFAULT ); + var_SetFloat( p_input, "rate", 1. ); } void InputManager::setRate( int new_rate ) { if( hasInput() ) - var_SetInteger( p_input, "rate", new_rate ); + var_SetFloat( p_input, "rate", + (float)INPUT_RATE_DEFAULT / (float)new_rate ); } void InputManager::jumpFwd() { - int i_interval = config_GetInt( p_input, "short-jump-size" ); + int i_interval = var_InheritInteger( p_input, "short-jump-size" ); if( i_interval > 0 ) { mtime_t val = (mtime_t)(i_interval) * 1000000L; @@ -819,7 +851,7 @@ void InputManager::jumpFwd() void InputManager::jumpBwd() { - int i_interval = config_GetInt( p_input, "short-jump-size" ); + int i_interval = var_InheritInteger( p_input, "short-jump-size" ); if( i_interval > 0 ) { mtime_t val = -1 *(mtime_t)(i_interval) * 1000000L; @@ -837,26 +869,25 @@ void InputManager::setAtoB() { timeB = var_GetTime( THEMIM->getInput(), "time" ); var_SetTime( THEMIM->getInput(), "time" , timeA ); - CONNECT( this, positionUpdated( float, int, int ), - this, AtoBLoop( float, int, int ) ); + CONNECT( this, positionUpdated( float, int64_t, int ), + this, AtoBLoop( float, int64_t, int ) ); } else { timeA = 0; timeB = 0; - disconnect( this, SIGNAL( positionUpdated( float, int, int ) ), - this, SLOT( AtoBLoop( float, int, int ) ) ); + disconnect( this, SIGNAL( positionUpdated( float, int64_t, int ) ), + this, SLOT( AtoBLoop( float, int64_t, int ) ) ); } emit AtoBchanged( (timeA != 0 ), (timeB != 0 ) ); } /* Function called regularly when in an AtoB loop */ -void InputManager::AtoBLoop( float, int i_time, int ) +void InputManager::AtoBLoop( float, int64_t i_time, int ) { if( timeB ) { - if( ( i_time >= (int)( timeB/1000000 ) ) - || ( i_time < (int)( timeA/1000000 ) ) ) + if( i_time >= timeB || i_time < timeA ) var_SetTime( THEMIM->getInput(), "time" , timeA ); } } @@ -877,12 +908,19 @@ MainInputManager::MainInputManager( intf_thread_t *_p_intf ) var_AddCallback( THEPL, "item-change", ItemChanged, im ); var_AddCallback( THEPL, "item-current", PLItemChanged, this ); var_AddCallback( THEPL, "activity", PLItemChanged, this ); + var_AddCallback( THEPL, "leaf-to-parent", LeafToParent, this ); + var_AddCallback( THEPL, "playlist-item-append", PLItemAppended, this ); + var_AddCallback( THEPL, "playlist-item-deleted", PLItemRemoved, this ); + var_AddCallback( THEPL, "random", RandomChanged, this ); + var_AddCallback( THEPL, "repeat", RepeatChanged, this ); + var_AddCallback( THEPL, "loop", LoopChanged, this ); - var_AddCallback( p_intf->p_libvlc, "volume-change", VolumeChanged, this ); + var_AddCallback( THEPL, "volume-change", VolumeChanged, this ); + var_AddCallback( THEPL, "volume-muted", SoundMuteChanged, this ); /* Warn our embedded IM about input changes */ - CONNECT( this, inputChanged( input_thread_t * ), - im, setInput( input_thread_t * ) ); + DCONNECT( this, inputChanged( input_thread_t * ), + im, setInput( input_thread_t * ) ); /* emit check if playlist has already started playing */ input_thread_t *p_input = playlist_CurrentInput( THEPL ); @@ -908,12 +946,20 @@ MainInputManager::~MainInputManager() vlc_object_release( p_input ); } - var_DelCallback( p_intf->p_libvlc, "volume-change", VolumeChanged, this ); + var_DelCallback( THEPL, "volume-change", VolumeChanged, this ); + var_DelCallback( THEPL, "volume-muted", SoundMuteChanged, this ); var_DelCallback( THEPL, "activity", PLItemChanged, this ); var_DelCallback( THEPL, "item-change", ItemChanged, im ); + var_DelCallback( THEPL, "leaf-to-parent", LeafToParent, this ); var_DelCallback( THEPL, "item-current", PLItemChanged, this ); + var_DelCallback( THEPL, "playlist-item-append", PLItemAppended, this ); + var_DelCallback( THEPL, "playlist-item-deleted", PLItemRemoved, this ); + var_DelCallback( THEPL, "random", RandomChanged, this ); + var_DelCallback( THEPL, "repeat", RepeatChanged, this ); + var_DelCallback( THEPL, "loop", LoopChanged, this ); + } vout_thread_t* MainInputManager::getVout() @@ -929,14 +975,39 @@ aout_instance_t * MainInputManager::getAout() void MainInputManager::customEvent( QEvent *event ) { int type = event->type(); - if ( type != ItemChanged_Type && type != VolumeChanged_Type ) - return; + + PLEvent *plEv; + IMEvent *imEv; // msg_Dbg( p_intf, "New MainIM Event of type: %i", type ); - if( type == VolumeChanged_Type ) + switch( type ) { + case VolumeChanged_Type: emit volumeChanged(); return; + case SoundMuteChanged_Type: + emit soundMuteChanged(); + return; + case PLItemAppended_Type: + plEv = static_cast( event ); + emit playlistItemAppended( plEv->i_item, plEv->i_parent ); + return; + case PLItemRemoved_Type: + plEv = static_cast( event ); + emit playlistItemRemoved( plEv->i_item ); + return; + case RandomChanged_Type: + emit randomChanged( var_GetBool( THEPL, "random" ) ); + return; + case LoopChanged_Type: + case RepeatChanged_Type: + notifyRepeatLoop(); + return; + case LeafToParent_Type: + imEv = static_cast( event ); + emit leafBecameParent( imEv->p_item ); + default: + if( type != ItemChanged_Type ) return; } /* Should be PLItemChanged Event */ @@ -970,13 +1041,11 @@ void MainInputManager::customEvent( QEvent *event ) p_input = NULL; } /* we are working as a dialogs provider */ - playlist_t *p_playlist = pl_Hold( p_intf ); - p_input = playlist_CurrentInput( p_playlist ); + p_input = playlist_CurrentInput( pl_Get(p_intf) ); if( p_input ) { emit inputChanged( p_input ); } - pl_Release( p_intf ); } } @@ -1005,12 +1074,64 @@ void MainInputManager::togglePlayPause() getIM()->togglePlayPause(); } +void MainInputManager::play() +{ + /* No input, play */ + if( !p_input ) + playlist_Play( THEPL ); + else + { + if( PLAYING_S != var_GetInteger( p_input, "state" ) ) + { + getIM()->togglePlayPause(); + } + } +} + +void MainInputManager::pause() +{ + if(p_input && PLAYING_S == var_GetInteger( p_input, "state" ) ) + { + getIM()->togglePlayPause(); + } +} + +void MainInputManager::toggleRandom() +{ + var_ToggleBool( THEPL, "random" ); +} + +void MainInputManager::notifyRepeatLoop() +{ + int i_value = var_GetBool( THEPL, "loop" ) * REPEAT_ONE + + var_GetBool( THEPL, "repeat" ) * REPEAT_ALL; + + emit repeatLoopChanged( i_value ); +} + +void MainInputManager::loopRepeatLoopStatus() +{ + /* Toggle Normal -> Loop -> Repeat -> Normal ... */ + if( var_GetBool( THEPL, "repeat" ) ) + var_SetBool( THEPL, "repeat", false ); + else if( var_GetBool( THEPL, "loop" ) ) + { + var_SetBool( THEPL, "loop", false ); + var_SetBool( THEPL, "repeat", true ); + } + else + var_SetBool( THEPL, "loop", true ); +} + void MainInputManager::activatePlayQuit( bool b_exit ) { var_SetBool( THEPL, "play-and-exit", b_exit ); } -/* Static callbacks for MIM */ + +/**************************** + * Static callbacks for MIM * + ****************************/ static int PLItemChanged( vlc_object_t *p_this, const char *psz_var, vlc_value_t oldval, vlc_value_t, void *param ) { @@ -1021,6 +1142,17 @@ static int PLItemChanged( vlc_object_t *p_this, const char *psz_var, return VLC_SUCCESS; } +static int LeafToParent( vlc_object_t *p_this, const char *psz_var, + vlc_value_t oldval, vlc_value_t newval, void *param ) +{ + MainInputManager *mim = (MainInputManager*)param; + + IMEvent *event = new IMEvent( LeafToParent_Type, + static_cast( newval.p_address ) ); + QApplication::postEvent( mim, event ); + return VLC_SUCCESS; +} + static int VolumeChanged( vlc_object_t *p_this, const char *psz_var, vlc_value_t oldval, vlc_value_t newval, void *param ) { @@ -1031,3 +1163,63 @@ static int VolumeChanged( vlc_object_t *p_this, const char *psz_var, return VLC_SUCCESS; } +static int SoundMuteChanged( vlc_object_t *p_this, const char *psz_var, + vlc_value_t oldval, vlc_value_t newval, void *param ) +{ + MainInputManager *mim = (MainInputManager*)param; + + IMEvent *event = new IMEvent( SoundMuteChanged_Type ); + QApplication::postEvent( mim, event ); + return VLC_SUCCESS; +} + +static int PLItemAppended +( vlc_object_t * obj, const char *var, vlc_value_t old, vlc_value_t cur, void *data ) +{ + MainInputManager *mim = static_cast(data); + playlist_add_t *p_add = static_cast( cur.p_address ); + + PLEvent *event = new PLEvent( PLItemAppended_Type, p_add->i_item, p_add->i_node ); + QApplication::postEvent( mim, event ); + return VLC_SUCCESS; +} +static int PLItemRemoved +( vlc_object_t * obj, const char *var, vlc_value_t old, vlc_value_t cur, void *data ) +{ + MainInputManager *mim = static_cast(data); + + PLEvent *event = new PLEvent( PLItemRemoved_Type, cur.i_int, 0 ); + QApplication::postEvent( mim, event ); + return VLC_SUCCESS; +} + +static int RandomChanged +( vlc_object_t * obj, const char *var, vlc_value_t old, vlc_value_t cur, void *data ) +{ + MainInputManager *mim = static_cast(data); + + IMEvent *event = new IMEvent( RandomChanged_Type ); + QApplication::postEvent( mim, event ); + return VLC_SUCCESS; +} + +/* Probably could be merged with next callback */ +static int LoopChanged +( vlc_object_t * obj, const char *var, vlc_value_t old, vlc_value_t cur, void *data ) +{ + MainInputManager *mim = static_cast(data); + + IMEvent *event = new IMEvent( LoopChanged_Type ); + QApplication::postEvent( mim, event ); + return VLC_SUCCESS; +} + +static int RepeatChanged +( vlc_object_t * obj, const char *var, vlc_value_t old, vlc_value_t cur, void *data ) +{ + MainInputManager *mim = static_cast(data); + + IMEvent *event = new IMEvent( RepeatChanged_Type ); + QApplication::postEvent( mim, event ); + return VLC_SUCCESS; +}