From 06825e4aeb8810217f1587984c1f3d86854be94e Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Fri, 23 May 2014 15:39:25 +0200 Subject: [PATCH] Added support for audio cds and udisks2 --- openlp/core/ui/media/mediacontroller.py | 10 +- openlp/core/ui/media/vlcplayer.py | 14 +- .../media/forms/mediaclipselectorform.py | 202 ++++++++++++------ openlp/plugins/media/lib/mediaitem.py | 2 +- 4 files changed, 160 insertions(+), 68 deletions(-) diff --git a/openlp/core/ui/media/mediacontroller.py b/openlp/core/ui/media/mediacontroller.py index 993172354..b25556e73 100644 --- a/openlp/core/ui/media/mediacontroller.py +++ b/openlp/core/ui/media/mediacontroller.py @@ -464,7 +464,10 @@ class MediaController(RegistryMixin, OpenLPMixin, RegistryProperties): # Setup media info controller.media_info = MediaInfo() controller.media_info.file_info = QtCore.QFileInfo(filename) - controller.media_info.media_type = MediaType.DVD + if audio_track == -1 and subtitle_track == -1: + controller.media_info.media_type = MediaType.CD + else: + controller.media_info.media_type = MediaType.DVD controller.media_info.start_time = start/1000 controller.media_info.end_time = end/1000 controller.media_info.length = (end - start)/1000 @@ -489,7 +492,10 @@ class MediaController(RegistryMixin, OpenLPMixin, RegistryProperties): vlc_player.load(display) self.resize(display, vlc_player) self.current_media_players[controller.controller_type] = vlc_player - controller.media_info.media_type = MediaType.DVD + if audio_track == -1 and subtitle_track == -1: + controller.media_info.media_type = MediaType.CD + else: + controller.media_info.media_type = MediaType.DVD return True def _check_file_type(self, controller, display, service_item): diff --git a/openlp/core/ui/media/vlcplayer.py b/openlp/core/ui/media/vlcplayer.py index 6fd9bafd3..0c6d91078 100644 --- a/openlp/core/ui/media/vlcplayer.py +++ b/openlp/core/ui/media/vlcplayer.py @@ -166,7 +166,19 @@ class VlcPlayer(MediaPlayer): file_path = str(controller.media_info.file_info.absoluteFilePath()) path = os.path.normcase(file_path) # create the media - display.vlc_media = display.vlc_instance.media_new_path(path) + if controller.media_info.media_type == MediaType.CD: + display.vlc_media = display.vlc_instance.media_new_location('cdda://' + path) + display.vlc_media_player.set_media(display.vlc_media) + display.vlc_media_player.play() + # Wait for media to start playing. In this case VLC actually returns an error. + self.media_state_wait(display, vlc.State.Playing) + # If subitems exists, this is a CD + audio_cd_tracks = display.vlc_media.subitems() + if not audio_cd_tracks or audio_cd_tracks.count() < 1: + return False + display.vlc_media = audio_cd_tracks.item_at_index(controller.media_info.title_track) + else: + display.vlc_media = display.vlc_instance.media_new_path(path) # put the media in the media player display.vlc_media_player.set_media(display.vlc_media) # parse the metadata of the file diff --git a/openlp/plugins/media/forms/mediaclipselectorform.py b/openlp/plugins/media/forms/mediaclipselectorform.py index e9f46d9d1..82b3cd9ea 100644 --- a/openlp/plugins/media/forms/mediaclipselectorform.py +++ b/openlp/plugins/media/forms/mediaclipselectorform.py @@ -150,6 +150,40 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector): self.timer.timeout.connect(self.update_position) self.timer.start(100) self.find_optical_devices() + self.audio_cd = False + self.audio_cd_tracks = None + + def detect_audio_cd(self, path): + """ + Detects is the given path is an audio CD + + :param path: Path to the device to be tested. + :return: True if it was an audio CD else False. + """ + # Detect by trying to play it as a CD + self.vlc_media = self.vlc_instance.media_new_location('cdda://' + path) + self.vlc_media_player.set_media(self.vlc_media) + self.vlc_media_player.play() + # Wait for media to start playing. In this case VLC actually returns an error. + self.media_state_wait(vlc.State.Playing) + self.vlc_media_player.pause() + # If subitems exists, this is a CD + self.audio_cd_tracks = self.vlc_media.subitems() + if not self.audio_cd_tracks or self.audio_cd_tracks.count() < 1: + return False + # Insert into title_combo_box + self.title_combo_box.clear() + for i in range(self.audio_cd_tracks.count()): + item = self.audio_cd_tracks.item_at_index(i) + item_title = item.get_meta(vlc.Meta.Title) + self.title_combo_box.addItem(item_title, i) + self.vlc_media_player.set_media(self.audio_cd_tracks.item_at_index(0)) + self.audio_cd = True + self.title_combo_box.setDisabled(False) + self.title_combo_box.setCurrentIndex(0) + self.on_title_combo_box_currentIndexChanged(0) + + return True @QtCore.pyqtSlot(bool) def on_load_disc_pushbutton_clicked(self, clicked): @@ -172,7 +206,7 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector): 'Given path does not exists')) self.toggle_disable_load_media(False) return - self.vlc_media = self.vlc_instance.media_new_path(path) + self.vlc_media = self.vlc_instance.media_new_location(path) if not self.vlc_media: log.debug('vlc media player is none') critical_error_message_box(message=translate('MediaPlugin.MediaClipSelectorForm', @@ -191,25 +225,28 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector): return self.vlc_media_player.audio_set_mute(True) if not self.media_state_wait(vlc.State.Playing): - critical_error_message_box(message=translate('MediaPlugin.MediaClipSelectorForm', - 'VLC player failed playing the media')) - self.toggle_disable_load_media(False) - return + # Tests if this is an audio CD + if not self.detect_audio_cd(path): + critical_error_message_box(message=translate('MediaPlugin.MediaClipSelectorForm', + 'VLC player failed playing the media')) + self.toggle_disable_load_media(False) + return self.vlc_media_player.pause() self.vlc_media_player.set_time(0) - # Get titles, insert in combobox - titles = self.vlc_media_player.video_get_title_description() - self.title_combo_box.clear() - for title in titles: - self.title_combo_box.addItem(title[1].decode(), title[0]) - # Main title is usually title #1 - if len(titles) > 1: - self.title_combo_box.setCurrentIndex(1) - else: - self.title_combo_box.setCurrentIndex(0) - # Enable audio track combobox if anything is in it - if len(titles) > 0: - self.title_combo_box.setDisabled(False) + if not self.audio_cd: + # Get titles, insert in combobox + titles = self.vlc_media_player.video_get_title_description() + self.title_combo_box.clear() + for title in titles: + self.title_combo_box.addItem(title[1].decode(), title[0]) + # Main title is usually title #1 + if len(titles) > 1: + self.title_combo_box.setCurrentIndex(1) + else: + self.title_combo_box.setCurrentIndex(0) + # Enable audio track combobox if anything is in it + if len(titles) > 0: + self.title_combo_box.setDisabled(False) self.toggle_disable_load_media(False) @QtCore.pyqtSlot(bool) @@ -321,35 +358,53 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector): log.debug('in on_title_combo_box_changed, index: %d', index) if not self.vlc_media_player: return - self.vlc_media_player.set_title(index) - self.vlc_media_player.set_time(0) - self.vlc_media_player.play() - self.vlc_media_player.audio_set_mute(True) - if not self.media_state_wait(vlc.State.Playing): - return - # pause - self.vlc_media_player.pause() - self.vlc_media_player.set_time(0) - # Get audio tracks, insert in combobox - audio_tracks = self.vlc_media_player.audio_get_track_description() - self.audio_tracks_combobox.clear() - for audio_track in audio_tracks: - self.audio_tracks_combobox.addItem(audio_track[1].decode(), audio_track[0]) - # Enable audio track combobox if anything is in it - if len(audio_tracks) > 0: - self.audio_tracks_combobox.setDisabled(False) - # First track is "deactivated", so set to next if it exists - if len(audio_tracks) > 1: - self.audio_tracks_combobox.setCurrentIndex(1) - # Get subtitle tracks, insert in combobox - subtitles_tracks = self.vlc_media_player.video_get_spu_description() - self.subtitle_tracks_combobox.clear() - for subtitle_track in subtitles_tracks: - self.subtitle_tracks_combobox.addItem(subtitle_track[1].decode(), subtitle_track[0]) - # Enable subtitle track combobox is anything in it - if len(subtitles_tracks) > 0: - self.subtitle_tracks_combobox.setDisabled(False) - self.vlc_media_player.audio_set_mute(False) + if self.audio_cd: + self.vlc_media = self.audio_cd_tracks.item_at_index(index) + self.vlc_media_player.set_media(self.vlc_media) + self.vlc_media_player.set_time(0) + self.vlc_media_player.play() + self.vlc_media_player.audio_set_mute(True) + if not self.media_state_wait(vlc.State.Playing): + return + # pause + self.vlc_media_player.pause() + self.vlc_media_player.set_time(0) + self.vlc_media_player.audio_set_mute(False) + self.toggle_disable_player(False) + else: + self.vlc_media_player.set_title(index) + self.vlc_media_player.set_time(0) + self.vlc_media_player.play() + self.vlc_media_player.audio_set_mute(True) + if not self.media_state_wait(vlc.State.Playing): + return + # pause + self.vlc_media_player.pause() + self.vlc_media_player.set_time(0) + # Get audio tracks, insert in combobox + audio_tracks = self.vlc_media_player.audio_get_track_description() + self.audio_tracks_combobox.clear() + for audio_track in audio_tracks: + self.audio_tracks_combobox.addItem(audio_track[1].decode(), audio_track[0]) + # Enable audio track combobox if anything is in it + if len(audio_tracks) > 0: + self.audio_tracks_combobox.setDisabled(False) + # First track is "deactivated", so set to next if it exists + if len(audio_tracks) > 1: + self.audio_tracks_combobox.setCurrentIndex(1) + # Get subtitle tracks, insert in combobox + subtitles_tracks = self.vlc_media_player.video_get_spu_description() + self.subtitle_tracks_combobox.clear() + for subtitle_track in subtitles_tracks: + self.subtitle_tracks_combobox.addItem(subtitle_track[1].decode(), subtitle_track[0]) + # Enable subtitle track combobox is anything in it + if len(subtitles_tracks) > 0: + self.subtitle_tracks_combobox.setDisabled(False) + self.vlc_media_player.audio_set_mute(False) + # If a title or audio track is available the player is enabled + if self.title_combo_box.count() > 0 or len(audio_tracks) > 0: + self.toggle_disable_player(False) + # Set media length info self.playback_length = self.vlc_media_player.get_length() self.position_horizontalslider.setMaximum(self.playback_length) # setup start and end time @@ -359,9 +414,6 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector): self.start_timeedit.setMaximumTime(playback_length_time) self.end_timeedit.setMaximumTime(playback_length_time) self.end_timeedit.setTime(playback_length_time) - # If a title or audio track is available the player is enabled - if self.title_combo_box.count() > 0 or len(audio_tracks) > 0: - self.toggle_disable_player(False) @QtCore.pyqtSlot(int) def on_audio_tracks_combobox_currentIndexChanged(self, index): @@ -465,11 +517,15 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector): end_time.second() * 1000 + \ end_time.msec() title = self.title_combo_box.itemData(self.title_combo_box.currentIndex()) - audio_track = self.audio_tracks_combobox.itemData(self.audio_tracks_combobox.currentIndex()) - subtitle_track = self.subtitle_tracks_combobox.itemData(self.subtitle_tracks_combobox.currentIndex()) path = self.media_path_combobox.currentText() - optical = 'optical:' + str(title) + ':' + str(audio_track) + ':' + str(subtitle_track) + ':' + str( - start_time_ms) + ':' + str(end_time_ms) + ':' + path + optical = '' + if self.audio_cd: + optical = 'optical:' + str(title) + ':-1:-1:' + str(start_time_ms) + ':' + str(end_time_ms) + ':' + path + else: + audio_track = self.audio_tracks_combobox.itemData(self.audio_tracks_combobox.currentIndex()) + subtitle_track = self.subtitle_tracks_combobox.itemData(self.subtitle_tracks_combobox.currentIndex()) + optical = 'optical:' + str(title) + ':' + str(audio_track) + ':' + str(subtitle_track) + ':' + str( + start_time_ms) + ':' + str(end_time_ms) + ':' + path self.media_item.add_optical_clip(optical) def media_state_wait(self, media_state): @@ -513,16 +569,34 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector): elif sys.platform.startswith('linux'): # Get disc devices from dbus and find the ones that are optical bus = dbus.SystemBus() - udev_manager_obj = bus.get_object('org.freedesktop.UDisks', '/org/freedesktop/UDisks') - udev_manager = dbus.Interface(udev_manager_obj, 'org.freedesktop.UDisks') - for dev in udev_manager.EnumerateDevices(): - device_obj = bus.get_object("org.freedesktop.UDisks", dev) - device_props = dbus.Interface(device_obj, dbus.PROPERTIES_IFACE) - if device_props.Get('org.freedesktop.UDisks.Device', 'DeviceIsDrive'): - drive_props = device_props.Get('org.freedesktop.UDisks.Device', 'DriveMediaCompatibility') - if any('optical' in prop for prop in drive_props): - self.media_path_combobox.addItem(device_props.Get('org.freedesktop.UDisks.Device', - 'DeviceFile')) + try: + udev_manager_obj = bus.get_object('org.freedesktop.UDisks', '/org/freedesktop/UDisks') + udev_manager = dbus.Interface(udev_manager_obj, 'org.freedesktop.UDisks') + for dev in udev_manager.EnumerateDevices(): + device_obj = bus.get_object("org.freedesktop.UDisks", dev) + device_props = dbus.Interface(device_obj, dbus.PROPERTIES_IFACE) + if device_props.Get('org.freedesktop.UDisks.Device', 'DeviceIsDrive'): + drive_props = device_props.Get('org.freedesktop.UDisks.Device', 'DriveMediaCompatibility') + if any('optical' in prop for prop in drive_props): + self.media_path_combobox.addItem(device_props.Get('org.freedesktop.UDisks.Device', + 'DeviceFile')) + return + except dbus.exceptions.DBusException: + log.debug('could not use udisks, will try udisks2') + udev_manager_obj = bus.get_object('org.freedesktop.UDisks2', '/org/freedesktop/UDisks2') + udev_manager = dbus.Interface(udev_manager_obj, 'org.freedesktop.DBus.ObjectManager') + for k,v in udev_manager.GetManagedObjects().items(): + drive_info = v.get('org.freedesktop.UDisks2.Drive', {}) + drive_props = drive_info.get('MediaCompatibility') + if drive_props and any('optical' in prop for prop in drive_props): + for device in udev_manager.GetManagedObjects().values(): + if dbus.String('org.freedesktop.UDisks2.Block') in device: + if device[dbus.String('org.freedesktop.UDisks2.Block')][dbus.String('Drive')] == k: + block_file = '' + for c in device[dbus.String('org.freedesktop.UDisks2.Block')][dbus.String('PreferredDevice')]: + if chr(c) != '\x00': + block_file += chr(c) + self.media_path_combobox.addItem(block_file) elif sys.platform.startswith('darwin'): # Look for DVD folders in devices to find optical devices volumes = os.listdir('/Volumes') diff --git a/openlp/plugins/media/lib/mediaitem.py b/openlp/plugins/media/lib/mediaitem.py index 626ef36c9..ca8690d75 100644 --- a/openlp/plugins/media/lib/mediaitem.py +++ b/openlp/plugins/media/lib/mediaitem.py @@ -428,6 +428,6 @@ class MediaMediaItem(MediaManagerItem, RegistryProperties): :return: Time string in format: hh.mm.ss,ttt """ seconds, millis = divmod(milliseconds, 1000) - minutes, seconds = divmod(millis, 60) + minutes, seconds = divmod(seconds, 60) hours, minutes = divmod(minutes, 60) return "%02d:%02d:%02d,%03d" % (hours, minutes, seconds, millis)