def setUp(self): # We use a real default path to get some real presets self.default_path = get_audiopresets_dir() # Create some fake dir to avoid messing actual data self.user_path = tempfile.mkdtemp() self.manager = AudioPresetManager() self.manager.default_path = self.default_path self.manager.user_path = self.user_path
def testEsotericFilenames(self): self.manager.addPreset("Default", {"channels": 2, "depth": -9000, "sample-rate": 44100, "filepath": os.path.join(self.user_path, "Default.json")}) self.manager.saveAll() self.manager.addPreset('Solid Snake (ソリッド・スネーク) \#!"/$%?&*', {"name": "デイビッド", "channels": 2, "depth": 16, "sample-rate": 44100, "filepath": os.path.join(self.user_path, 'Solid Snake (ソリッド・スネーク) \#!"/$%?&*' + ".json")}) snake = self.manager.presets['Solid Snake (ソリッド・スネーク) \#!"/$%?&*'] self.assertEqual(5, len(snake)) # The slash ("/") in the filename is supposed to make it choke #self.assertRaises(IOError, self.manager.saveAll) # Let's be slightly more gentle snake["filepath"] = os.path.join(self.user_path, 'Solid Snake (ソリッド・スネーク)' + ".json") self.manager.saveAll() # Create a second concurrent instance with the same paths, # to check that it can read and write from the first instance's data other_manager = AudioPresetManager() other_manager.default_path = self.default_path other_manager.user_path = self.user_path other_manager.loadAll() snaaaake = other_manager.presets['Solid Snake (ソリッド・スネーク)'] self.assertEqual(2, snaaaake["channels"]) foo = other_manager.presets['Default'] self.assertEqual(4, len(foo)) self.assertEqual(-9000, foo["depth"]) self.assertEquals(2, len(other_manager.presets))
def testRenamingSystemPresets(self): self.manager.loadAll() system_presets = list(self.manager.presets.keys()) new_name_template = "%s new" for preset_name in system_presets: self.manager.restorePreset(preset_name) new_name = new_name_template % preset_name self.manager.saveCurrentPreset(new_name) # Check that the files have not been deleted or changed. other_manager = AudioPresetManager(System()) other_manager.user_path = "/pitivi/non/existing/directory" other_manager.loadAll() for preset_name in system_presets: self.assertTrue(other_manager.hasPreset(preset_name), preset_name) other_manager = self.createOtherManager() other_manager.loadAll() for preset_name in system_presets: self.assertFalse(other_manager.hasPreset(preset_name), preset_name) new_name = new_name_template % preset_name self.assertTrue(other_manager.hasPreset(new_name), new_name)
def testRemovingSystemPresets(self): self.manager.loadAll() system_presets = list(self.manager.presets.keys()) for preset_name in system_presets: self.manager.restorePreset(preset_name) self.manager.removeCurrentPreset() # Check that the files have not been deleted or changed. other_manager = AudioPresetManager(System()) other_manager.user_path = "/pitivi/non/existing/directory" other_manager.loadAll() for preset_name in system_presets: self.assertTrue(other_manager.hasPreset(preset_name)) # Check that overwrite files have been created and # they mark the system presets as deleted. other_manager = self.createOtherManager() other_manager.loadAll() for preset_name in system_presets: self.assertFalse(other_manager.hasPreset(preset_name))
def testRenamingSystemPresets(self): self.manager.loadAll() system_presets = list(self.manager.presets.keys()) new_name_template = "%s new" for preset_name in system_presets: self.manager.restorePreset(preset_name) new_name = new_name_template % preset_name self.manager.saveCurrentPreset(new_name) # Check that the files have not been deleted or changed. other_manager = AudioPresetManager() other_manager.user_path = "/pitivi/non/existing/directory" other_manager.loadAll() for preset_name in system_presets: self.assertTrue(other_manager.hasPreset(preset_name), preset_name) other_manager = self.createOtherManager() other_manager.loadAll() for preset_name in system_presets: self.assertFalse(other_manager.hasPreset(preset_name), preset_name) new_name = new_name_template % preset_name self.assertTrue(other_manager.hasPreset(new_name), new_name)
def testRemovingSystemPresets(self): self.manager.loadAll() system_presets = list(self.manager.presets.keys()) for preset_name in system_presets: self.manager.restorePreset(preset_name) self.manager.removeCurrentPreset() # Check that the files have not been deleted or changed. other_manager = AudioPresetManager() other_manager.user_path = "/pitivi/non/existing/directory" other_manager.loadAll() for preset_name in system_presets: self.assertTrue(other_manager.hasPreset(preset_name)) # Check that overwrite files have been created and # they mark the system presets as deleted. other_manager = self.createOtherManager() other_manager.loadAll() for preset_name in system_presets: self.assertFalse(other_manager.hasPreset(preset_name))
def createOtherManager(self): other_manager = AudioPresetManager(System()) other_manager.user_path = self.manager.user_path return other_manager
def setUp(self): self.manager = AudioPresetManager(System()) self.manager.user_path = tempfile.mkdtemp()
class TestAudioPresetsIO(common.TestCase): def setUp(self): self.manager = AudioPresetManager(System()) self.manager.user_path = tempfile.mkdtemp() def tearDown(self): clearPresetManagerPaths(self.manager) def createOtherManager(self): other_manager = AudioPresetManager(System()) other_manager.user_path = self.manager.user_path return other_manager def testSaveAndLoad(self): self.manager.createPreset("Vegeta", { "channels": 6000, "sample-rate": 44100 }) self.manager.saveAll() self.assertEqual(1, countUserPresets(self.manager)) self.manager.createPreset("Nappa", { "channels": 4000, "sample-rate": 44100 }) self.manager.saveAll() self.assertEqual(2, countUserPresets(self.manager)) other_manager = self.createOtherManager() other_manager.loadAll() total_presets = countDefaultPresets(self.manager) + countUserPresets( self.manager) self.assertEqual(total_presets, len(other_manager.presets)) def testNonAsciiFilenamesSaveAndLoad(self): non_ascii_preset_name = "Solid Snake (ソリッド・スネーク) \\#!\"'$%?&*" self.manager.createPreset(non_ascii_preset_name, { "channels": 2, "sample-rate": 44100 }) snake = self.manager.presets[non_ascii_preset_name] self.assertEqual(2, len(snake)) self.manager.saveAll() other_manager = self.createOtherManager() other_manager.loadAll() self.assertEqual(1 + countDefaultPresets(other_manager), len(other_manager.presets)) snaaaake = other_manager.presets[non_ascii_preset_name] self.assertEqual(snake, snaaaake) def testInvalidFilenamesSaveAndLoad(self): # This would be an invalid file name as is. preset_name = " / % " self.manager.createPreset(preset_name, { "channels": 2, "sample-rate": 44100 }) values = self.manager.presets[preset_name] self.assertEqual(2, len(values)) self.manager.saveAll() other_manager = self.createOtherManager() other_manager.loadAll() self.assertEqual(1 + countDefaultPresets(other_manager), len(other_manager.presets)) other_values = other_manager.presets[preset_name] self.assertEqual(values, other_values) def testRemovingSystemPresets(self): self.manager.loadAll() system_presets = list(self.manager.presets.keys()) for preset_name in system_presets: self.manager.restorePreset(preset_name) self.manager.removeCurrentPreset() # Check that the files have not been deleted or changed. other_manager = AudioPresetManager(System()) other_manager.user_path = "/pitivi/non/existing/directory" other_manager.loadAll() for preset_name in system_presets: self.assertTrue(other_manager.hasPreset(preset_name)) # Check that overwrite files have been created and # they mark the system presets as deleted. other_manager = self.createOtherManager() other_manager.loadAll() for preset_name in system_presets: self.assertFalse(other_manager.hasPreset(preset_name)) def testRenamingSystemPresets(self): self.manager.loadAll() system_presets = list(self.manager.presets.keys()) new_name_template = "%s new" for preset_name in system_presets: self.manager.restorePreset(preset_name) new_name = new_name_template % preset_name self.manager.saveCurrentPreset(new_name) # Check that the files have not been deleted or changed. other_manager = AudioPresetManager(System()) other_manager.user_path = "/pitivi/non/existing/directory" other_manager.loadAll() for preset_name in system_presets: self.assertTrue(other_manager.hasPreset(preset_name), preset_name) other_manager = self.createOtherManager() other_manager.loadAll() for preset_name in system_presets: self.assertFalse(other_manager.hasPreset(preset_name), preset_name) new_name = new_name_template % preset_name self.assertTrue(other_manager.hasPreset(new_name), new_name)
def createOtherManager(self): other_manager = AudioPresetManager() other_manager.default_path = self.manager.default_path other_manager.user_path = self.manager.user_path return other_manager
def setUp(self): self.manager = AudioPresetManager() setPresetManagerPaths(self.manager, get_audiopresets_dir())
class TestAudioPresetsIO(TestCase): def setUp(self): self.manager = AudioPresetManager() setPresetManagerPaths(self.manager, get_audiopresets_dir()) def tearDown(self): clearPresetManagerPaths(self.manager) def createOtherManager(self): other_manager = AudioPresetManager() other_manager.default_path = self.manager.default_path other_manager.user_path = self.manager.user_path return other_manager def testSaveAndLoad(self): self.manager.addPreset("Vegeta", {"channels": 6000, "sample-rate": 44100}) self.manager.saveAll() self.assertEqual(1, countUserPresets(self.manager)) self.manager.addPreset("Nappa", {"channels": 4000, "sample-rate": 44100}) self.manager.saveAll() self.assertEqual(2, countUserPresets(self.manager)) other_manager = self.createOtherManager() other_manager.loadAll() total_presets = countDefaultPresets( self.manager) + countUserPresets(self.manager) self.assertEqual(total_presets, len(other_manager.presets)) def testNonAsciiFilenamesSaveAndLoad(self): non_ascii_preset_name = "Solid Snake (ソリッド・スネーク) \\#!\"'$%?&*" self.manager.addPreset(non_ascii_preset_name, {"channels": 2, "sample-rate": 44100}) snake = self.manager.presets[non_ascii_preset_name] self.assertEqual(2, len(snake)) self.manager.saveAll() other_manager = self.createOtherManager() other_manager.loadAll() self.assertEqual(1 + countDefaultPresets( other_manager), len(other_manager.presets)) snaaaake = other_manager.presets[non_ascii_preset_name] self.assertEqual(snake, snaaaake) def testInvalidFilenamesSaveAndLoad(self): # This would be an invalid file name as is. preset_name = " / % " self.manager.addPreset(preset_name, {"channels": 2, "sample-rate": 44100}) values = self.manager.presets[preset_name] self.assertEqual(2, len(values)) self.manager.saveAll() other_manager = self.createOtherManager() other_manager.loadAll() self.assertEqual(1 + countDefaultPresets( other_manager), len(other_manager.presets)) other_values = other_manager.presets[preset_name] self.assertEqual(values, other_values)
def testSaveAndLoad(self): def countDefaultPresets(): foo = 0 for file in os.listdir(self.default_path): # This is needed to avoid a miscount with makefiles and such if file.endswith(".json"): foo += 1 return foo def countUserPresets(): return len(os.listdir(self.user_path)) self.manager.addPreset("Vegeta", {"channels": 6000, "depth": 16, "sample-rate": 44100, "filepath": os.path.join(self.user_path, "vegeta.json")}) self.manager.cur_preset = "Vegeta" self.manager.savePreset() self.assertEqual(1, countUserPresets()) self.manager.addPreset("Nappa", {"channels": 4000, "depth": 16, "sample-rate": 44100, "filepath": os.path.join(self.user_path, "nappa.json")}) self.assertEqual(1, countUserPresets()) self.manager.saveAll() self.assertEqual(2, countUserPresets()) self.assertIn("vegeta.json", os.listdir(self.user_path)) self.assertIn("nappa.json", os.listdir(self.user_path)) other_manager = AudioPresetManager() other_manager.default_path = self.default_path other_manager.user_path = self.user_path other_manager.loadAll() total_presets = countDefaultPresets() + countUserPresets() self.assertEqual(total_presets, len(other_manager.presets)) # Test invalid filenames/filepaths # Testing with an invalid filepath: self.manager.addPreset("Sangoku", {"channels": 8001, "depth": 32, "sample-rate": 44100, "filepath": "INVALID FILENAME?!"}) self.assertEqual(2 + countDefaultPresets(), len(other_manager.presets)) self.manager.saveAll() # The filepath was invalid. It was not actually a path. self.assertEqual(2, len(os.listdir(self.user_path))) # Testing with an invalid filename: self.manager.presets["Sangoku"]["filepath"] = os.path.join(self.user_path, "INVALID FILENAME?!") self.manager.saveAll() # The filepath did not have a ".json" file extension # While such a file would be written to disk, it would not be loaded self.assertEqual(3, len(os.listdir(self.user_path))) # Trying to load all presets multiple times will create duplicates... self.assertRaises(DuplicatePresetNameException, other_manager.loadAll) # So let's reset it to a clean state: other_manager = AudioPresetManager() other_manager.default_path = self.default_path other_manager.user_path = self.user_path other_manager.loadAll() # We only expect two valid, loaded presets: nappa and vegeta self.assertEqual(2 + countDefaultPresets(), len(other_manager.presets))
class TestPresetsIO(TestCase): def setUp(self): # We use a real default path to get some real presets self.default_path = get_audiopresets_dir() # Create some fake dir to avoid messing actual data self.user_path = tempfile.mkdtemp() self.manager = AudioPresetManager() self.manager.default_path = self.default_path self.manager.user_path = self.user_path def tearDown(self): # Delete the user directory we created (but not the default directory) shutil.rmtree(self.user_path) def testSaveAndLoad(self): def countDefaultPresets(): foo = 0 for file in os.listdir(self.default_path): # This is needed to avoid a miscount with makefiles and such if file.endswith(".json"): foo += 1 return foo def countUserPresets(): return len(os.listdir(self.user_path)) self.manager.addPreset("Vegeta", {"channels": 6000, "depth": 16, "sample-rate": 44100, "filepath": os.path.join(self.user_path, "vegeta.json")}) self.manager.cur_preset = "Vegeta" self.manager.savePreset() self.assertEqual(1, countUserPresets()) self.manager.addPreset("Nappa", {"channels": 4000, "depth": 16, "sample-rate": 44100, "filepath": os.path.join(self.user_path, "nappa.json")}) self.assertEqual(1, countUserPresets()) self.manager.saveAll() self.assertEqual(2, countUserPresets()) self.assertIn("vegeta.json", os.listdir(self.user_path)) self.assertIn("nappa.json", os.listdir(self.user_path)) other_manager = AudioPresetManager() other_manager.default_path = self.default_path other_manager.user_path = self.user_path other_manager.loadAll() total_presets = countDefaultPresets() + countUserPresets() self.assertEqual(total_presets, len(other_manager.presets)) # Test invalid filenames/filepaths # Testing with an invalid filepath: self.manager.addPreset("Sangoku", {"channels": 8001, "depth": 32, "sample-rate": 44100, "filepath": "INVALID FILENAME?!"}) self.assertEqual(2 + countDefaultPresets(), len(other_manager.presets)) self.manager.saveAll() # The filepath was invalid. It was not actually a path. self.assertEqual(2, len(os.listdir(self.user_path))) # Testing with an invalid filename: self.manager.presets["Sangoku"]["filepath"] = os.path.join(self.user_path, "INVALID FILENAME?!") self.manager.saveAll() # The filepath did not have a ".json" file extension # While such a file would be written to disk, it would not be loaded self.assertEqual(3, len(os.listdir(self.user_path))) # Trying to load all presets multiple times will create duplicates... self.assertRaises(DuplicatePresetNameException, other_manager.loadAll) # So let's reset it to a clean state: other_manager = AudioPresetManager() other_manager.default_path = self.default_path other_manager.user_path = self.user_path other_manager.loadAll() # We only expect two valid, loaded presets: nappa and vegeta self.assertEqual(2 + countDefaultPresets(), len(other_manager.presets)) def testEsotericFilenames(self): self.manager.addPreset("Default", {"channels": 2, "depth": -9000, "sample-rate": 44100, "filepath": os.path.join(self.user_path, "Default.json")}) self.manager.saveAll() self.manager.addPreset('Solid Snake (ソリッド・スネーク) \#!"/$%?&*', {"name": "デイビッド", "channels": 2, "depth": 16, "sample-rate": 44100, "filepath": os.path.join(self.user_path, 'Solid Snake (ソリッド・スネーク) \#!"/$%?&*' + ".json")}) snake = self.manager.presets['Solid Snake (ソリッド・スネーク) \#!"/$%?&*'] self.assertEqual(5, len(snake)) # The slash ("/") in the filename is supposed to make it choke #self.assertRaises(IOError, self.manager.saveAll) # Let's be slightly more gentle snake["filepath"] = os.path.join(self.user_path, 'Solid Snake (ソリッド・スネーク)' + ".json") self.manager.saveAll() # Create a second concurrent instance with the same paths, # to check that it can read and write from the first instance's data other_manager = AudioPresetManager() other_manager.default_path = self.default_path other_manager.user_path = self.user_path other_manager.loadAll() snaaaake = other_manager.presets['Solid Snake (ソリッド・スネーク)'] self.assertEqual(2, snaaaake["channels"]) foo = other_manager.presets['Default'] self.assertEqual(4, len(foo)) self.assertEqual(-9000, foo["depth"]) self.assertEquals(2, len(other_manager.presets))
def setUp(self): self.manager = AudioPresetManager() self.manager.user_path = tempfile.mkdtemp()
class TestAudioPresetsIO(TestCase): def setUp(self): self.manager = AudioPresetManager() self.manager.user_path = tempfile.mkdtemp() def tearDown(self): clearPresetManagerPaths(self.manager) def createOtherManager(self): other_manager = AudioPresetManager() other_manager.user_path = self.manager.user_path return other_manager def testSaveAndLoad(self): self.manager.createPreset("Vegeta", {"channels": 6000, "sample-rate": 44100}) self.manager.saveAll() self.assertEqual(1, countUserPresets(self.manager)) self.manager.createPreset("Nappa", {"channels": 4000, "sample-rate": 44100}) self.manager.saveAll() self.assertEqual(2, countUserPresets(self.manager)) other_manager = self.createOtherManager() other_manager.loadAll() total_presets = countDefaultPresets( self.manager) + countUserPresets(self.manager) self.assertEqual(total_presets, len(other_manager.presets)) def testNonAsciiFilenamesSaveAndLoad(self): non_ascii_preset_name = "Solid Snake (ソリッド・スネーク) \\#!\"'$%?&*" self.manager.createPreset(non_ascii_preset_name, {"channels": 2, "sample-rate": 44100}) snake = self.manager.presets[non_ascii_preset_name] self.assertEqual(2, len(snake)) self.manager.saveAll() other_manager = self.createOtherManager() other_manager.loadAll() self.assertEqual(1 + countDefaultPresets( other_manager), len(other_manager.presets)) snaaaake = other_manager.presets[non_ascii_preset_name] self.assertEqual(snake, snaaaake) def testInvalidFilenamesSaveAndLoad(self): # This would be an invalid file name as is. preset_name = " / % " self.manager.createPreset(preset_name, {"channels": 2, "sample-rate": 44100}) values = self.manager.presets[preset_name] self.assertEqual(2, len(values)) self.manager.saveAll() other_manager = self.createOtherManager() other_manager.loadAll() self.assertEqual(1 + countDefaultPresets( other_manager), len(other_manager.presets)) other_values = other_manager.presets[preset_name] self.assertEqual(values, other_values) def testRemovingSystemPresets(self): self.manager.loadAll() system_presets = list(self.manager.presets.keys()) for preset_name in system_presets: self.manager.restorePreset(preset_name) self.manager.removeCurrentPreset() # Check that the files have not been deleted or changed. other_manager = AudioPresetManager() other_manager.user_path = "/pitivi/non/existing/directory" other_manager.loadAll() for preset_name in system_presets: self.assertTrue(other_manager.hasPreset(preset_name)) # Check that overwrite files have been created and # they mark the system presets as deleted. other_manager = self.createOtherManager() other_manager.loadAll() for preset_name in system_presets: self.assertFalse(other_manager.hasPreset(preset_name)) def testRenamingSystemPresets(self): self.manager.loadAll() system_presets = list(self.manager.presets.keys()) new_name_template = "%s new" for preset_name in system_presets: self.manager.restorePreset(preset_name) new_name = new_name_template % preset_name self.manager.saveCurrentPreset(new_name) # Check that the files have not been deleted or changed. other_manager = AudioPresetManager() other_manager.user_path = "/pitivi/non/existing/directory" other_manager.loadAll() for preset_name in system_presets: self.assertTrue(other_manager.hasPreset(preset_name), preset_name) other_manager = self.createOtherManager() other_manager.loadAll() for preset_name in system_presets: self.assertFalse(other_manager.hasPreset(preset_name), preset_name) new_name = new_name_template % preset_name self.assertTrue(other_manager.hasPreset(new_name), new_name)
def __init__(self, parent, project): self.project = project self.settings = project.getSettings() self.builder = gtk.Builder() self.builder.add_from_file(os.path.join(get_ui_dir(), "projectsettings.ui")) self._setProperties() self.builder.connect_signals(self) # add custom display aspect ratio widget self.dar_fraction_widget = FractionWidget() self.video_properties_table.attach(self.dar_fraction_widget, 0, 1, 6, 7, xoptions=gtk.EXPAND | gtk.FILL, yoptions=0) self.dar_fraction_widget.show() # add custom pixel aspect ratio widget self.par_fraction_widget = FractionWidget() self.video_properties_table.attach(self.par_fraction_widget, 1, 2, 6, 7, xoptions=gtk.EXPAND | gtk.FILL, yoptions=0) self.par_fraction_widget.show() # add custom framerate widget self.frame_rate_fraction_widget = FractionWidget() self.video_properties_table.attach(self.frame_rate_fraction_widget, 1, 2, 2, 3, xoptions=gtk.EXPAND | gtk.FILL, yoptions=0) self.frame_rate_fraction_widget.show() # populate coboboxes with appropriate data self.frame_rate_combo.set_model(frame_rates) self.dar_combo.set_model(display_aspect_ratios) self.par_combo.set_model(pixel_aspect_ratios) self.channels_combo.set_model(audio_channels) self.sample_rate_combo.set_model(audio_rates) self.sample_depth_combo.set_model(audio_depths) # behavior self.wg = RippleUpdateGroup() self.wg.addVertex(self.frame_rate_combo, signal="changed", update_func=self._updateCombo, update_func_args=(self.frame_rate_fraction_widget,)) self.wg.addVertex(self.frame_rate_fraction_widget, signal="value-changed", update_func=self._updateFraction, update_func_args=(self.frame_rate_combo,)) self.wg.addVertex(self.dar_combo, signal="changed") self.wg.addVertex(self.dar_fraction_widget, signal="value-changed") self.wg.addVertex(self.par_combo, signal="changed") self.wg.addVertex(self.par_fraction_widget, signal="value-changed") self.wg.addVertex(self.width_spinbutton, signal="value-changed") self.wg.addVertex(self.height_spinbutton, signal="value-changed") self.wg.addVertex(self.save_audio_preset_button, update_func=self._updateAudioSaveButton) self.wg.addVertex(self.save_video_preset_button, update_func=self._updateVideoSaveButton) self.wg.addVertex(self.channels_combo, signal="changed") self.wg.addVertex(self.sample_rate_combo, signal="changed") self.wg.addVertex(self.sample_depth_combo, signal="changed") # constrain width and height IFF constrain_sar_button is active self.wg.addEdge(self.width_spinbutton, self.height_spinbutton, predicate=self.constrained, edge_func=self.updateHeight) self.wg.addEdge(self.height_spinbutton, self.width_spinbutton, predicate=self.constrained, edge_func=self.updateWidth) # keep framereate text field and combo in sync self.wg.addBiEdge(self.frame_rate_combo, self.frame_rate_fraction_widget) # keep dar text field and combo in sync self.wg.addEdge(self.dar_combo, self.dar_fraction_widget, edge_func=self.updateDarFromCombo) self.wg.addEdge(self.dar_fraction_widget, self.dar_combo, edge_func=self.updateDarFromFractionWidget) # keep par text field and combo in sync self.wg.addEdge(self.par_combo, self.par_fraction_widget, edge_func=self.updateParFromCombo) self.wg.addEdge(self.par_fraction_widget, self.par_combo, edge_func=self.updateParFromFractionWidget) # constrain DAR and PAR values. because the combo boxes are already # linked, we only have to link the fraction widgets together. self.wg.addEdge(self.par_fraction_widget, self.dar_fraction_widget, edge_func=self.updateDarFromPar) self.wg.addEdge(self.dar_fraction_widget, self.par_fraction_widget, edge_func=self.updateParFromDar) # update PAR when width/height change and the DAR checkbutton is # selected self.wg.addEdge(self.width_spinbutton, self.par_fraction_widget, predicate=self.darSelected, edge_func=self.updateParFromDar) self.wg.addEdge(self.height_spinbutton, self.par_fraction_widget, predicate=self.darSelected, edge_func=self.updateParFromDar) # update DAR when width/height change and the PAR checkbutton is # selected self.wg.addEdge(self.width_spinbutton, self.dar_fraction_widget, predicate=self.parSelected, edge_func=self.updateDarFromPar) self.wg.addEdge(self.height_spinbutton, self.dar_fraction_widget, predicate=self.parSelected, edge_func=self.updateDarFromPar) # presets self.audio_presets = AudioPresetManager() self.audio_presets.loadAll() self.video_presets = VideoPresetManager() self.video_presets.loadAll() self._fillPresetsTreeview( self.audio_preset_treeview, self.audio_presets, self._updateAudioPresetButtons) self._fillPresetsTreeview( self.video_preset_treeview, self.video_presets, self._updateVideoPresetButtons) # A map which tells which infobar should be used when displaying # an error for a preset manager. self._infobarForPresetManager = { self.audio_presets: self.audio_preset_infobar, self.video_presets: self.video_preset_infobar} # Bind the widgets in the Video tab to the Video Presets Manager. self.bindSpinbutton(self.video_presets, "width", self.width_spinbutton) self.bindSpinbutton(self.video_presets, "height", self.height_spinbutton) self.bindFractionWidget(self.video_presets, "frame-rate", self.frame_rate_fraction_widget) self.bindPar(self.video_presets) # Bind the widgets in the Audio tab to the Audio Presets Manager. self.bindCombo(self.audio_presets, "channels", self.channels_combo) self.bindCombo(self.audio_presets, "sample-rate", self.sample_rate_combo) self.bindCombo(self.audio_presets, "depth", self.sample_depth_combo) self.wg.addEdge(self.par_fraction_widget, self.save_video_preset_button) self.wg.addEdge(self.frame_rate_fraction_widget, self.save_video_preset_button) self.wg.addEdge(self.width_spinbutton, self.save_video_preset_button) self.wg.addEdge(self.height_spinbutton, self.save_video_preset_button) self.wg.addEdge(self.channels_combo, self.save_audio_preset_button) self.wg.addEdge(self.sample_rate_combo, self.save_audio_preset_button) self.wg.addEdge(self.sample_depth_combo, self.save_audio_preset_button) self.updateUI() self.createAudioNoPreset(self.audio_presets) self.createVideoNoPreset(self.video_presets)
class ProjectSettingsDialog(): def __init__(self, parent, project): self.project = project self.settings = project.getSettings() self.builder = gtk.Builder() self.builder.add_from_file(os.path.join(get_ui_dir(), "projectsettings.ui")) self._setProperties() self.builder.connect_signals(self) # add custom display aspect ratio widget self.dar_fraction_widget = FractionWidget() self.video_properties_table.attach(self.dar_fraction_widget, 0, 1, 6, 7, xoptions=gtk.EXPAND | gtk.FILL, yoptions=0) self.dar_fraction_widget.show() # add custom pixel aspect ratio widget self.par_fraction_widget = FractionWidget() self.video_properties_table.attach(self.par_fraction_widget, 1, 2, 6, 7, xoptions=gtk.EXPAND | gtk.FILL, yoptions=0) self.par_fraction_widget.show() # add custom framerate widget self.frame_rate_fraction_widget = FractionWidget() self.video_properties_table.attach(self.frame_rate_fraction_widget, 1, 2, 2, 3, xoptions=gtk.EXPAND | gtk.FILL, yoptions=0) self.frame_rate_fraction_widget.show() # populate coboboxes with appropriate data self.frame_rate_combo.set_model(frame_rates) self.dar_combo.set_model(display_aspect_ratios) self.par_combo.set_model(pixel_aspect_ratios) self.channels_combo.set_model(audio_channels) self.sample_rate_combo.set_model(audio_rates) self.sample_depth_combo.set_model(audio_depths) # behavior self.wg = RippleUpdateGroup() self.wg.addVertex(self.frame_rate_combo, signal="changed", update_func=self._updateCombo, update_func_args=(self.frame_rate_fraction_widget,)) self.wg.addVertex(self.frame_rate_fraction_widget, signal="value-changed", update_func=self._updateFraction, update_func_args=(self.frame_rate_combo,)) self.wg.addVertex(self.dar_combo, signal="changed") self.wg.addVertex(self.dar_fraction_widget, signal="value-changed") self.wg.addVertex(self.par_combo, signal="changed") self.wg.addVertex(self.par_fraction_widget, signal="value-changed") self.wg.addVertex(self.width_spinbutton, signal="value-changed") self.wg.addVertex(self.height_spinbutton, signal="value-changed") self.wg.addVertex(self.save_audio_preset_button, update_func=self._updateAudioSaveButton) self.wg.addVertex(self.save_video_preset_button, update_func=self._updateVideoSaveButton) self.wg.addVertex(self.channels_combo, signal="changed") self.wg.addVertex(self.sample_rate_combo, signal="changed") self.wg.addVertex(self.sample_depth_combo, signal="changed") # constrain width and height IFF constrain_sar_button is active self.wg.addEdge(self.width_spinbutton, self.height_spinbutton, predicate=self.constrained, edge_func=self.updateHeight) self.wg.addEdge(self.height_spinbutton, self.width_spinbutton, predicate=self.constrained, edge_func=self.updateWidth) # keep framereate text field and combo in sync self.wg.addBiEdge(self.frame_rate_combo, self.frame_rate_fraction_widget) # keep dar text field and combo in sync self.wg.addEdge(self.dar_combo, self.dar_fraction_widget, edge_func=self.updateDarFromCombo) self.wg.addEdge(self.dar_fraction_widget, self.dar_combo, edge_func=self.updateDarFromFractionWidget) # keep par text field and combo in sync self.wg.addEdge(self.par_combo, self.par_fraction_widget, edge_func=self.updateParFromCombo) self.wg.addEdge(self.par_fraction_widget, self.par_combo, edge_func=self.updateParFromFractionWidget) # constrain DAR and PAR values. because the combo boxes are already # linked, we only have to link the fraction widgets together. self.wg.addEdge(self.par_fraction_widget, self.dar_fraction_widget, edge_func=self.updateDarFromPar) self.wg.addEdge(self.dar_fraction_widget, self.par_fraction_widget, edge_func=self.updateParFromDar) # update PAR when width/height change and the DAR checkbutton is # selected self.wg.addEdge(self.width_spinbutton, self.par_fraction_widget, predicate=self.darSelected, edge_func=self.updateParFromDar) self.wg.addEdge(self.height_spinbutton, self.par_fraction_widget, predicate=self.darSelected, edge_func=self.updateParFromDar) # update DAR when width/height change and the PAR checkbutton is # selected self.wg.addEdge(self.width_spinbutton, self.dar_fraction_widget, predicate=self.parSelected, edge_func=self.updateDarFromPar) self.wg.addEdge(self.height_spinbutton, self.dar_fraction_widget, predicate=self.parSelected, edge_func=self.updateDarFromPar) # presets self.audio_presets = AudioPresetManager() self.audio_presets.loadAll() self.video_presets = VideoPresetManager() self.video_presets.loadAll() self._fillPresetsTreeview( self.audio_preset_treeview, self.audio_presets, self._updateAudioPresetButtons) self._fillPresetsTreeview( self.video_preset_treeview, self.video_presets, self._updateVideoPresetButtons) # A map which tells which infobar should be used when displaying # an error for a preset manager. self._infobarForPresetManager = { self.audio_presets: self.audio_preset_infobar, self.video_presets: self.video_preset_infobar} # Bind the widgets in the Video tab to the Video Presets Manager. self.bindSpinbutton(self.video_presets, "width", self.width_spinbutton) self.bindSpinbutton(self.video_presets, "height", self.height_spinbutton) self.bindFractionWidget(self.video_presets, "frame-rate", self.frame_rate_fraction_widget) self.bindPar(self.video_presets) # Bind the widgets in the Audio tab to the Audio Presets Manager. self.bindCombo(self.audio_presets, "channels", self.channels_combo) self.bindCombo(self.audio_presets, "sample-rate", self.sample_rate_combo) self.bindCombo(self.audio_presets, "depth", self.sample_depth_combo) self.wg.addEdge(self.par_fraction_widget, self.save_video_preset_button) self.wg.addEdge(self.frame_rate_fraction_widget, self.save_video_preset_button) self.wg.addEdge(self.width_spinbutton, self.save_video_preset_button) self.wg.addEdge(self.height_spinbutton, self.save_video_preset_button) self.wg.addEdge(self.channels_combo, self.save_audio_preset_button) self.wg.addEdge(self.sample_rate_combo, self.save_audio_preset_button) self.wg.addEdge(self.sample_depth_combo, self.save_audio_preset_button) self.updateUI() self.createAudioNoPreset(self.audio_presets) self.createVideoNoPreset(self.video_presets) def bindPar(self, mgr): def updatePar(value): # activate par so we can set the value self.select_par_radiobutton.props.active = True self.par_fraction_widget.setWidgetValue(value) mgr.bindWidget("par", updatePar, self.par_fraction_widget.getWidgetValue) def bindFractionWidget(self, mgr, name, widget): mgr.bindWidget(name, widget.setWidgetValue, widget.getWidgetValue) def bindCombo(self, mgr, name, widget): mgr.bindWidget(name, lambda x: set_combo_value(widget, x), lambda: get_combo_value(widget)) def bindSpinbutton(self, mgr, name, widget): mgr.bindWidget(name, lambda x: widget.set_value(float(x)), lambda: int(widget.get_value())) def _fillPresetsTreeview(self, treeview, mgr, update_buttons_func): """Set up the specified treeview to display the specified presets. @param treeview: The treeview for displaying the presets. @type treeview: TreeView @param mgr: The preset manager. @type mgr: PresetManager @param update_buttons_func: A function which updates the buttons for removing and saving a preset, enabling or disabling them accordingly. @type update_buttons_func: function """ renderer = gtk.CellRendererText() renderer.props.editable = True column = gtk.TreeViewColumn("Preset", renderer, text=0) treeview.append_column(column) treeview.props.headers_visible = False model = mgr.getModel() treeview.set_model(model) model.connect("row-inserted", self._newPresetCb, column, renderer, treeview) renderer.connect("edited", self._presetNameEditedCb, mgr) renderer.connect("editing-started", self._presetNameEditingStartedCb, mgr) treeview.get_selection().connect("changed", self._presetChangedCb, mgr, update_buttons_func) treeview.connect("focus-out-event", self._treeviewDefocusedCb, mgr) def createAudioNoPreset(self, mgr): mgr.prependPreset(_("No preset"), { "depth": int(get_combo_value(self.sample_depth_combo)), "channels": int(get_combo_value(self.channels_combo)), "sample-rate": int(get_combo_value(self.sample_rate_combo))}) def createVideoNoPreset(self, mgr): mgr.prependPreset(_("No preset"), { "par": gst.Fraction(int(get_combo_value(self.par_combo).num), int(get_combo_value(self.par_combo).denom)), "frame-rate": gst.Fraction(int(get_combo_value(self.frame_rate_combo).num), int(get_combo_value(self.frame_rate_combo).denom)), "height": int(self.height_spinbutton.get_value()), "width": int(self.width_spinbutton.get_value())}) def _newPresetCb(self, model, path, iter_, column, renderer, treeview): """Handle the addition of a preset to the model of the preset manager. """ treeview.set_cursor_on_cell(path, column, renderer, start_editing=True) treeview.grab_focus() def _presetNameEditedCb(self, renderer, path, new_text, mgr): """Handle the renaming of a preset.""" try: mgr.renamePreset(path, new_text) except DuplicatePresetNameException: error_markup = _('"%s" already exists.') % new_text self._showPresetManagerError(mgr, error_markup) def _presetNameEditingStartedCb(self, renderer, editable, path, mgr): """Handle the start of a preset renaming.""" self._hidePresetManagerError(mgr) def _presetChangedCb(self, selection, mgr, update_preset_buttons_func): """Handle the selection of a preset.""" model, iter_ = selection.get_selected() if iter_: preset = model[iter_][0] else: preset = None mgr.restorePreset(preset) update_preset_buttons_func() self._hidePresetManagerError(mgr) def _treeviewDefocusedCb(self, widget, event, mgr): self._hidePresetManagerError(mgr) def _showPresetManagerError(self, mgr, error_markup): """Show the specified error on the infobar associated with the manager. @param mgr: The preset manager for which to show the error. @type mgr: PresetManager """ infobar = self._infobarForPresetManager[mgr] # The infobar must contain exactly one object in the content area: # a label for displaying the error. label = infobar.get_content_area().children()[0] label.set_markup(error_markup) infobar.show() def _hidePresetManagerError(self, mgr): """Hide the error infobar associated with the manager. @param mgr: The preset manager for which to hide the error infobar. @type mgr: PresetManager """ infobar = self._infobarForPresetManager[mgr] infobar.hide() def constrained(self): return self.constrain_sar_button.props.active def _updateFraction(self, unused, fraction, combo): fraction.setWidgetValue(get_combo_value(combo)) def _updateCombo(self, unused, combo, fraction): set_combo_value(combo, fraction.getWidgetValue()) def getSAR(self): width = int(self.width_spinbutton.get_value()) height = int(self.height_spinbutton.get_value()) return gst.Fraction(width, height) def _setProperties(self): getObj = self.builder.get_object self.window = getObj("project-settings-dialog") self.video_properties_table = getObj("video_properties_table") self.video_properties_table = getObj("video_properties_table") self.frame_rate_combo = getObj("frame_rate_combo") self.dar_combo = getObj("dar_combo") self.par_combo = getObj("par_combo") self.channels_combo = getObj("channels_combo") self.sample_rate_combo = getObj("sample_rate_combo") self.sample_depth_combo = getObj("sample_depth_combo") self.year_spinbutton = getObj("year_spinbutton") self.author_entry = getObj("author_entry") self.width_spinbutton = getObj("width_spinbutton") self.height_spinbutton = getObj("height_spinbutton") self.save_audio_preset_button = getObj("save_audio_preset_button") self.save_video_preset_button = getObj("save_video_preset_button") self.audio_preset_treeview = getObj("audio_preset_treeview") self.video_preset_treeview = getObj("video_preset_treeview") self.select_par_radiobutton = getObj("select_par_radiobutton") self.remove_audio_preset_button = getObj("remove_audio_preset_button") self.remove_video_preset_button = getObj("remove_video_preset_button") self.constrain_sar_button = getObj("constrain_sar_button") self.select_dar_radiobutton = getObj("select_dar_radiobutton") self.video_preset_infobar = getObj("video-preset-infobar") self.audio_preset_infobar = getObj("audio-preset-infobar") self.title_entry = getObj("title_entry") self.author_entry = getObj("author_entry") self.year_spinbutton = getObj("year_spinbutton") def _constrainSarButtonToggledCb(self, button): if button.props.active: self.sar = self.getSAR() def _selectDarRadiobuttonToggledCb(self, button): state = button.props.active self.dar_fraction_widget.set_sensitive(state) self.dar_combo.set_sensitive(state) self.par_fraction_widget.set_sensitive(not state) self.par_combo.set_sensitive(not state) @staticmethod def _getUniquePresetName(mgr): """Get a unique name for a new preset for the specified PresetManager. """ existing_preset_names = list(mgr.getPresetNames()) preset_name = _("New preset") i = 1 while preset_name in existing_preset_names: preset_name = _("New preset %d") % i i += 1 return preset_name def _addAudioPresetButtonClickedCb(self, button): preset_name = self._getUniquePresetName(self.audio_presets) self.audio_presets.addPreset(preset_name, { "channels": get_combo_value(self.channels_combo), "sample-rate": get_combo_value(self.sample_rate_combo), "depth": get_combo_value(self.sample_depth_combo) }) self.audio_presets.restorePreset(preset_name) self._updateAudioPresetButtons() def _removeAudioPresetButtonClickedCb(self, button): selection = self.audio_preset_treeview.get_selection() model, iter_ = selection.get_selected() if iter_: self.audio_presets.removePreset(model[iter_][0]) def _saveAudioPresetButtonClickedCb(self, button): self.audio_presets.savePreset() self.save_audio_preset_button.set_sensitive(False) self.remove_audio_preset_button.set_sensitive(True) def _addVideoPresetButtonClickedCb(self, button): preset_name = self._getUniquePresetName(self.video_presets) self.video_presets.addPreset(preset_name, { "width": int(self.width_spinbutton.get_value()), "height": int(self.height_spinbutton.get_value()), "frame-rate": self.frame_rate_fraction_widget.getWidgetValue(), "par": self.par_fraction_widget.getWidgetValue(), }) self.video_presets.restorePreset(preset_name) self._updateVideoPresetButtons() def _removeVideoPresetButtonClickedCb(self, button): selection = self.video_preset_treeview.get_selection() model, iter_ = selection.get_selected() if iter_: self.video_presets.removePreset(model[iter_][0]) def _saveVideoPresetButtonClickedCb(self, button): self.video_presets.savePreset() self.save_video_preset_button.set_sensitive(False) self.remove_video_preset_button.set_sensitive(True) def _updateAudioPresetButtons(self): can_save = self.audio_presets.isSaveButtonSensitive() self.save_audio_preset_button.set_sensitive(can_save) can_remove = self.audio_presets.isRemoveButtonSensitive() self.remove_audio_preset_button.set_sensitive(can_remove) def _updateVideoPresetButtons(self): self.save_video_preset_button.set_sensitive(self.video_presets.isSaveButtonSensitive()) self.remove_video_preset_button.set_sensitive(self.video_presets.isRemoveButtonSensitive()) def _updateAudioSaveButton(self, unused_in, button): button.set_sensitive(self.audio_presets.isSaveButtonSensitive()) def _updateVideoSaveButton(self, unused_in, button): button.set_sensitive(self.video_presets.isSaveButtonSensitive()) def darSelected(self): return self.select_dar_radiobutton.props.active def parSelected(self): return not self.darSelected() def updateWidth(self): height = int(self.height_spinbutton.get_value()) self.width_spinbutton.set_value(height * self.sar) def updateHeight(self): width = int(self.width_spinbutton.get_value()) self.height_spinbutton.set_value(width * (1 / self.sar)) def updateDarFromPar(self): par = self.par_fraction_widget.getWidgetValue() sar = self.getSAR() self.dar_fraction_widget.setWidgetValue(sar * par) def updateParFromDar(self): dar = self.dar_fraction_widget.getWidgetValue() sar = self.getSAR() self.par_fraction_widget.setWidgetValue(dar * (1 / sar)) def updateDarFromCombo(self): self.dar_fraction_widget.setWidgetValue(get_combo_value(self.dar_combo)) def updateDarFromFractionWidget(self): set_combo_value(self.dar_combo, self.dar_fraction_widget.getWidgetValue()) def updateParFromCombo(self): self.par_fraction_widget.setWidgetValue(get_combo_value(self.par_combo)) def updateParFromFractionWidget(self): set_combo_value(self.par_combo, self.par_fraction_widget.getWidgetValue()) def updateUI(self): self.width_spinbutton.set_value(self.settings.videowidth) self.height_spinbutton.set_value(self.settings.videoheight) # video self.frame_rate_fraction_widget.setWidgetValue(self.settings.videorate) self.par_fraction_widget.setWidgetValue(self.settings.videopar) # audio set_combo_value(self.channels_combo, self.settings.audiochannels) set_combo_value(self.sample_rate_combo, self.settings.audiorate) set_combo_value(self.sample_depth_combo, self.settings.audiodepth) self._selectDarRadiobuttonToggledCb(self.select_dar_radiobutton) # metadata self.title_entry.set_text(self.project.name) self.author_entry.set_text(self.project.author) if self.project.year: year = int(self.project.year) else: year = datetime.now().year self.year_spinbutton.get_adjustment().set_value(year) def updateMetadata(self): self.project.name = self.title_entry.get_text() self.project.author = self.author_entry.get_text() self.project.year = str(self.year_spinbutton.get_value_as_int()) def updateSettings(self): width = int(self.width_spinbutton.get_value()) height = int(self.height_spinbutton.get_value()) par = self.par_fraction_widget.getWidgetValue() frame_rate = self.frame_rate_fraction_widget.getWidgetValue() channels = get_combo_value(self.channels_combo) sample_rate = get_combo_value(self.sample_rate_combo) sample_depth = get_combo_value(self.sample_depth_combo) self.settings.setVideoProperties(width, height, frame_rate, par) self.settings.setAudioProperties(channels, sample_rate, sample_depth) self.project.setSettings(self.settings) def _responseCb(self, unused_widget, response): if response == gtk.RESPONSE_OK: self.updateSettings() self.updateMetadata() self.window.destroy()
class TestAudioPresetsIO(TestCase): def setUp(self): self.manager = AudioPresetManager() setPresetManagerPaths(self.manager, get_audiopresets_dir()) def tearDown(self): clearPresetManagerPaths(self.manager) def createOtherManager(self): other_manager = AudioPresetManager() other_manager.default_path = self.manager.default_path other_manager.user_path = self.manager.user_path return other_manager def testSaveAndLoad(self): self.manager.addPreset("Vegeta", { "channels": 6000, "sample-rate": 44100 }) self.manager.saveAll() self.assertEqual(1, countUserPresets(self.manager)) self.manager.addPreset("Nappa", { "channels": 4000, "sample-rate": 44100 }) self.manager.saveAll() self.assertEqual(2, countUserPresets(self.manager)) other_manager = self.createOtherManager() other_manager.loadAll() total_presets = countDefaultPresets(self.manager) + countUserPresets( self.manager) self.assertEqual(total_presets, len(other_manager.presets)) def testNonAsciiFilenamesSaveAndLoad(self): non_ascii_preset_name = "Solid Snake (ソリッド・スネーク) \\#!\"'$%?&*" self.manager.addPreset(non_ascii_preset_name, { "channels": 2, "sample-rate": 44100 }) snake = self.manager.presets[non_ascii_preset_name] self.assertEqual(2, len(snake)) self.manager.saveAll() other_manager = self.createOtherManager() other_manager.loadAll() self.assertEqual(1 + countDefaultPresets(other_manager), len(other_manager.presets)) snaaaake = other_manager.presets[non_ascii_preset_name] self.assertEqual(snake, snaaaake) def testInvalidFilenamesSaveAndLoad(self): # This would be an invalid file name as is. preset_name = " / % " self.manager.addPreset(preset_name, { "channels": 2, "sample-rate": 44100 }) values = self.manager.presets[preset_name] self.assertEqual(2, len(values)) self.manager.saveAll() other_manager = self.createOtherManager() other_manager.loadAll() self.assertEqual(1 + countDefaultPresets(other_manager), len(other_manager.presets)) other_values = other_manager.presets[preset_name] self.assertEqual(values, other_values)