Skip to content
Browse files

Add lsdvd dependency. Use lsdvd to find title, chapter, and audio inf…

…ormation and allow the user to choose them in the source properties dialog. Disable selection of chapter and audio stream for now as GStreamer is providing no way for me to select it, from bugs in dvdreadsrc causing it to ignore chapter selection to DVD audio streams being inconsistently named.
  • Loading branch information...
1 parent 7fa3a5d commit 7f8c6701c72a4aef65b58abf93218a9a735c2bf9 @danielgtaylor committed
Showing with 416 additions and 68 deletions.
  1. +1 −0 README.md
  2. +172 −16 arista-gtk
  3. +8 −2 arista/discoverer.py
  4. +33 −9 arista/transcoder.py
  5. +15 −0 arista/utils.py
  6. +187 −41 ui/props.ui
View
1 README.md
@@ -37,6 +37,7 @@ Dependencies
* gstreamer-plugins-bad
* gstreamer-plugins-ugly
* python-webkit (for in-app documentation)
+ * lsdvd (to read DVD title information)
Debian users may need to install these additional dependencies:
View
188 arista-gtk
@@ -33,6 +33,7 @@ import logging
import os
import re
import shutil
+import subprocess
import sys
import threading
import time
@@ -168,22 +169,27 @@ class DvdInfo(gobject.GObject):
}
def __init__(self, path):
+ gobject.GObject.__init__(self)
self.path = path
- self.proc = subprocess.Popen('lsdvd -x -Oy %s' % path, stdin=subprocess.PIPE, shell=True)
+ self.proc = subprocess.Popen('lsdvd -x -Oy %s' % path, stdout=subprocess.PIPE, shell=True)
gobject.timeout_add(100, self.run)
def run(self):
+ # Check if we have the info, if not, return and we will be called
+ # again to check in 100ms.
if self.proc.poll() is not None:
- # TODO: is there a safer way to do this?
- exec(self.proc.stdin.read())
-
- self.emit("ready", lsdvd)
+ if self.proc.returncode == 0:
+ # TODO: is there a safer way to do this?
+ exec(self.proc.stdout.read())
+ self.emit("ready", lsdvd)
return False
return True
+gobject.type_register(DvdInfo)
+
class LogoWidget(gtk.Widget):
"""
A widget to show the Arista logo.
@@ -983,8 +989,9 @@ class PropertiesDialog(object):
A simple dialog to set properties for the input source, such as
subtitles and deinterlacing.
"""
- def __init__(self, dialog):
- self.options = dialog.options
+ def __init__(self, path, options):
+ self.path = path
+ self.options = options
ui_path = arista.utils.get_path("ui", "props.ui")
@@ -992,10 +999,24 @@ class PropertiesDialog(object):
self.builder.add_from_file(ui_path)
self.window = self.builder.get_object("props_dialog")
+ self.frame_dvd = self.builder.get_object("frame_dvd")
+ self.table_dvd = self.builder.get_object("table_dvd")
+ self.combo_title = self.builder.get_object("combo_title")
+ self.combo_chapter = self.builder.get_object("combo_chapter")
+ self.combo_audio = self.builder.get_object("combo_audio")
self.subs = self.builder.get_object("filechooserbutton_subs")
self.font = self.builder.get_object("fontbutton")
self.deinterlace = self.builder.get_object("checkbutton_deinterlace")
+ # GStreamer's DVD handling is VERY limited, to the point of making
+ # chapter and audio stream selection extremely difficult if not
+ # impossible when using gst-launch. Hide chapter and audio selection
+ # until this can be fixed somehow!
+ self.table_dvd.remove(self.builder.get_object("label_chapter"))
+ self.table_dvd.remove(self.combo_chapter)
+ self.table_dvd.remove(self.builder.get_object("label_audio"))
+ self.table_dvd.remove(self.combo_audio)
+
if options.subfile:
self.subs.set_filename(options.subfile)
@@ -1005,9 +1026,49 @@ class PropertiesDialog(object):
if options.deinterlace:
self.deinterlace.set_active(options.deinterlace)
+ if path.startswith("dvd://"):
+ # Setup combo boxes
+ for combo, handler in [(self.combo_title, self.on_title_changed), (self.combo_chapter, self.on_chapter_changed), (self.combo_audio, self.on_audio_changed)]:
+ store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)
+ text_cell = gtk.CellRendererText()
+ combo.set_model(store)
+ combo.pack_start(text_cell, True)
+ combo.add_attribute(text_cell, 'text', 0)
+ iter = store.append()
+ store.set_value(iter, 0, "Auto")
+ store.set_value(iter, 1, None)
+ combo.set_active(0)
+ combo.connect("changed", handler)
+
+ # Get DVD info
+ info = DvdInfo(path[6:])
+ info.connect("ready", self.on_dvd_info_ready)
+ else:
+ self.frame_dvd.hide()
+
self.builder.connect_signals(self)
- self.window.show_all()
+ self.window.show()
+
+ def on_dvd_info_ready(self, widget, lsdvd):
+ """
+ Got DVD info, store it and populate the title list.
+ """
+ self.lsdvd = lsdvd
+ title_model = self.combo_title.get_model()
+
+ for track in lsdvd["track"]:
+ iter = title_model.append()
+ title_model.set_value(iter, 0,"Title %(index)02d - %(length)s" % {
+ "index": track["ix"],
+ "length": arista.utils.get_friendly_time(track["length"]),
+ })
+ title_model.set_value(iter, 1, track)
+
+ if self.options.title:
+ self.combo_title.set_active(self.options.title)
+
+ self.combo_title.set_sensitive(True)
def on_close(self, widget, response):
"""
@@ -1015,6 +1076,96 @@ class PropertiesDialog(object):
"""
self.window.destroy()
+ def on_title_changed(self, widget):
+ """
+ Title was changed by user, update chapter and audio info, store
+ selected title in options.
+ """
+ sensitive = False
+ track = None
+ iter = self.combo_title.get_active_iter()
+ chapter_index = 0
+ audio_index = 0
+
+ # Temporarily disable signal handling
+ self.combo_chapter.handler_block_by_func(self.on_chapter_changed)
+ self.combo_audio.handler_block_by_func(self.on_audio_changed)
+
+ # Update models
+ if iter:
+ track = self.combo_title.get_model().get_value(iter, 1)
+
+ if track:
+ chapter_model = self.combo_chapter.get_model()
+ audio_model = self.combo_audio.get_model()
+
+ for model in [chapter_model, audio_model]:
+ model.clear()
+ iter = model.append()
+ model.set_value(iter, 0, "Auto")
+ model.set_value(iter, 1, None)
+
+ for chapter in track["chapter"]:
+ iter = chapter_model.append()
+ chapter_model.set_value(iter, 0, "Chapter %(index)02d - %(length)s" % {
+ "index": chapter["ix"],
+ "length": arista.utils.get_friendly_time(chapter["length"]),
+ })
+ chapter_model.set_value(iter, 1, chapter)
+
+ for audio in track["audio"]:
+ iter = audio_model.append()
+ audio_model.set_value(iter, 0, "Audio %(index)02d - %(language)s" % {
+ "index": audio["ix"],
+ "language": audio["language"],
+ })
+ audio_model.set_value(iter, 1, audio)
+
+ sensitive = True
+
+ if self.options.title == track["ix"]:
+ chapter_index = self.options.chapter or 0
+ audio_index = self.options.audio or 0
+
+ # Store new title
+ self.options.title = track and track["ix"] or None
+
+ # Set chapter/audio selection
+ self.combo_chapter.set_active(chapter_index)
+ self.combo_audio.set_active(audio_index)
+
+ # Restore signal handling
+ self.combo_chapter.handler_unblock_by_func(self.on_chapter_changed)
+ self.combo_audio.handler_unblock_by_func(self.on_audio_changed)
+
+ # Set combos sensitive or not
+ self.combo_chapter.set_sensitive(sensitive)
+ self.combo_audio.set_sensitive(sensitive)
+
+ def on_chapter_changed(self, widget):
+ """
+ Chapter has changed - store new value in encoding options
+ """
+ chapter = None
+
+ iter = self.combo_chapter.get_active_iter()
+ if iter:
+ chapter = self.combo_chapter.get_model().get_value(iter, 1)
+
+ self.options.chapter = chapter and chapter["ix"] or None
+
+ def on_audio_changed(self, widget):
+ """
+ Audio track has changed - store new value in encoding options
+ """
+ audio = None
+
+ iter = self.combo_audio.get_active_iter()
+ if iter:
+ audio = self.combo_audio.get_model().get_value(iter, 1)
+
+ self.options.audio = audio and audio["ix"] or None
+
def on_subs_set(self, widget):
"""
Set subtitle file.
@@ -1323,22 +1474,27 @@ class AddDialog(object):
"""
self.presets_filter.refilter()
- def on_preset_changed(self, selection):
- model, iter = selection.get_selected()
-
+ def get_source(self):
smodel, siter = self.source.get_model(), self.source.get_active_iter()
if siter:
try:
- source = smodel.get_value(siter, 2)[1]
+ source = smodel.get_value(siter, 2)
except TypeError:
# Not a tuple? Maybe None or a string instead, ignore
- source = None
+ source = ('', False)
else:
- source = None
+ source = ('', False)
+
+ return source
+
+ def on_preset_changed(self, selection):
+ model, iter = selection.get_selected()
+
+ path, active = self.get_source()
self.button_del.set_sensitive(bool(iter))
self.button_info.set_sensitive(bool(iter))
- self.button_add.set_sensitive(bool(iter and source))
+ self.button_add.set_sensitive(bool(iter and active))
def on_disc_found(self, finder, device, label):
"""
@@ -1488,7 +1644,7 @@ class AddDialog(object):
Show source properties dialog so user can set things like
subtitles, forcing deinterlacing, etc.
"""
- dialog = PropertiesDialog(self)
+ dialog = PropertiesDialog(self.get_source()[0], self.options)
dialog.window.run()
dialog.window.destroy()
View
10 arista/discoverer.py
@@ -22,7 +22,7 @@
"""
Class and functions for getting multimedia information about files
-Modified to support dvd://device@title style URIs using dvdreadsrc.
+Modified to support dvd://device@title:chapter:audio style URIs using dvdreadsrc.
Modified to support v4l://device style URIs using v4lsrc.
Modified to support v4l2://device style URIs using v4l2src.
@@ -136,9 +136,15 @@ def __init__(self, filename, max_interleave=1.0):
if len(parts) > 1:
# Specific chapter was requested, so we need to use a different
# source to manually specify the title to decode.
+ rest = parts[1].split(":")
self.src = gst.element_factory_make("dvdreadsrc")
self.src.set_property("device", parts[0][6:])
- self.src.set_property("title", int(parts[1]))
+ self.src.set_property("title", int(rest[0]))
+ if len(rest) > 1:
+ try:
+ self.src.set_property("chapter", int(rest[1]))
+ except:
+ pass
self.dbin = gst.element_factory_make("decodebin2")
self.add(self.src, self.dbin)
View
42 arista/transcoder.py
@@ -87,7 +87,8 @@ class TranscoderOptions(object):
"""
def __init__(self, uri = None, preset = None, output_uri = None, ssa = False,
subfile = None, subfile_charset = None, font = "Sans Bold 16",
- deinterlace = None, crop = None):
+ deinterlace = None, crop = None, title = None, chapter = None,
+ audio = None):
"""
@type uri: str
@param uri: The URI to the input file, device, or stream
@@ -107,13 +108,20 @@ def __init__(self, uri = None, preset = None, output_uri = None, ssa = False,
@type crop: int tuple
@param crop: How much should be cropped on each side
(top, right, bottom, left)
+ @type title: int
+ @param title: DVD title index
+ @type chatper: int
+ @param chapter: DVD chapter index
+ @type audio: int
+ @param audio: DVD audio stream index
"""
self.reset(uri, preset, output_uri, ssa,subfile, subfile_charset, font,
- deinterlace, crop)
+ deinterlace, crop, title, chapter, audio)
def reset(self, uri = None, preset = None, output_uri = None, ssa = False,
subfile = None, subfile_charset = None, font = "Sans Bold 16",
- deinterlace = None, crop = None):
+ deinterlace = None, crop = None, title = None, chapter = None,
+ audio = None):
"""
Reset the input options to nothing.
"""
@@ -126,6 +134,9 @@ def reset(self, uri = None, preset = None, output_uri = None, ssa = False,
self.font = font
self.deinterlace = deinterlace
self.crop = crop
+ self.title = title
+ self.chapter = chapter
+ self.audio = audio
# =============================================================================
# The Transcoder
@@ -166,16 +177,24 @@ def __init__(self, options):
self._percent_cached_time = 0
if options.uri.startswith("dvd://") and len(options.uri.split("@")) < 2:
+ options.uri += "@%(title)s:%(chapter)s:%(audio)s" % {
+ "title": options.title or "a",
+ "chapter": options.chapter or "a",
+ "audio": options.audio or "a",
+ }
+
+ if not options.title:
# This is a DVD and no title is yet selected... find the best
# candidate by searching for the longest title!
- self.options.uri += "@0"
+ parts = options.uri.split("@")
+ options.uri = parts[0] + "@0:a:a"
self.dvd_infos = []
def _got_info(info, is_media):
self.dvd_infos.append([discoverer, info])
parts = self.options.uri.split("@")
fname = parts[0]
- title = int(parts[1])
+ title = int(parts[1].split(":")[0])
if title >= 8:
# We've checked 8 titles, let's give up and pick the
# most likely to be the main feature.
@@ -209,7 +228,7 @@ def _got_info(info, is_media):
self.start()
return
- self.options.uri = fname + "@" + str(title + 1)
+ self.options.uri = fname + "@" + str(title + 1) + ":a:a"
self.discoverer = discoverer.Discoverer(options.uri)
self.discoverer.connect("discovered", _got_info)
self.discoverer.discover()
@@ -271,18 +290,23 @@ def _get_source(self):
if self.infile.startswith("dvd://"):
parts = self.infile.split("@")
device = parts[0][6:]
+ rest = len(parts) > 1 and parts[1].split(":")
title = 1
- if len(parts) > 1:
+ if rest:
try:
- title = int(parts[1])
+ title = int(rest[0])
except:
title = 1
+ try:
+ chapter = int(rest[1])
+ except:
+ chapter = None
if self.options.deinterlace is None:
self.options.deinterlace = True
- return "dvdreadsrc device=\"%s\" title=%d ! decodebin2 name=dmux" % (device, title)
+ return "dvdreadsrc device=\"%s\" title=%d %s ! decodebin2 name=dmux" % (device, title, chapter and "chapter=" + str(chapter) or '')
elif self.infile.startswith("v4l://") or self.infile.startswith("v4l2://"):
filename = self.infile
elif self.infile.startswith("file://"):
View
15 arista/utils.py
@@ -130,6 +130,21 @@ def get_write_path(*parts, **kwargs):
"path": path,
})
+def get_friendly_time(seconds):
+ """
+ Get a human-friendly time description.
+ """
+ hours = seconds / (60 * 60)
+ seconds = seconds % (60 * 60)
+ minutes = seconds / 60
+ seconds = seconds % 60
+
+ return "%(hours)02d:%(minutes)02d:%(seconds)02d" % {
+ "hours": hours,
+ "minutes": minutes,
+ "seconds": seconds,
+ }
+
def generate_output_path(filename, preset, to_be_created=[],
device_name=""):
"""
View
228 ui/props.ui
@@ -1,45 +1,208 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="2.16"/>
<!-- interface-naming-policy project-wide -->
<object class="GtkDialog" id="props_dialog">
<property name="width_request">350</property>
+ <property name="can_focus">False</property>
<property name="border_width">5</property>
<property name="title" translatable="yes">Source Properties</property>
<property name="window_position">center</property>
<property name="type_hint">normal</property>
- <property name="has_separator">False</property>
<child internal-child="vbox">
<object class="GtkVBox" id="dialog-vbox1">
<property name="visible">True</property>
- <property name="orientation">vertical</property>
+ <property name="can_focus">False</property>
<property name="spacing">2</property>
+ <child internal-child="action_area">
+ <object class="GtkHButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <object class="GtkButton" id="button1">
+ <property name="label">gtk-close</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
<child>
<object class="GtkVBox" id="vbox1">
<property name="visible">True</property>
- <property name="orientation">vertical</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkFrame" id="frame_dvd">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkAlignment" id="alignment3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="top_padding">5</property>
+ <property name="bottom_padding">5</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkTable" id="table_dvd">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="n_rows">4</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">5</property>
+ <property name="row_spacing">5</property>
+ <child>
+ <object class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Title:</property>
+ </object>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="combo_title">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_chapter">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Chapter:</property>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="combo_chapter">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label_audio">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Audio:</property>
+ </object>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBox" id="combo_audio">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">&lt;b&gt;DVD Options&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
<child>
<object class="GtkFrame" id="frame1">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="alignment1">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="top_padding">5</property>
+ <property name="bottom_padding">5</property>
<property name="left_padding">12</property>
<child>
<object class="GtkTable" id="table1">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="n_rows">2</property>
<property name="n_columns">2</property>
- <property name="column_spacing">4</property>
+ <property name="column_spacing">5</property>
<property name="row_spacing">5</property>
<child>
<object class="GtkFileChooserButton" id="filechooserbutton_subs">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="local_only">False</property>
<property name="title" translatable="yes">Select Subtitles</property>
- <signal name="file_set" handler="on_subs_set"/>
+ <signal name="file-set" handler="on_subs_set" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
@@ -49,6 +212,7 @@
<child>
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Subtitles to render:</property>
</object>
@@ -56,6 +220,7 @@
<child>
<object class="GtkLabel" id="label4">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Font to render:</property>
</object>
@@ -69,7 +234,8 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
- <signal name="font_set" handler="on_font_set"/>
+ <property name="use_action_appearance">False</property>
+ <signal name="font-set" handler="on_font_set" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
@@ -85,6 +251,7 @@
<child type="label">
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="label" translatable="yes">&lt;b&gt;Subtitles&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
@@ -92,17 +259,22 @@
</object>
<packing>
<property name="expand">False</property>
- <property name="position">0</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkFrame" id="frame2">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkAlignment" id="alignment2">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="top_padding">5</property>
+ <property name="bottom_padding">5</property>
<property name="left_padding">12</property>
<child>
<object class="GtkCheckButton" id="checkbutton_deinterlace">
@@ -110,8 +282,9 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
+ <property name="use_action_appearance">False</property>
<property name="draw_indicator">True</property>
- <signal name="toggled" handler="on_deinterlace"/>
+ <signal name="toggled" handler="on_deinterlace" swapped="no"/>
</object>
</child>
</object>
@@ -119,6 +292,7 @@
<child type="label">
<object class="GtkLabel" id="label3">
<property name="visible">True</property>
+ <property name="can_focus">False</property>
<property name="label" translatable="yes">&lt;b&gt;Deinterlacing&lt;/b&gt;</property>
<property name="use_markup">True</property>
</object>
@@ -126,45 +300,17 @@
</object>
<packing>
<property name="expand">False</property>
- <property name="position">1</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
</packing>
</child>
- <child>
- <placeholder/>
- </child>
</object>
<packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
- <child internal-child="action_area">
- <object class="GtkHButtonBox" id="dialog-action_area1">
- <property name="visible">True</property>
- <property name="layout_style">end</property>
- <child>
- <placeholder/>
- </child>
- <child>
- <object class="GtkButton" id="button1">
- <property name="label">gtk-close</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_stock">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
</object>
</child>
<action-widgets>

0 comments on commit 7f8c670

Please sign in to comment.
Something went wrong with that request. Please try again.