[vlc-devel] [PATCH 20/20] qt: add secondary subtitle delay synchronization

Thomas Guillem thomas at gllm.fr
Thu Jun 20 17:24:03 CEST 2019


From: Roland Bewick <roland.bewick at gmail.com>

Signed-off-by: Thomas Guillem <thomas at gllm.fr>
---
 modules/gui/qt/components/extended_panels.cpp | 44 ++++++++++---
 modules/gui/qt/components/extended_panels.hpp |  2 +
 .../gui/qt/components/player_controller.cpp   | 61 ++++++++++++++++++-
 .../gui/qt/components/player_controller.hpp   |  4 ++
 .../gui/qt/components/player_controller_p.hpp |  6 +-
 5 files changed, 105 insertions(+), 12 deletions(-)

diff --git a/modules/gui/qt/components/extended_panels.cpp b/modules/gui/qt/components/extended_panels.cpp
index 358fbc2479..63166a8de1 100644
--- a/modules/gui/qt/components/extended_panels.cpp
+++ b/modules/gui/qt/components/extended_panels.cpp
@@ -1374,16 +1374,25 @@ SyncControls::SyncControls( intf_thread_t *_p_intf, QWidget *_parent )
     subsBox = new QGroupBox( qtr( "Subtitles/Video" ) );
     QGridLayout *subsLayout = new QGridLayout( subsBox );
 
-    QLabel *subsLabel = new QLabel;
-    subsLabel->setText( qtr( "Subtitle track synchronization:" ) );
-    subsLayout->addWidget( subsLabel, 0, 0, 1, 1 );
+    QGroupBox *subsTrackSyncBox = new QGroupBox( qtr( "Subtitle track synchronization" ) );
+    QGridLayout *synchronizationLayout = new QGridLayout( subsTrackSyncBox );
 
-    subsSpin = new SyncWidget( this );
-    subsLayout->addWidget( subsSpin, 0, 2, 1, 1 );
+    for( int i = 0; i < 2; i++ )
+    {
+        QLabel *subsLabel = new QLabel;
+        subsLabel->setText( qtr( i == 0 ? "Primary subtitle Track:" : "Secondary subtitle track:" ) );
+        synchronizationLayout->addWidget( subsLabel, i, 0, 1, 1 );
+        SyncWidget **p_subsSpin = i == 0 ? &subsSpin : &secondarySubsSpin;
+
+        *p_subsSpin = new SyncWidget( this );
+        synchronizationLayout->addWidget( *p_subsSpin, i, 2, 1, 1 );
+    }
+
+    subsLayout->addWidget( subsTrackSyncBox, 0, 0, 2, 5 );
 
     QLabel *subSpeedLabel = new QLabel;
     subSpeedLabel->setText( qtr( "Subtitle speed:" ) );
-    subsLayout->addWidget( subSpeedLabel, 1, 0, 1, 1 );
+    subsLayout->addWidget( subSpeedLabel, 2, 0, 1, 1 );
 
     subSpeedSpin = new QDoubleSpinBox;
     subSpeedSpin->setAlignment( Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter );
@@ -1393,11 +1402,11 @@ SyncControls::SyncControls( intf_thread_t *_p_intf, QWidget *_parent )
     subSpeedSpin->setSingleStep( 0.2 );
     subSpeedSpin->setSuffix( " fps" );
     subSpeedSpin->setButtonSymbols( QDoubleSpinBox::PlusMinus );
-    subsLayout->addWidget( subSpeedSpin, 1, 2, 1, 1 );
+    subsLayout->addWidget( subSpeedSpin, 2, 2, 1, 1 );
 
     QLabel *subDurationLabel = new QLabel;
     subDurationLabel->setText( qtr( "Subtitle duration factor:" ) );
-    subsLayout->addWidget( subDurationLabel, 2, 0, 1, 1 );
+    subsLayout->addWidget( subDurationLabel, 3, 0, 1, 1 );
 
     subDurationSpin = new QDoubleSpinBox;
     subDurationSpin->setAlignment( Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter );
@@ -1406,7 +1415,7 @@ SyncControls::SyncControls( intf_thread_t *_p_intf, QWidget *_parent )
     subDurationSpin->setMaximum( 20 );
     subDurationSpin->setSingleStep( 0.2 );
     subDurationSpin->setButtonSymbols( QDoubleSpinBox::PlusMinus );
-    subsLayout->addWidget( subDurationSpin, 2, 2, 1, 1 );
+    subsLayout->addWidget( subDurationSpin, 3, 2, 1, 1 );
 
     mainLayout->addWidget( subsBox, 2, 0, 2, 5 );
 
@@ -1417,6 +1426,7 @@ SyncControls::SyncControls( intf_thread_t *_p_intf, QWidget *_parent )
     /* Various Connects */
     connect( AVSpin, &SyncWidget::valueChanged, this, &SyncControls::advanceAudio ) ;
     connect( subsSpin, &SyncWidget::valueChanged, this, &SyncControls::advanceSubs ) ;
+    connect( secondarySubsSpin, &SyncWidget::valueChanged, this, &SyncControls::advanceSecondarySubs ) ;
     connect( subSpeedSpin, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &SyncControls::adjustSubsSpeed);
     connect( subDurationSpin, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &SyncControls::adjustSubsDuration);
 
@@ -1425,6 +1435,11 @@ SyncControls::SyncControls( intf_thread_t *_p_intf, QWidget *_parent )
         subsSpin->setValue(secf_from_vlc_tick(value));
         b_userAction = true;
     });
+    connect( THEMIM, &PlayerController::secondarySubtitleDelayChanged, [this](vlc_tick_t value) {
+        b_userAction = false;
+        secondarySubsSpin->setValue(secf_from_vlc_tick(value));
+        b_userAction = true;
+    });
     connect( THEMIM, &PlayerController::audioDelayChanged, [this](vlc_tick_t value) {
         b_userAction = false;
         AVSpin->setValue(secf_from_vlc_tick(value));
@@ -1452,6 +1467,7 @@ void SyncControls::clean()
     b_userAction = false;
     AVSpin->setValue( 0.0 );
     subsSpin->setValue( 0.0 );
+    secondarySubsSpin->setValue( 0.0 );
     subSpeedSpin->setValue( 1.0 );
     subsdelayClean();
     b_userAction = true;
@@ -1463,6 +1479,7 @@ void SyncControls::update()
     if( THEMIM->getInput() )
     {
         subsSpin->setValue(secf_from_vlc_tick(THEMIM->getSubtitleDelay()));
+        secondarySubsSpin->setValue(secf_from_vlc_tick(THEMIM->getSecondarySubtitleDelay()));
         AVSpin->setValue(secf_from_vlc_tick(THEMIM->getAudioDelay()));
         subSpeedSpin->setValue(THEMIM->getSubtitleFPS());
         subDurationSpin->setValue(m_SubsDelayCfgFactor.getValue());
@@ -1488,6 +1505,15 @@ void SyncControls::advanceSubs( double f_advance )
     }
 }
 
+void SyncControls::advanceSecondarySubs( double f_advance )
+{
+    if( THEMIM->getInput() && b_userAction )
+    {
+        vlc_tick_t i_delay = vlc_tick_from_sec( f_advance );
+        THEMIM->setSecondarySubtitleDelay( i_delay );
+    }
+}
+
 void SyncControls::adjustSubsSpeed( double f_fps )
 {
     if( THEMIM->getInput() && b_userAction )
diff --git a/modules/gui/qt/components/extended_panels.hpp b/modules/gui/qt/components/extended_panels.hpp
index a96240d67a..a06704bbcb 100644
--- a/modules/gui/qt/components/extended_panels.hpp
+++ b/modules/gui/qt/components/extended_panels.hpp
@@ -248,6 +248,7 @@ private:
     intf_thread_t *p_intf;
     SyncWidget *AVSpin;
     SyncWidget *subsSpin;
+    SyncWidget *secondarySubsSpin;
     QDoubleSpinBox *subSpeedSpin;
     QDoubleSpinBox *subDurationSpin;
     QVLCFloat m_SubsDelayCfgFactor;
@@ -265,6 +266,7 @@ public slots:
 private slots:
     void advanceAudio( double );
     void advanceSubs( double );
+    void advanceSecondarySubs( double );
     void adjustSubsSpeed( double );
     void adjustSubsDuration( double );
 };
diff --git a/modules/gui/qt/components/player_controller.cpp b/modules/gui/qt/components/player_controller.cpp
index 3d7e13994b..8f5561f9ab 100644
--- a/modules/gui/qt/components/player_controller.cpp
+++ b/modules/gui/qt/components/player_controller.cpp
@@ -190,6 +190,29 @@ void PlayerControllerPrivate::UpdateVouts(vout_thread_t **vouts, size_t i_vouts)
         emit q->hasVideoOutputChanged(m_hasVideo);
 }
 
+void PlayerControllerPrivate::UpdateSpuOrder(vlc_es_id_t *es_id, enum vlc_spu_channel_order spu_order)
+{
+    switch (spu_order)
+    {
+        case VLC_SPU_CHANNEL_ORDER_NONE:
+            if (es_id == m_secondarySpuEsId.get())
+                m_secondarySpuEsId.reset(NULL, false);
+            break;
+        case VLC_SPU_CHANNEL_ORDER_SECONDARY:
+            m_secondarySpuEsId.reset(es_id, true);
+            if (m_secondarySubtitleDelay != 0)
+            {
+                vlc_player_locker lock{ m_player };
+                vlc_player_SetEsIdDelay(m_player, es_id,
+                                        m_secondarySubtitleDelay,
+                                        VLC_PLAYER_WHENCE_ABSOLUTE);
+            }
+            break;
+        default:
+            break;
+    }
+}
+
 extern "C" {
 
 //player callbacks
@@ -601,6 +624,22 @@ static void on_player_category_delay_changed(vlc_player_t *,
     });
 }
 
+static void on_player_track_delay_changed(vlc_player_t *,
+                                vlc_es_id_t *es_id, vlc_tick_t new_delay,
+                                void *data)
+{
+    PlayerControllerPrivate* that = static_cast<PlayerControllerPrivate*>(data);
+    EsIdPtr esIdPtr = EsIdPtr(es_id);
+
+    that->callAsync([that,esIdPtr,new_delay] (){
+        if (that->m_secondarySpuEsId.get() == esIdPtr.get())
+        {
+            that->m_secondarySubtitleDelay = new_delay;
+            emit that->q_func()->secondarySubtitleDelayChanged( new_delay );
+        }
+    });
+}
+
 static void on_player_associated_subs_fps_changed(vlc_player_t *, float subs_fps, void *data)
 {
     PlayerControllerPrivate* that = static_cast<PlayerControllerPrivate*>(data);
@@ -711,7 +750,7 @@ static void on_player_subitems_changed(vlc_player_t *, input_item_t *, input_ite
 
 
 static void on_player_vout_changed(vlc_player_t *player, enum vlc_player_vout_action,
-    vout_thread_t *, enum vlc_spu_channel_order, vlc_es_id_t *es_id, void *data)
+    vout_thread_t *, enum vlc_spu_channel_order spu_order, vlc_es_id_t *es_id, void *data)
 {
     PlayerControllerPrivate* that = static_cast<PlayerControllerPrivate*>(data);
     msg_Dbg( that->p_intf, "on_player_vout_list_changed");
@@ -736,6 +775,14 @@ static void on_player_vout_changed(vlc_player_t *player, enum vlc_player_vout_ac
             });
             break;
         }
+        case SPU_ES:
+        {
+            EsIdPtr esIdPtr = EsIdPtr(es_id);
+            that->callAsync([that,esIdPtr,spu_order] () {
+                that->UpdateSpuOrder(esIdPtr.get(), spu_order);
+            });
+            break;
+        }
         default:
             break;
     }
@@ -820,7 +867,7 @@ static const struct vlc_player_cbs player_cbs = {
     on_player_length_changed,
     on_player_track_list_changed,
     on_player_track_selection_changed,
-    NULL /* on_player_track_delay_changed */,
+    on_player_track_delay_changed,
     on_player_program_list_changed,
     on_player_program_selection_changed,
     on_player_titles_changed,
@@ -1065,6 +1112,15 @@ void PlayerController::setSubtitleDelay(VLCTick delay)
     vlc_player_SetSubtitleDelay( d->m_player, delay, VLC_PLAYER_WHENCE_ABSOLUTE );
 }
 
+void PlayerController::setSecondarySubtitleDelay(VLCTick delay)
+{
+    Q_D(PlayerController);
+    vlc_player_locker lock{ d->m_player };
+    if (d->m_secondarySpuEsId.get() != NULL)
+        vlc_player_SetEsIdDelay(d->m_player, d->m_secondarySpuEsId.get(),
+                                delay, VLC_PLAYER_WHENCE_ABSOLUTE);
+}
+
 void PlayerController::setSubtitleFPS(float fps)
 {
     Q_D(PlayerController);
@@ -1494,6 +1550,7 @@ PRIMITIVETYPE_GETTER(float, getPosition, m_position)
 PRIMITIVETYPE_GETTER(VLCTick, getLength, m_length)
 PRIMITIVETYPE_GETTER(VLCTick, getAudioDelay, m_audioDelay)
 PRIMITIVETYPE_GETTER(VLCTick, getSubtitleDelay, m_subtitleDelay)
+PRIMITIVETYPE_GETTER(VLCTick, getSecondarySubtitleDelay, m_secondarySubtitleDelay)
 PRIMITIVETYPE_GETTER(bool, isSeekable, m_capabilities & VLC_PLAYER_CAP_SEEK)
 PRIMITIVETYPE_GETTER(bool, isRewindable, m_capabilities & VLC_PLAYER_CAP_REWIND)
 PRIMITIVETYPE_GETTER(bool, isPausable, m_capabilities & VLC_PLAYER_CAP_PAUSE)
diff --git a/modules/gui/qt/components/player_controller.hpp b/modules/gui/qt/components/player_controller.hpp
index 885eba2cd4..24373e2d8f 100644
--- a/modules/gui/qt/components/player_controller.hpp
+++ b/modules/gui/qt/components/player_controller.hpp
@@ -121,6 +121,7 @@ public:
 
     Q_PROPERTY(VLCTick audioDelay READ getAudioDelay WRITE setAudioDelay NOTIFY audioDelayChanged)
     Q_PROPERTY(VLCTick subtitleDelay READ getSubtitleDelay WRITE setSubtitleDelay NOTIFY subtitleDelayChanged)
+    Q_PROPERTY(VLCTick secondarySubtitleDelay READ getSecondarySubtitleDelay WRITE setSecondarySubtitleDelay NOTIFY secondarySubtitleDelayChanged)
     Q_PROPERTY(float subtitleFPS READ getSubtitleFPS WRITE setSubtitleFPS NOTIFY subtitleFPSChanged)
 
     //title/chapters/menu
@@ -264,7 +265,9 @@ public slots:
     VLCTick getAudioDelay() const;
     void setAudioDelay( VLCTick );
     VLCTick getSubtitleDelay() const;
+    VLCTick getSecondarySubtitleDelay() const;
     void setSubtitleDelay( VLCTick );
+    void setSecondarySubtitleDelay( VLCTick );
     float getSubtitleFPS( ) const;
     void setSubtitleFPS( float );
 
@@ -348,6 +351,7 @@ signals:
     //tracks
     void audioDelayChanged(VLCTick);
     void subtitleDelayChanged(VLCTick);
+    void secondarySubtitleDelayChanged(VLCTick);
     void subtitleFPSChanged(float);
 
     //title/chapters/menu
diff --git a/modules/gui/qt/components/player_controller_p.hpp b/modules/gui/qt/components/player_controller_p.hpp
index 3a52205aa2..8fff81639c 100644
--- a/modules/gui/qt/components/player_controller_p.hpp
+++ b/modules/gui/qt/components/player_controller_p.hpp
@@ -43,6 +43,7 @@ public:
     void UpdateProgram(vlc_player_list_action action, const vlc_player_program *prgm);
     void UpdateVouts(vout_thread_t **vouts, size_t i_vouts);
     void UpdateTrackSelection(vlc_es_id_t *trackid, bool selected);
+    void UpdateSpuOrder(vlc_es_id_t *es_id, enum vlc_spu_channel_order spu_order);
 
     ///call function @a fun on object thread
     template <typename Fun>
@@ -89,9 +90,12 @@ public:
     TrackListModel m_audioTracks;
     TrackListModel m_subtitleTracks;
 
+    vlc_shared_data_ptr_type(vlc_es_id_t, vlc_es_id_Hold, vlc_es_id_Release) m_secondarySpuEsId;
+
     VLCTick      m_audioDelay = 0;
     VLCTick      m_subtitleDelay = 0;
-    float           m_subtitleFPS = 1.0;
+    VLCTick      m_secondarySubtitleDelay = 0;
+    float        m_subtitleFPS = 1.0;
 
     //title/chapters/menu
     TitleListModel m_titleList;
-- 
2.20.1



More information about the vlc-devel mailing list