[pitivi] render: Make clear which muxers and encoders are unsupported
- From: Alexandru Băluț <alexbalut src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pitivi] render: Make clear which muxers and encoders are unsupported
- Date: Mon, 1 Aug 2016 17:09:27 +0000 (UTC)
commit 82966026ef5a980ea5f183424de859f77b5ba25a
Author: Alexandru Băluț <alexandru balut gmail com>
Date: Sat Jul 23 22:58:36 2016 +0200
render: Make clear which muxers and encoders are unsupported
The unsupported muxers and encoders appear under an "Unsupported"
element at the bottom of the comboboxes's model.
Fixes https://phabricator.freedesktop.org/T7496
Reviewed-by: Thibault Saunier <tsaunier gnome org>
Differential Revision: https://phabricator.freedesktop.org/D1217
data/ui/projectsettings.ui | 24 ----
data/ui/renderingdialog.ui | 70 +------------
pitivi/preset.py | 10 +-
pitivi/render.py | 254 +++++++++++++++++++++++++++-----------------
pitivi/utils/ui.py | 21 ++--
tests/test_render.py | 2 +-
6 files changed, 180 insertions(+), 201 deletions(-)
---
diff --git a/data/ui/projectsettings.ui b/data/ui/projectsettings.ui
index 9f4851e..99b9976 100644
--- a/data/ui/projectsettings.ui
+++ b/data/ui/projectsettings.ui
@@ -23,28 +23,6 @@
<property name="step_increment">1</property>
<property name="page_increment">10</property>
</object>
- <object class="GtkListStore" id="model1">
- <columns>
- <!-- column-name gchararray -->
- <column type="gchararray"/>
- </columns>
- <data>
- <row>
- <col id="0" translatable="yes">Standard (4:3)</col>
- </row>
- </data>
- </object>
- <object class="GtkListStore" id="model2">
- <columns>
- <!-- column-name gchararray -->
- <column type="gchararray"/>
- </columns>
- <data>
- <row>
- <col id="0" translatable="yes">Standard PAL</col>
- </row>
- </data>
- </object>
<object class="GtkDialog" id="project-settings-dialog">
<property name="can_focus">False</property>
<property name="border_width">5</property>
@@ -353,7 +331,6 @@
<object class="GtkComboBox" id="dar_combo">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="model">model1</property>
<child>
<object class="GtkCellRendererText" id="renderer1"/>
<attributes>
@@ -370,7 +347,6 @@
<object class="GtkComboBox" id="par_combo">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="model">model2</property>
<child>
<object class="GtkCellRendererText" id="renderer2"/>
<attributes>
diff --git a/data/ui/renderingdialog.ui b/data/ui/renderingdialog.ui
index d3338d5..9a9dece 100644
--- a/data/ui/renderingdialog.ui
+++ b/data/ui/renderingdialog.ui
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.19.0 -->
+<!-- Generated with glade 3.20.0 -->
<interface>
<requires lib="gtk+" version="3.10"/>
<object class="GtkAdjustment" id="adjustment1">
@@ -14,64 +14,6 @@
<property name="can_focus">False</property>
<property name="icon_name">help-contents</property>
</object>
- <object class="GtkListStore" id="model1">
- <columns>
- <!-- column-name gchararray -->
- <column type="gchararray"/>
- </columns>
- <data>
- <row>
- <col id="0" translatable="yes">MP4</col>
- </row>
- </data>
- </object>
- <object class="GtkListStore" id="model2">
- <columns>
- <!-- column-name gchararray -->
- <column type="gchararray"/>
- </columns>
- <data>
- <row>
- <col id="0" translatable="yes">H.264</col>
- </row>
- </data>
- </object>
- <object class="GtkListStore" id="model3">
- <columns>
- <!-- column-name gchararray -->
- <column type="gchararray"/>
- </columns>
- <data>
- <row>
- <col id="0" translatable="yes">29.97 fps</col>
- </row>
- </data>
- </object>
- <object class="GtkListStore" id="model4">
- <columns>
- <!-- column-name gchararray -->
- <column type="gchararray"/>
- </columns>
- <data>
- <row>
- <col id="0" translatable="yes">AC-3</col>
- </row>
- <row>
- <col id="0" translatable="yes">AAC</col>
- </row>
- </data>
- </object>
- <object class="GtkListStore" id="model5">
- <columns>
- <!-- column-name gchararray -->
- <column type="gchararray"/>
- </columns>
- <data>
- <row>
- <col id="0" translatable="yes">6 channels (5.1)</col>
- </row>
- </data>
- </object>
<object class="GtkDialog" id="render-dialog">
<property name="can_focus">False</property>
<property name="border_width">12</property>
@@ -230,8 +172,6 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
- <property name="model">model1</property>
- <property name="active">0</property>
<signal name="changed" handler="_muxerComboChangedCb" swapped="no"/>
<child>
<object class="GtkCellRendererText" id="renderer1"/>
@@ -476,7 +416,6 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
- <property name="model">model2</property>
<signal name="changed" handler="_videoEncoderComboChangedCb" swapped="no"/>
<child>
<object class="GtkCellRendererText" id="renderer2"/>
@@ -514,7 +453,6 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
- <property name="model">model3</property>
<signal name="changed" handler="_frameRateComboChangedCb" swapped="no"/>
<child>
<object class="GtkCellRendererText" id="renderer3"/>
@@ -613,7 +551,6 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
- <property name="model">model5</property>
<signal name="changed" handler="_channelsComboChangedCb" swapped="no"/>
<child>
<object class="GtkCellRendererText" id="renderer5"/>
@@ -650,7 +587,6 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
- <property name="model">model4</property>
<signal name="changed" handler="_audioEncoderChangedComboCb" swapped="no"/>
<child>
<object class="GtkCellRendererText" id="renderer4"/>
@@ -688,7 +624,6 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
- <property name="model">model5</property>
<signal name="changed" handler="_sampleRateComboChangedCb" swapped="no"/>
<child>
<object class="GtkCellRendererText" id="renderer6"/>
@@ -823,5 +758,8 @@ This option is a good trade-off between quality of the rendered video and stabil
<action-widget response="0">closebutton</action-widget>
<action-widget response="0">render_button</action-widget>
</action-widgets>
+ <child>
+ <placeholder/>
+ </child>
</object>
</interface>
diff --git a/pitivi/preset.py b/pitivi/preset.py
index 71a2aff..8c1ecc7 100644
--- a/pitivi/preset.py
+++ b/pitivi/preset.py
@@ -482,22 +482,22 @@ class AudioPresetManager(PresetManager):
class RenderPresetManager(PresetManager):
- def __init__(self, system):
+ def __init__(self, system, encoders):
default_path = get_renderpresets_dir()
user_path = os.path.join(xdg_data_home(), 'render_presets')
PresetManager.__init__(self, default_path, user_path, system)
+ self.encoders = encoders
def _deserializePreset(self, parser):
container = parser["container"]
acodec = parser["acodec"]
vcodec = parser["vcodec"]
- from pitivi.render import Encoders
- if acodec not in [fact.get_name() for fact in Encoders().aencoders]:
+ if acodec not in [fact.get_name() for fact in self.encoders.aencoders]:
raise DeserializeException("Audio codec not available: %s" % acodec)
- if vcodec not in [fact.get_name() for fact in Encoders().vencoders]:
+ if vcodec not in [fact.get_name() for fact in self.encoders.vencoders]:
raise DeserializeException("Video codec not available: %s" % vcodec)
- if container not in [fact.get_name() for fact in Encoders().muxers]:
+ if container not in [fact.get_name() for fact in self.encoders.muxers]:
raise DeserializeException("Container not available: %s" % vcodec)
try:
diff --git a/pitivi/render.py b/pitivi/render.py
index 8cb99cb..8aee2f9 100644
--- a/pitivi/render.py
+++ b/pitivi/render.py
@@ -30,6 +30,7 @@ from gi.repository import Gtk
from pitivi import configure
from pitivi.check import missing_soft_deps
+from pitivi.preset import RenderPresetManager
from pitivi.utils.loggable import Loggable
from pitivi.utils.misc import path_from_uri
from pitivi.utils.misc import show_user_manual
@@ -39,7 +40,6 @@ from pitivi.utils.ui import audio_rates
from pitivi.utils.ui import beautify_ETA
from pitivi.utils.ui import frame_rates
from pitivi.utils.ui import get_combo_value
-from pitivi.utils.ui import model
from pitivi.utils.ui import set_combo_value
from pitivi.utils.widgets import GstElementSettingsDialog
@@ -52,9 +52,15 @@ class Encoders(Loggable):
It is a singleton. Use `Encoders()` to access the instance.
Attributes:
- muxers (List[Gst.ElementFactory]): The avalaible muxers.
- aencoders (List[Gst.ElementFactory]): The avalaible audio encoders.
- vencoders (List[Gst.ElementFactory]): The avalaible video encoders.
+ supported_muxers (List[Gst.ElementFactory]): The supported available
+ muxers.
+ supported_aencoders (List[Gst.ElementFactory]): The supported available
+ audio encoders.
+ supported_vencoders (List[Gst.ElementFactory]): The supported available
+ video encoders.
+ muxers (List[Gst.ElementFactory]): The available muxers.
+ aencoders (List[Gst.ElementFactory]): The available audio encoders.
+ vencoders (List[Gst.ElementFactory]): The available video encoders.
compatible_audio_encoders (dict): Maps each muxer name to a list of
compatible audio encoders ordered by rank.
compatible_video_encoders (dict): Maps each muxer name to a list of
@@ -105,7 +111,7 @@ class Encoders(Loggable):
def __new__(cls, *args, **kwargs):
"""Returns the singleton instance."""
if not cls._instance:
- cls._instance = super(Encoders, cls).__new__(cls, *args, **kwargs)
+ cls._instance = super(Encoders, cls).__new__(cls)
# We have to initialize the instance here, otherwise
# __init__ is called every time we use Encoders().
Loggable.__init__(cls._instance)
@@ -150,6 +156,20 @@ class Encoders(Loggable):
for muxer in useless_muxers:
self.muxers.remove(muxer)
+ self.factories_by_name = dict([(fact.get_name(), fact)
+ for fact in self.muxers + self.aencoders + self.vencoders])
+
+ good_muxers, good_aencoders, good_vencoders = zip(*self.SUPPORTED_ENCODERS_COMBINATIONS)
+ self.supported_muxers = set([muxer
+ for muxer in self.muxers
+ if muxer.get_name() in good_muxers])
+ self.supported_aencoders = set([encoder
+ for encoder in self.aencoders
+ if encoder.get_name() in good_aencoders])
+ self.supported_vencoders = set([encoder
+ for encoder in self.vencoders
+ if encoder.get_name() in good_vencoders])
+
self.default_muxer, \
self.default_audio_encoder, \
self.default_video_encoder = self._pick_defaults()
@@ -182,28 +202,39 @@ class Encoders(Loggable):
Returns:
(str, str, str): The muxer, audio encoder, video encoder.
"""
- muxer_names = [fact.get_name() for fact in self.muxers]
- aencoder_names = [fact.get_name() for fact in self.aencoders]
- vencoder_names = [fact.get_name() for fact in self.vencoders]
for muxer, audio, video in self.SUPPORTED_ENCODERS_COMBINATIONS:
- if muxer not in muxer_names or \
- audio not in aencoder_names or \
- video not in vencoder_names:
+ if muxer not in self.factories_by_name or \
+ audio not in self.factories_by_name or \
+ video not in self.factories_by_name:
continue
self.info("Default encoders: %s, %s, %s", muxer, audio, video)
return muxer, audio, video
self.warning("No good combination of container and encoders available.")
return Encoders.OGG, Encoders.VORBIS, Encoders.THEORA
+ def is_supported(self, factory):
+ """Returns whether the specified factory is supported."""
+ if type(factory) is str:
+ factory = self.factories_by_name[factory]
+ return factory in self.supported_muxers or\
+ factory in self.supported_aencoders or\
+ factory in self.supported_vencoders
+
def _registry_feature_added_cb(self, registry, feature):
# TODO Check what feature has been added and update our lists
pass
-def beautify_factoryname(factory):
+def beautify_factory_name(factory):
"""Returns a nice name for the specified Gst.ElementFactory instance.
Intended for removing redundant words and shorten the codec names.
+
+ Args:
+ factory (Gst.ElementFactory): The factory which needs to be displayed.
+
+ Returns:
+ str: Cleaned up name.
"""
# Only replace lowercase versions of "format", "video", "audio"
# otherwise they might be part of a trademark name.
@@ -257,23 +288,6 @@ def extension_for_muxer(muxer_name):
return exts.get(muxer_name)
-def factorylist(factories):
- """Creates a Gtk.ListStore() of sorted, beautified factory names.
-
- Args:
- factories (List[Gst.ElementFactory]): The factories for display.
-
- Returns:
- Gtk.ListStore: The model with to columns for name and factory.
- """
- columns = (str, object)
- data = [(beautify_factoryname(factory), factory)
- for factory in factories
- if factory.get_rank() > 0]
- data.sort(key=lambda x: x[0])
- return model(columns, data)
-
-
# --------------------------------- Public classes -----------------------------#
class RenderingProgressDialog(GObject.Object):
@@ -377,8 +391,6 @@ class RenderDialog(Loggable):
_factory_formats = {}
def __init__(self, app, project):
- from pitivi.preset import RenderPresetManager
-
Loggable.__init__(self)
self.app = app
@@ -401,9 +413,11 @@ class RenderDialog(Loggable):
# {object: sigId}
self._gstSigId = {}
- self.render_presets = RenderPresetManager(self.app.system)
+ self.render_presets = RenderPresetManager(self.app.system, Encoders())
self.render_presets.loadAll()
+ # Whether encoders changing are a result of changing the muxer.
+ self.muxer_combo_changing = False
self._createUi()
# Directory and Filename
@@ -420,7 +434,10 @@ class RenderDialog(Loggable):
self.preferred_aencoder = self.project.aencoder
self.__unproxiedClips = {}
- self._initializeComboboxModels()
+ self.frame_rate_combo.set_model(frame_rates)
+ self.channels_combo.set_model(audio_channels)
+ self.sample_rate_combo.set_model(audio_rates)
+ self.__initialize_muxers_model()
self._displaySettings()
self._displayRenderSettings()
@@ -434,7 +451,7 @@ class RenderDialog(Loggable):
self.wg.addVertex(self.frame_rate_combo, signal="changed")
self.wg.addVertex(self.channels_combo, signal="changed")
self.wg.addVertex(self.sample_rate_combo, signal="changed")
- self.wg.addVertex(self.muxercombobox, signal="changed")
+ self.wg.addVertex(self.muxer_combo, signal="changed")
self.wg.addVertex(self.audio_encoder_combo, signal="changed")
self.wg.addVertex(self.video_encoder_combo, signal="changed")
self.wg.addVertex(self.preset_menubutton,
@@ -443,15 +460,15 @@ class RenderDialog(Loggable):
self.wg.addEdge(self.frame_rate_combo, self.preset_menubutton)
self.wg.addEdge(self.audio_encoder_combo, self.preset_menubutton)
self.wg.addEdge(self.video_encoder_combo, self.preset_menubutton)
- self.wg.addEdge(self.muxercombobox, self.preset_menubutton)
+ self.wg.addEdge(self.muxer_combo, self.preset_menubutton)
self.wg.addEdge(self.channels_combo, self.preset_menubutton)
self.wg.addEdge(self.sample_rate_combo, self.preset_menubutton)
# Bind widgets to RenderPresetsManager
self.render_presets.bindWidget(
"container",
- lambda x: self.muxer_setter(self.muxercombobox, x),
- lambda: get_combo_value(self.muxercombobox).get_name())
+ lambda x: self.muxer_setter(self.muxer_combo, x),
+ lambda: get_combo_value(self.muxer_combo).get_name())
self.render_presets.bindWidget(
"acodec",
lambda x: self.acodec_setter(self.audio_encoder_combo, x),
@@ -484,34 +501,30 @@ class RenderDialog(Loggable):
def _updatePresetMenuButton(self, unused_source, unused_target):
self.render_presets.updateMenuActions()
- def muxer_setter(self, widget, value):
- set_combo_value(widget, Gst.ElementFactory.find(value))
- self.project.setEncoders(muxer=value)
+ def muxer_setter(self, widget, muxer_name):
+ set_combo_value(widget, Encoders().factories_by_name.get(muxer_name))
+ self.project.setEncoders(muxer=muxer_name)
# Update the extension of the filename.
basename = os.path.splitext(self.fileentry.get_text())[0]
self.updateFilename(basename)
# Update muxer-dependent widgets.
- self.muxer_combo_changing = True
- try:
- self.updateAvailableEncoders()
- finally:
- self.muxer_combo_changing = False
+ self.updateAvailableEncoders()
- def acodec_setter(self, widget, value):
- set_combo_value(widget, Gst.ElementFactory.find(value))
- self.project.aencoder = value
+ def acodec_setter(self, widget, aencoder_name):
+ set_combo_value(widget, Encoders().factories_by_name.get(aencoder_name))
+ self.project.aencoder = aencoder_name
if not self.muxer_combo_changing:
# The user directly changed the audio encoder combo.
- self.preferred_aencoder = value
+ self.preferred_aencoder = aencoder_name
- def vcodec_setter(self, widget, value):
- set_combo_value(widget, Gst.ElementFactory.find(value))
- self.project.setEncoders(vencoder=value)
+ def vcodec_setter(self, widget, vencoder_name):
+ set_combo_value(widget, Encoders().factories_by_name.get(vencoder_name))
+ self.project.setEncoders(vencoder=vencoder_name)
if not self.muxer_combo_changing:
# The user directly changed the video encoder combo.
- self.preferred_vencoder = value
+ self.preferred_vencoder = vencoder_name
def sample_rate_setter(self, widget, value):
set_combo_value(widget, value)
@@ -542,10 +555,12 @@ class RenderDialog(Loggable):
self.audio_settings_button = builder.get_object(
"audio_settings_button")
self.frame_rate_combo = builder.get_object("frame_rate_combo")
+ self.frame_rate_combo.set_model(frame_rates)
self.scale_spinbutton = builder.get_object("scale_spinbutton")
self.channels_combo = builder.get_object("channels_combo")
+ self.channels_combo.set_model(audio_channels)
self.sample_rate_combo = builder.get_object("sample_rate_combo")
- self.muxercombobox = builder.get_object("muxercombobox")
+ self.muxer_combo = builder.get_object("muxercombobox")
self.audio_encoder_combo = builder.get_object("audio_encoder_combo")
self.video_encoder_combo = builder.get_object("video_encoder_combo")
self.filebutton = builder.get_object("filebutton")
@@ -575,12 +590,45 @@ class RenderDialog(Loggable):
def _settingsChanged(self, unused_project, unused_key, unused_value):
self.updateResolution()
- def _initializeComboboxModels(self):
- # Avoid loop import
- self.frame_rate_combo.set_model(frame_rates)
- self.channels_combo.set_model(audio_channels)
- self.sample_rate_combo.set_model(audio_rates)
- self.muxercombobox.set_model(factorylist(Encoders().muxers))
+ def __initialize_muxers_model(self):
+ # By default show only supported muxers and encoders.
+ model = self.create_combobox_model(Encoders().muxers)
+ self.muxer_combo.set_model(model)
+
+ def create_combobox_model(self, factories):
+ """Creates a model for a combobox showing factories.
+
+ Args:
+ combobox (Gtk.ComboBox): The combobox to setup.
+ factories (List[Gst.ElementFactory]): The factories to display.
+
+ Returns:
+ Gtk.ListStore: The model with (display name, factory, unsupported).
+ """
+ model = Gtk.TreeStore(str, object)
+ data_supported = []
+ data_unsupported = []
+ for factory in factories:
+ supported = Encoders().is_supported(factory)
+ row = (beautify_factory_name(factory), factory)
+ if supported:
+ data_supported.append(row)
+ else:
+ data_unsupported.append(row)
+
+ data_supported.sort()
+ for row in data_supported:
+ model.append(None, row)
+
+ # Translators: This item appears in a combobox's popup and
+ # contains as children the unsupported (but still available)
+ # muxers and encoders.
+ unsupported_iter = model.append(None, (_("Unsupported"), None))
+ data_unsupported.sort()
+ for row in data_unsupported:
+ model.append(unsupported_iter, row)
+
+ return model
def _displaySettings(self):
"""Displays the settings also in the ProjectSettingsDialog."""
@@ -597,8 +645,8 @@ class RenderDialog(Loggable):
self.scale_spinbutton.set_value(self.project.render_scale)
# Muxer settings
# This will trigger an update of the codec comboboxes.
- set_combo_value(self.muxercombobox,
- Gst.ElementFactory.find(self.project.muxer))
+ set_combo_value(self.muxer_combo,
+ Encoders().factories_by_name.get(self.project.muxer))
def _checkForExistingFile(self, *unused_args):
"""Displays a warning if the file path already exists."""
@@ -659,30 +707,44 @@ class RenderDialog(Loggable):
def updateAvailableEncoders(self):
"""Updates the encoder comboboxes to show the available encoders."""
- vencoder_model = factorylist(
- Encoders().compatible_video_encoders[self.project.muxer])
- self.video_encoder_combo.set_model(vencoder_model)
-
- aencoder_model = factorylist(
- Encoders().compatible_audio_encoders[self.project.muxer])
- self.audio_encoder_combo.set_model(aencoder_model)
-
- self._updateEncoderCombo(
- self.video_encoder_combo, self.preferred_vencoder)
- self._updateEncoderCombo(
- self.audio_encoder_combo, self.preferred_aencoder)
+ self.muxer_combo_changing = True
+ try:
+ model = self.create_combobox_model(
+ Encoders().compatible_video_encoders[self.project.muxer])
+ self.video_encoder_combo.set_model(model)
+ self._update_encoder_combo(self.video_encoder_combo,
+ self.preferred_vencoder)
+
+ model = self.create_combobox_model(
+ Encoders().compatible_audio_encoders[self.project.muxer])
+ self.audio_encoder_combo.set_model(model)
+ self._update_encoder_combo(self.audio_encoder_combo,
+ self.preferred_aencoder)
+ finally:
+ self.muxer_combo_changing = False
- def _updateEncoderCombo(self, encoder_combo, preferred_encoder):
+ def _update_encoder_combo(self, encoder_combo, preferred_encoder):
"""Selects the specified encoder for the specified encoder combo."""
if preferred_encoder:
# A preference exists, pick it if it can be found in
# the current model of the combobox.
- vencoder = Gst.ElementFactory.find(preferred_encoder)
- set_combo_value(encoder_combo, vencoder, default_index=0)
- else:
- # No preference exists, pick the first encoder from
- # the current model of the combobox.
- encoder_combo.set_active(0)
+ encoder = Encoders().factories_by_name.get(preferred_encoder)
+ set_combo_value(encoder_combo, encoder)
+ if not preferred_encoder or not get_combo_value(encoder_combo):
+ # No preference exists or it is not available,
+ # pick the first encoder from the combobox's model.
+ first = encoder_combo.props.model.get_iter_first()
+ if not first:
+ # Model is empty. Should not happen.
+ self.warning("Model is empty")
+ return
+ if not encoder_combo.props.model.iter_has_child(first):
+ # The first item is a supported factory.
+ encoder_combo.set_active_iter(first)
+ else:
+ # The first element is the Unsupported group.
+ second = encoder_combo.props.model.iter_nth_child(first, 0)
+ encoder_combo.set_active_iter(second)
def _elementSettingsDialog(self, factory, settings_attr):
"""Opens a dialog to edit the properties for the specified factory.
@@ -846,7 +908,7 @@ class RenderDialog(Loggable):
except KeyError:
# Now find a format to set on the restriction caps.
# The reason is we can't send different formats on the encoders.
- factory = Gst.ElementFactory.find(self.project.vencoder)
+ factory = Encoders().factories_by_name.get(self.project.vencoder)
for struct in factory.get_static_pad_templates():
if struct.direction == Gst.PadDirection.SINK:
caps = Gst.Caps.from_string(struct.get_caps().to_string())
@@ -1040,12 +1102,13 @@ class RenderDialog(Loggable):
self.project.framerate = framerate
def _videoEncoderComboChangedCb(self, combo):
- vencoder = get_combo_value(combo).get_name()
- self.project.vencoder = vencoder
-
+ factory = get_combo_value(combo)
+ name = factory.get_name()
+ self.project.vencoder = name
if not self.muxer_combo_changing:
# The user directly changed the video encoder combo.
- self.preferred_vencoder = vencoder
+ self.debug("User chose a video encoder: %s", name)
+ self.preferred_vencoder = name
def _videoSettingsButtonClickedCb(self, unused_button):
factory = get_combo_value(self.video_encoder_combo)
@@ -1058,27 +1121,26 @@ class RenderDialog(Loggable):
self.project.audiorate = get_combo_value(combo)
def _audioEncoderChangedComboCb(self, combo):
- aencoder = get_combo_value(combo).get_name()
- self.project.aencoder = aencoder
+ factory = get_combo_value(combo)
+ name = factory.get_name()
+ self.project.aencoder = name
if not self.muxer_combo_changing:
# The user directly changed the audio encoder combo.
- self.preferred_aencoder = aencoder
+ self.debug("User chose an audio encoder: %s", name)
+ self.preferred_aencoder = name
def _audioSettingsButtonClickedCb(self, unused_button):
factory = get_combo_value(self.audio_encoder_combo)
self._elementSettingsDialog(factory, 'acodecsettings')
- def _muxerComboChangedCb(self, muxer_combo):
+ def _muxerComboChangedCb(self, combo):
"""Handles the changing of the container format combobox."""
- self.project.muxer = get_combo_value(muxer_combo).get_name()
+ factory = get_combo_value(combo)
+ self.project.muxer = factory.get_name()
# Update the extension of the filename.
basename = os.path.splitext(self.fileentry.get_text())[0]
self.updateFilename(basename)
# Update muxer-dependent widgets.
- self.muxer_combo_changing = True
- try:
- self.updateAvailableEncoders()
- finally:
- self.muxer_combo_changing = False
+ self.updateAvailableEncoders()
diff --git a/pitivi/utils/ui.py b/pitivi/utils/ui.py
index 3cf94ac..ebad6f6 100644
--- a/pitivi/utils/ui.py
+++ b/pitivi/utils/ui.py
@@ -459,18 +459,21 @@ def model(columns, data):
return ret
-def set_combo_value(combo, value, default_index=-1):
- model = combo.props.model
- for i, row in enumerate(model):
- if row[1] == value:
- combo.set_active(i)
- return
- combo.set_active(default_index)
+def set_combo_value(combo, value):
+ def select_specific_row(model, unused_path, iter_, unused_data):
+ if value == model.get_value(iter_, 1):
+ combo.set_active_iter(iter_)
+ return True
+ return False
+
+ combo.props.model.foreach(select_specific_row, None)
def get_combo_value(combo):
- active = combo.get_active()
- return combo.props.model[active][1]
+ active_iter = combo.get_active_iter()
+ if not active_iter:
+ return None
+ return combo.props.model.get_value(active_iter, 1)
def get_value_from_model(model, key):
diff --git a/tests/test_render.py b/tests/test_render.py
index da3d789..ca8ec3b 100644
--- a/tests/test_render.py
+++ b/tests/test_render.py
@@ -37,7 +37,7 @@ class TestRender(TestCase):
"""Checks we associate file extensions to the muxers of the presets."""
with mock.patch("pitivi.preset.xdg_data_home") as xdg_data_home:
xdg_data_home.return_value = "/pitivi-dir-which-does-not-exist"
- preset_manager = RenderPresetManager(system=None)
+ preset_manager = RenderPresetManager(system=None, encoders=Encoders())
preset_manager.loadAll()
self.assertTrue(preset_manager.presets)
for unused_name, preset in preset_manager.presets.items():
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]