[vlc-devel] [PATCH 03/10] Add dual subtitles configuration - Enable / disable dual subtitles - Alignment (default unset) - Margin

Roland Bewick roland.bewick at gmail.com
Sun May 5 12:01:43 CEST 2019


---
 .../gui/qt/components/simple_preferences.cpp  |  9 ++
 modules/gui/qt/ui/sprefs_subtitles.ui         | 98 +++++++++++++++++++
 src/input/es_out.c                            |  3 +-
 src/input/var.c                               |  1 +
 src/libvlc-module.c                           | 31 ++++++
 src/video_output/vout_subpictures.c           | 36 +++++--
 6 files changed, 169 insertions(+), 9 deletions(-)

diff --git a/modules/gui/qt/components/simple_preferences.cpp b/modules/gui/qt/components/simple_preferences.cpp
index 914b92f07d..cc3787438f 100644
--- a/modules/gui/qt/components/simple_preferences.cpp
+++ b/modules/gui/qt/components/simple_preferences.cpp
@@ -870,6 +870,15 @@ SPrefsPanel::SPrefsPanel( intf_thread_t *_p_intf, QWidget *_parent,
             optionWidgets["shadowCB"] = ui.shadowCheck;
             optionWidgets["backgroundCB"] = ui.backgroundCheck;
 
+            CONFIG_BOOL( "secondary-spu", secondarySpuActiveBox);
+            CONFIG_GENERIC( "secondary-spu-alignment", IntegerList,
+                            ui.secondarySubsAlignmentLabel, secondarySubsAlignment );
+            CONFIG_GENERIC_NO_BOOL( "secondary-sub-margin", Integer, ui.secondarySubsPosLabel, secondarySubsPosition );
+            
+            ui.secondarySpuZone->setEnabled( ui.secondarySpuActiveBox->isChecked() );
+            CONNECT( ui.secondarySpuActiveBox, toggled( bool ),
+                     ui.secondarySpuZone, setEnabled( bool ) );
+
         END_SPREFS_CAT;
 
         case SPrefsHotkeys:
diff --git a/modules/gui/qt/ui/sprefs_subtitles.ui b/modules/gui/qt/ui/sprefs_subtitles.ui
index b9e851dc9d..15edd91d43 100644
--- a/modules/gui/qt/ui/sprefs_subtitles.ui
+++ b/modules/gui/qt/ui/sprefs_subtitles.ui
@@ -313,6 +313,104 @@
         </layout>
        </widget>
       </item>
+      <item>
+       <widget class="QGroupBox" name="groupBox_5">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="title">
+         <string>Dual Subtitles</string>
+        </property>
+        <layout class="QVBoxLayout" name="verticalLayout">
+         <item>
+          <widget class="QCheckBox" name="secondarySpuActiveBox">
+           <property name="text">
+            <string>Enable</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QWidget" name="secondarySpuZone" native="true">
+           <layout class="QGridLayout">
+            <item row="0" column="1">
+             <widget class="QComboBox" name="secondarySubsAlignment"/>
+            </item>
+            <item row="0" column="0">
+             <widget class="QLabel" name="secondarySubsAlignmentLabel">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="text">
+               <string>Align</string>
+              </property>
+              <property name="alignment">
+               <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+              </property>
+              <property name="buddy">
+               <cstring>secondarySubsAlignment</cstring>
+              </property>
+             </widget>
+            </item>
+            <item row="0" column="2">
+             <spacer name="horizontalSpacer">
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
+              </property>
+              <property name="sizeType">
+               <enum>QSizePolicy::Preferred</enum>
+              </property>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>50</width>
+                <height>20</height>
+               </size>
+              </property>
+             </spacer>
+            </item>
+            <item row="0" column="3">
+             <widget class="QLabel" name="secondarySubsPosLabel">
+              <property name="text">
+               <string>Offset</string>
+              </property>
+              <property name="buddy">
+               <cstring>secondarySubsPosition</cstring>
+              </property>
+             </widget>
+            </item>
+            <item row="0" column="4">
+             <widget class="QSpinBox" name="secondarySubsPosition">
+              <property name="maximumSize">
+               <size>
+                <width>16777215</width>
+                <height>16777215</height>
+               </size>
+              </property>
+              <property name="alignment">
+               <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+              </property>
+              <property name="suffix">
+               <string> px</string>
+              </property>
+              <property name="minimum">
+               <number>-1024</number>
+              </property>
+              <property name="maximum">
+               <number>1024</number>
+              </property>
+             </widget>
+            </item>
+           </layout>
+          </widget>
+         </item>
+        </layout>
+       </widget>
+      </item>
      </layout>
     </widget>
    </item>
diff --git a/src/input/es_out.c b/src/input/es_out.c
index 824d64b3c0..bd2f9f1025 100644
--- a/src/input/es_out.c
+++ b/src/input/es_out.c
@@ -2074,7 +2074,8 @@ static void EsOutSelect( es_out_t *out, es_out_id_t *es, bool b_force )
     bool b_select_secondary_subtitle = es->fmt.i_cat == SPU_ES && 
                                p_sys->b_select_secondary_subtitle &&
                                p_esprops->p_main_es != NULL &&
-                               EsIsSelected(p_esprops->p_main_es);
+                               EsIsSelected(p_esprops->p_main_es) &&
+                               var_GetBool( p_sys->p_input, "secondary-spu" );
 
     if ( b_select_secondary_subtitle &&
          EsOutCountSelected( p_sys, es->fmt.i_cat ) > 1 )
diff --git a/src/input/var.c b/src/input/var.c
index 7822d66003..9c9e7b9dba 100644
--- a/src/input/var.c
+++ b/src/input/var.c
@@ -726,6 +726,7 @@ void input_ConfigVarInit ( input_thread_t *p_input )
         var_Create( p_input, "video", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
         var_Create( p_input, "audio", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
         var_Create( p_input, "spu", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
+        var_Create( p_input, "secondary-spu", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
 
         var_Create( p_input, "video-track", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
         var_Create( p_input, "audio-track", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
diff --git a/src/libvlc-module.c b/src/libvlc-module.c
index 958fb4014c..bbc21a32a5 100644
--- a/src/libvlc-module.c
+++ b/src/libvlc-module.c
@@ -371,6 +371,11 @@ static const char *const ppsz_pos_descriptions[] =
 { N_("Center"), N_("Left"), N_("Right"), N_("Top"), N_("Bottom"),
   N_("Top-Left"), N_("Top-Right"), N_("Bottom-Left"), N_("Bottom-Right") };
 
+static const int pi_sub_align_values[] = { -1, 0, 1, 2, 4, 8, 5, 6, 9, 10 };
+static const char *const ppsz_sub_align_descriptions[] =
+{ N_("Unset"), N_("Center"), N_("Left"), N_("Right"), N_("Top"), N_("Bottom"),
+  N_("Top-Left"), N_("Top-Right"), N_("Bottom-Left"), N_("Bottom-Right") };
+
 #define SS_TEXT N_("Disable screensaver")
 #define SS_LONGTEXT N_("Disable the screensaver during video playback." )
 
@@ -743,6 +748,20 @@ static const char *const ppsz_prefres[] = {
 #define SPU_LONGTEXT N_( \
     "You can completely disable the sub-picture processing.")
 
+#define SECONDARY_SPU_TEXT N_("Enable dual subtitles")
+#define SECONDARY_SPU_LONGTEXT N_( \
+    "This option allows you to view two subtitle tracks simultaneously " \
+    "(to assist language learning, etc).")
+
+#define SECONDARY_SPU_POSITION_TEXT N_("Position of secondary subtitles")
+#define SECONDARY_SPU_POSITION_LONGTEXT N_( \
+    "Place on video where to display secondary subtitles (default bottom center).")
+
+#define SECONDARY_SUB_MARGIN_TEXT N_("Force secondary subtitle position")
+#define SECONDARY_SUB_MARGIN_LONGTEXT N_( \
+    "You can use this option to vertically adjust the position secondary " \
+    "subtitles are displayed.")
+
 #define OSD_TEXT N_("On Screen Display")
 #define OSD_LONGTEXT N_( \
     "VLC can display messages on the video. This is called OSD (On Screen " \
@@ -1753,6 +1772,18 @@ vlc_module_begin ()
     add_module_list("sub-filter", "sub filter", NULL,
                     SUB_FILTER_TEXT, SUB_FILTER_LONGTEXT)
 
+    set_section( N_( "Dual Subtitles" ) , NULL )
+    add_bool( "secondary-spu", 0, SECONDARY_SPU_TEXT, SECONDARY_SPU_LONGTEXT, false )
+        change_safe ()
+    add_integer( "secondary-spu-alignment", -1, SECONDARY_SPU_POSITION_TEXT,
+                 SECONDARY_SPU_POSITION_LONGTEXT, false )
+        change_safe ()
+        change_integer_list( pi_sub_align_values, ppsz_sub_align_descriptions )
+    /* Push the secondary subtitles up a bit so they won't overlap with
+       the primary subtitles using the default settings.*/
+    add_integer( "secondary-sub-margin", 100, SECONDARY_SUB_MARGIN_TEXT,
+                 SECONDARY_SUB_MARGIN_LONGTEXT, true )
+
 /* Input options */
     set_category( CAT_INPUT )
     set_subcategory( SUBCAT_INPUT_GENERAL )
diff --git a/src/video_output/vout_subpictures.c b/src/video_output/vout_subpictures.c
index 6b106534d3..742a93cf14 100644
--- a/src/video_output/vout_subpictures.c
+++ b/src/video_output/vout_subpictures.c
@@ -91,6 +91,9 @@ struct spu_private_t {
     atomic_int margin;                 /**< force position of a subpicture */
     video_palette_t palette;              /**< force palette of subpicture */
 
+    int secondary_sub_alignment;   /**< force alignment for secondary subs */
+    int secondary_sub_margin;      /**< move the secondary sub vertically  */
+
     /* Subpiture filters */
     char           *source_chain_current;
     char           *source_chain_update;
@@ -468,23 +471,28 @@ static void SpuAreaFitInside(spu_area_t *area, const spu_area_t *boundary)
  */
 static void SpuRegionPlace(int *x, int *y,
                            const subpicture_t *subpic,
-                           const subpicture_region_t *region)
+                           const subpicture_region_t *region,
+                           int i_secondary_spu_align_override)
 {
+    int i_align = region->i_align;
+    if (subpic->b_secondary && i_secondary_spu_align_override >= 0)
+        i_align = i_secondary_spu_align_override;
+
     assert(region->i_x != INT_MAX && region->i_y != INT_MAX);
     if (subpic->b_absolute) {
         *x = region->i_x;
         *y = region->i_y;
     } else {
-        if (region->i_align & SUBPICTURE_ALIGN_TOP)
-            *y = region->i_y;
-        else if (region->i_align & SUBPICTURE_ALIGN_BOTTOM)
+        if (i_align & SUBPICTURE_ALIGN_TOP)
+            *y = region->i_y + ( subpic->b_subtitle ? region->fmt.i_visible_height : 0 );
+        else if (i_align & SUBPICTURE_ALIGN_BOTTOM)
             *y = subpic->i_original_picture_height - region->fmt.i_visible_height - region->i_y;
         else
             *y = subpic->i_original_picture_height / 2 - region->fmt.i_visible_height / 2;
 
-        if (region->i_align & SUBPICTURE_ALIGN_LEFT)
+        if (i_align & SUBPICTURE_ALIGN_LEFT)
             *x = region->i_x;
-        else if (region->i_align & SUBPICTURE_ALIGN_RIGHT)
+        else if (i_align & SUBPICTURE_ALIGN_RIGHT)
             *x = subpic->i_original_picture_width - region->fmt.i_visible_width - region->i_x;
         else
             *x = subpic->i_original_picture_width / 2 - region->fmt.i_visible_width / 2;
@@ -777,7 +785,9 @@ static void SpuRenderRegion(spu_t *spu,
 
     /* Compute the margin which is expressed in destination pixel unit
      * The margin is applied only to subtitle and when no forced crop is
-     * requested (dvd menu) */
+     * requested (dvd menu).
+     * Note: Margin will also be applied to secondary subtitles if they exist
+     * to ensure that overlap does not occur. */
     int y_margin = 0;
     if (!crop_requested && subpic->b_subtitle)
         y_margin = spu_invscale_h(atomic_load(&sys->margin), scale_size);
@@ -785,7 +795,14 @@ static void SpuRenderRegion(spu_t *spu,
     /* Place the picture
      * We compute the position in the rendered size */
     SpuRegionPlace(&x_offset, &y_offset,
-                   subpic, region);
+                   subpic, region, sys->secondary_sub_alignment);
+
+    if (subpic->b_secondary && !subpic->b_absolute)
+    {
+        /* Move the secondary subtitles by the secondary margin before overlap detection.
+           This way, overlaps will be resolved if they still exist. */
+        y_offset -= spu_invscale_h(atomic_load(&sys->secondary_sub_margin), scale_size);
+    }
 
     /* Save this position for subtitle overlap support
      * it is really important that there are given without scale_size applied */
@@ -1386,6 +1403,9 @@ spu_t *spu_Create(vlc_object_t *object, vout_thread_t *vout)
     sys->scale_yuvp = NULL;
 
     atomic_init(&sys->margin, var_InheritInteger(spu, "sub-margin"));
+    atomic_init(&sys->secondary_sub_margin, var_InheritInteger(spu, "secondary-sub-margin"));
+
+    sys->secondary_sub_alignment = var_InheritInteger(spu, "secondary-spu-alignment");
 
     /* Register the default subpicture channel */
     sys->channel = VOUT_SPU_CHANNEL_AVAIL_FIRST;
-- 
2.17.1



More information about the vlc-devel mailing list