def test_parse_optical_path_win(self): """ Test that test_parse_optical_path() parses a optical path with windows device path correctly """ # GIVEN: An optical formatted path org_title_track = 1 org_audio_track = 2 org_subtitle_track = -1 org_start = 1234 org_end = 4321 org_name = 'test name' org_device_path = 'D:' path = 'optical:%d:%d:%d:%d:%d:%s:%s' % (org_title_track, org_audio_track, org_subtitle_track, org_start, org_end, org_name, org_device_path) # WHEN: parsing the path (device_path, title_track, audio_track, subtitle_track, start, end, name) = parse_optical_path(path) # THEN: The return values should match the original values self.assertEqual(org_title_track, title_track, 'Returned title_track should match the original') self.assertEqual(org_audio_track, audio_track, 'Returned audio_track should match the original') self.assertEqual(org_subtitle_track, subtitle_track, 'Returned subtitle_track should match the original') self.assertEqual(org_start, start, 'Returned start should match the original') self.assertEqual(org_end, end, 'Returned end should match the original') self.assertEqual(org_name, name, 'Returned end should match the original') self.assertEqual(org_device_path, device_path, 'Returned device_path should match the original')
def generate_slide_data(self, service_item, item=None, xml_version=False, remote=False, context=ServiceItemContext.Service): """ Generate the slide data. Needs to be implemented by the plugin. :param service_item: The service item to be built on :param item: The Song item to be used :param xml_version: The xml version (not used) :param remote: Triggered from remote :param context: Why is it being generated """ if item is None: item = self.list_view.currentItem() if item is None: return False filename = item.data(QtCore.Qt.UserRole) # Special handling if the filename is a optical clip if filename.startswith('optical:'): (name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(filename) if not os.path.exists(name): if not remote: # Optical disc is no longer present critical_error_message_box( translate('MediaPlugin.MediaItem', 'Missing Media File'), translate('MediaPlugin.MediaItem', 'The optical disc %s is no longer available.') % name) return False service_item.processor = self.display_type_combo_box.currentText() service_item.add_from_command(filename, name, CLAPPERBOARD) service_item.title = clip_name # Set the length self.media_controller.media_setup_optical(name, title, audio_track, subtitle_track, start, end, None, None) service_item.set_media_length((end - start) / 1000) service_item.start_time = start / 1000 service_item.end_time = end / 1000 service_item.add_capability(ItemCapabilities.IsOptical) else: if not os.path.exists(filename): if not remote: # File is no longer present critical_error_message_box( translate('MediaPlugin.MediaItem', 'Missing Media File'), translate('MediaPlugin.MediaItem', 'The file %s no longer exists.') % filename) return False (path, name) = os.path.split(filename) service_item.title = name service_item.processor = self.display_type_combo_box.currentText() service_item.add_from_command(path, name, CLAPPERBOARD) # Only get start and end times if going to a service if context == ServiceItemContext.Service: # Start media and obtain the length if not self.media_controller.media_length(service_item): return False service_item.add_capability(ItemCapabilities.CanAutoStartForLive) service_item.add_capability(ItemCapabilities.CanEditTitle) service_item.add_capability(ItemCapabilities.RequiresMedia) if Settings().value(self.settings_section + '/media auto start') == QtCore.Qt.Checked: service_item.will_auto_start = True # force a non-existent theme service_item.theme = -1 return True
def test_parse_optical_path_linux(self): """ Test that test_parse_optical_path() parses a optical path with linux device path correctly """ # GIVEN: An optical formatted path org_title_track = 1 org_audio_track = 2 org_subtitle_track = -1 org_start = 1234 org_end = 4321 org_name = 'test name' org_device_path = '/dev/dvd' path = 'optical:%d:%d:%d:%d:%d:%s:%s' % ( org_title_track, org_audio_track, org_subtitle_track, org_start, org_end, org_name, org_device_path) # WHEN: parsing the path (device_path, title_track, audio_track, subtitle_track, start, end, name) = parse_optical_path(path) # THEN: The return values should match the original values assert org_title_track == title_track, 'Returned title_track should match the original' assert org_audio_track == audio_track, 'Returned audio_track should match the original' assert org_subtitle_track == subtitle_track, 'Returned subtitle_track should match the original' assert org_start == start, 'Returned start should match the original' assert org_end == end, 'Returned end should match the original' assert org_name == name, 'Returned end should match the original' assert org_device_path == device_path, 'Returned device_path should match the original'
def load_list(self, media, target_group=None): """ Load the media list :param media: The media :param target_group: """ media.sort(key=lambda file_name: get_natural_key( os.path.split(str(file_name))[1])) for track in media: track_info = QtCore.QFileInfo(track) item_name = None if track.startswith('optical:'): # Handle optical based item (file_name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(track) item_name = QtWidgets.QListWidgetItem(clip_name) item_name.setIcon(UiIcons().optical) item_name.setData(QtCore.Qt.UserRole, track) item_name.setToolTip('{name}@{start}-{end}'.format( name=file_name, start=format_milliseconds(start), end=format_milliseconds(end))) elif not os.path.exists(track): # File doesn't exist, mark as error. file_name = os.path.split(str(track))[1] item_name = QtWidgets.QListWidgetItem(file_name) item_name.setIcon(UiIcons().error) item_name.setData(QtCore.Qt.UserRole, track) item_name.setToolTip(track) elif track_info.isFile(): # Normal media file handling. file_name = os.path.split(str(track))[1] item_name = QtWidgets.QListWidgetItem(file_name) search = file_name.split('.')[-1].lower() if '*.{text}'.format( text=search ) in self.media_controller.audio_extensions_list: item_name.setIcon(UiIcons().audio) else: item_name.setIcon(UiIcons().video) item_name.setData(QtCore.Qt.UserRole, track) item_name.setToolTip(track) if item_name: self.list_view.addItem(item_name)
def load_list(self, media, target_group=None): """ Load the media list :param media: The media :param target_group: """ media.sort(key=lambda file_name: get_locale_key( os.path.split(str(file_name))[1])) for track in media: track_info = QtCore.QFileInfo(track) item_name = None if track.startswith('optical:'): # Handle optical based item (file_name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(track) item_name = QtGui.QListWidgetItem(clip_name) item_name.setIcon(OPTICAL_ICON) item_name.setData(QtCore.Qt.UserRole, track) item_name.setToolTip('%s@%s-%s' % (file_name, format_milliseconds(start), format_milliseconds(end))) elif not os.path.exists(track): # File doesn't exist, mark as error. file_name = os.path.split(str(track))[1] item_name = QtGui.QListWidgetItem(file_name) item_name.setIcon(ERROR_ICON) item_name.setData(QtCore.Qt.UserRole, track) item_name.setToolTip(track) elif track_info.isFile(): # Normal media file handling. file_name = os.path.split(str(track))[1] item_name = QtGui.QListWidgetItem(file_name) if '*.%s' % (file_name.split('.')[-1].lower() ) in self.media_controller.audio_extensions_list: item_name.setIcon(AUDIO_ICON) else: item_name.setIcon(VIDEO_ICON) item_name.setData(QtCore.Qt.UserRole, track) item_name.setToolTip(track) if item_name: self.list_view.addItem(item_name)
def generate_slide_data(self, service_item, item=None, xml_version=False, remote=False, context=ServiceItemContext.Service): """ Generate the slide data. Needs to be implemented by the plugin. :param service_item: The service item to be built on :param item: The Song item to be used :param xml_version: The xml version (not used) :param remote: Triggered from remote :param context: Why is it being generated """ if item is None: item = self.list_view.currentItem() if item is None: return False filename = item.data(QtCore.Qt.UserRole) # Special handling if the filename is a optical clip if filename.startswith('optical:'): (name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(filename) if not os.path.exists(name): if not remote: # Optical disc is no longer present critical_error_message_box( translate('MediaPlugin.MediaItem', 'Missing Media File'), translate( 'MediaPlugin.MediaItem', 'The optical disc {name} is no longer available.'). format(name=name)) return False service_item.processor = self.display_type_combo_box.currentText() service_item.add_from_command(filename, name, CLAPPERBOARD) service_item.title = clip_name # Set the length service_item.set_media_length(end - start) service_item.start_time = start service_item.end_time = end service_item.add_capability(ItemCapabilities.IsOptical) else: if not os.path.exists(filename): if not remote: # File is no longer present critical_error_message_box( translate('MediaPlugin.MediaItem', 'Missing Media File'), translate('MediaPlugin.MediaItem', 'The file {name} no longer exists.').format( name=filename)) return False (path, name) = os.path.split(filename) service_item.title = name service_item.processor = self.display_type_combo_box.currentText() service_item.add_from_command(path, name, CLAPPERBOARD) # Only get start and end times if going to a service if not self.media_controller.media_length(service_item): return False service_item.add_capability(ItemCapabilities.CanAutoStartForLive) service_item.add_capability(ItemCapabilities.CanEditTitle) service_item.add_capability(ItemCapabilities.RequiresMedia) if Settings().value(self.settings_section + '/media auto start') == QtCore.Qt.Checked: service_item.will_auto_start = True # force a non-existent theme service_item.theme = -1 return True
def video(self, source, service_item, hidden=False, video_behind_text=False): """ Loads and starts a video to run with the option of sound :param source: Where the call originated form :param service_item: The player which is doing the playing :param hidden: The player which is doing the playing :param video_behind_text: Is the video to be played behind text. """ is_valid = False controller = self.display_controllers[source] # stop running videos self.media_reset(controller) controller.media_info = MediaInfo() controller.media_info.volume = controller.volume_slider.value() controller.media_info.is_background = video_behind_text # background will always loop video. controller.media_info.can_loop_playback = video_behind_text controller.media_info.file_info = QtCore.QFileInfo( service_item.get_frame_path()) display = self._define_display(controller) if controller.is_live: # if this is an optical device use special handling if service_item.is_capable(ItemCapabilities.IsOptical): log.debug('video is optical and live') path = service_item.get_frame_path() (name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(path) is_valid = self.media_setup_optical(name, title, audio_track, subtitle_track, start, end, display, controller) else: log.debug('video is not optical and live') controller.media_info.length = service_item.media_length is_valid = self._check_file_type(controller, display, service_item) display.override['theme'] = '' display.override['video'] = True if controller.media_info.is_background: # ignore start/end time controller.media_info.start_time = 0 controller.media_info.end_time = 0 else: controller.media_info.start_time = service_item.start_time controller.media_info.end_time = service_item.end_time elif controller.preview_display: if service_item.is_capable(ItemCapabilities.IsOptical): log.debug('video is optical and preview') path = service_item.get_frame_path() (name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(path) is_valid = self.media_setup_optical(name, title, audio_track, subtitle_track, start, end, display, controller) else: log.debug('video is not optical and preview') controller.media_info.length = service_item.media_length is_valid = self._check_file_type(controller, display, service_item) if not is_valid: # Media could not be loaded correctly critical_error_message_box( translate('MediaPlugin.MediaItem', 'Unsupported File'), translate('MediaPlugin.MediaItem', 'Unsupported File')) return False log.debug('video mediatype: ' + str(controller.media_info.media_type)) # dont care about actual theme, set a black background if controller.is_live and not controller.media_info.is_background: display.frame.evaluateJavaScript( 'show_video("setBackBoard", null, null,"visible");') # now start playing - Preview is autoplay! autoplay = False # Preview requested if not controller.is_live: autoplay = True # Visible or background requested or Service Item wants to autostart elif not hidden or controller.media_info.is_background or service_item.will_auto_start: autoplay = True # Unblank on load set elif Settings().value('core/auto unblank'): autoplay = True if autoplay: if not self.media_play(controller): critical_error_message_box( translate('MediaPlugin.MediaItem', 'Unsupported File'), translate('MediaPlugin.MediaItem', 'Unsupported File')) return False self.set_controls_visible(controller, True) log.debug( 'use %s controller' % self.current_media_players[controller.controller_type].display_name ) return True
def load_list(self, media, target_group=None): """ Load the media list :param media: The media :param target_group: """ media.sort(key=lambda file_name: get_locale_key(os.path.split(str(file_name))[1])) for track in media: track_info = QtCore.QFileInfo(track) item_name = None if track.startswith('optical:'): # Handle optical based item (file_name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(track) item_name = QtGui.QListWidgetItem(clip_name) item_name.setIcon(OPTICAL_ICON) item_name.setData(QtCore.Qt.UserRole, track) item_name.setToolTip('%s@%s-%s' % (file_name, format_milliseconds(start), format_milliseconds(end))) elif not os.path.exists(track): # File doesn't exist, mark as error. file_name = os.path.split(str(track))[1] item_name = QtGui.QListWidgetItem(file_name) item_name.setIcon(ERROR_ICON) item_name.setData(QtCore.Qt.UserRole, track) item_name.setToolTip(track) elif track_info.isFile(): # Normal media file handling. file_name = os.path.split(str(track))[1] item_name = QtGui.QListWidgetItem(file_name) if '*.%s' % (file_name.split('.')[-1].lower()) in self.media_controller.audio_extensions_list: item_name.setIcon(AUDIO_ICON) else: item_name.setIcon(VIDEO_ICON) item_name.setData(QtCore.Qt.UserRole, track) item_name.setToolTip(track) if item_name: self.list_view.addItem(item_name)
def video(self, source, service_item, hidden=False, video_behind_text=False): """ Loads and starts a video to run with the option of sound :param source: Where the call originated form :param service_item: The player which is doing the playing :param hidden: The player which is doing the playing :param video_behind_text: Is the video to be played behind text. """ log.debug('video') is_valid = False controller = self.display_controllers[source] # stop running videos self.media_reset(controller) controller.media_info = MediaInfo() controller.media_info.volume = controller.volume_slider.value() controller.media_info.is_background = video_behind_text controller.media_info.file_info = QtCore.QFileInfo(service_item.get_frame_path()) display = self._define_display(controller) if controller.is_live: # if this is an optical device use special handling if service_item.is_capable(ItemCapabilities.IsOptical): log.debug('video is optical and live') path = service_item.get_frame_path() (name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(path) is_valid = self.media_setup_optical(name, title, audio_track, subtitle_track, start, end, display, controller) else: log.debug('video is not optical and live') is_valid = self._check_file_type(controller, display, service_item) display.override['theme'] = '' display.override['video'] = True if controller.media_info.is_background: # ignore start/end time controller.media_info.start_time = 0 controller.media_info.end_time = 0 else: controller.media_info.start_time = service_item.start_time controller.media_info.end_time = service_item.end_time elif controller.preview_display: if service_item.is_capable(ItemCapabilities.IsOptical): log.debug('video is optical and preview') path = service_item.get_frame_path() (name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(path) is_valid = self.media_setup_optical(name, title, audio_track, subtitle_track, start, end, display, controller) else: log.debug('video is not optical and preview') is_valid = self._check_file_type(controller, display, service_item) if not is_valid: # Media could not be loaded correctly critical_error_message_box(translate('MediaPlugin.MediaItem', 'Unsupported File'), translate('MediaPlugin.MediaItem', 'Unsupported File')) return False log.debug('video mediatype: ' + str(controller.media_info.media_type)) # dont care about actual theme, set a black background if controller.is_live and not controller.media_info.is_background: display.frame.evaluateJavaScript('show_video( "setBackBoard", null, null, null,"visible");') # now start playing - Preview is autoplay! autoplay = False # Preview requested if not controller.is_live: autoplay = True # Visible or background requested or Service Item wants to autostart elif not hidden or controller.media_info.is_background or service_item.will_auto_start: autoplay = True # Unblank on load set elif Settings().value('core/auto unblank'): autoplay = True if autoplay: if not self.media_play(controller): critical_error_message_box(translate('MediaPlugin.MediaItem', 'Unsupported File'), translate('MediaPlugin.MediaItem', 'Unsupported File')) return False self.set_controls_visible(controller, True) log.debug('use %s controller' % self.current_media_players[controller.controller_type]) return True
def load_list(self, media, target_group=None): """ Load the media list :param media: The media :param target_group: """ media.sort(key=lambda file_path: get_natural_key(os.path.split(str(file_path))[1])) file_name = translate('MediaPlugin.MediaItem', 'Live Stream') item_name = QtWidgets.QListWidgetItem(file_name) item_name.setIcon(UiIcons().video) item_name.setData(QtCore.Qt.UserRole, UiStrings().LiveStream) item_name.setToolTip(translate('MediaPlugin.MediaItem', 'Show Live Stream')) self.list_view.addItem(item_name) for track in media: track_str = str(track) track_info = QtCore.QFileInfo(track_str) item_name = None # Dont add the live stream in when reloading the UI. if track_str == UiStrings().LiveStream: continue elif track_str.startswith('optical:'): # Handle optical based item (file_name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(track_str) item_name = QtWidgets.QListWidgetItem(clip_name) item_name.setIcon(UiIcons().optical) item_name.setData(QtCore.Qt.UserRole, track) item_name.setToolTip('{name}@{start}-{end}'.format(name=file_name, start=format_milliseconds(start), end=format_milliseconds(end))) elif not os.path.exists(track): # File doesn't exist, mark as error. file_name = os.path.split(track_str)[1] item_name = QtWidgets.QListWidgetItem(file_name) item_name.setIcon(UiIcons().error) item_name.setData(QtCore.Qt.UserRole, track) item_name.setToolTip(track_str) elif track_info.isFile(): # Normal media file handling. file_name = os.path.split(track_str)[1] item_name = QtWidgets.QListWidgetItem(file_name) search = file_name.split('.')[-1].lower() if search in AUDIO_EXT: item_name.setIcon(UiIcons().audio) else: item_name.setIcon(UiIcons().video) item_name.setData(QtCore.Qt.UserRole, track) item_name.setToolTip(track_str) if item_name: self.list_view.addItem(item_name)
def load_video(self, source, service_item, hidden=False): """ Loads and starts a video to run and sets the stored sound value. :param source: Where the call originated form :param service_item: The player which is doing the playing :param hidden: The player which is doing the playing """ is_valid = True controller = self.display_controllers(source) # stop running videos self.media_reset(controller) controller.media_info = ItemMediaInfo() if controller.is_live: controller.media_info.volume = self.settings.value( 'media/live volume') else: controller.media_info.volume = self.settings.value( 'media/preview volume') # background will always loop video. if service_item.is_capable(ItemCapabilities.HasBackgroundAudio): controller.media_info.file_info = service_item.background_audio else: if service_item.is_capable(ItemCapabilities.HasBackgroundVideo): controller.media_info.file_info = [ service_item.video_file_name ] service_item.media_length = self.media_length( path_to_str(service_item.video_file_name)) controller.media_info.is_looping_playback = True controller.media_info.is_background = True elif service_item.is_capable(ItemCapabilities.CanStream): controller.media_info.file_info = [] controller.media_info.is_background = True else: controller.media_info.file_info = [ service_item.get_frame_path() ] display = self._define_display(controller) if controller.is_live: # if this is an optical device use special handling if service_item.is_capable(ItemCapabilities.CanStream): is_valid = self._check_file_type(controller, display, True) controller.media_info.media_type = MediaType.Stream elif service_item.is_capable(ItemCapabilities.IsOptical): log.debug('video is optical and live') path = service_item.get_frame_path() (name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(path) is_valid = self.media_setup_optical(name, title, audio_track, subtitle_track, start, end, display, controller) else: log.debug('video is not optical and live') controller.media_info.length = service_item.media_length is_valid = self._check_file_type(controller, display) controller.media_info.start_time = service_item.start_time controller.media_info.end_time = service_item.end_time elif controller.preview_display: if service_item.is_capable(ItemCapabilities.CanStream): controller.media_info.media_type = MediaType.Stream is_valid = self._check_file_type(controller, display, True) elif service_item.is_capable(ItemCapabilities.IsOptical): log.debug('video is optical and preview') path = service_item.get_frame_path() (name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(path) is_valid = self.media_setup_optical(name, title, audio_track, subtitle_track, start, end, display, controller) else: log.debug('video is not optical and preview') controller.media_info.length = service_item.media_length is_valid = self._check_file_type(controller, display) if not is_valid: # Media could not be loaded correctly critical_error_message_box( translate('MediaPlugin.MediaItem', 'Unsupported File'), translate('MediaPlugin.MediaItem', 'Unsupported File')) return False log.debug('video media type: {tpe} '.format( tpe=str(controller.media_info.media_type))) autoplay = False if service_item.requires_media(): autoplay = True # Preview requested if not controller.is_live: autoplay = True # Visible or background requested or Service Item wants to autostart elif not hidden or service_item.will_auto_start: autoplay = True # Unblank on load set elif self.settings.value('core/auto unblank'): autoplay = True if autoplay: if not self.media_play(controller): critical_error_message_box( translate('MediaPlugin.MediaItem', 'Unsupported File'), translate('MediaPlugin.MediaItem', 'Unsupported File')) return False self.set_controls_visible(controller, True) log.debug('use {nm} controller'.format(nm=self.current_media_players[ controller.controller_type].display_name)) return True
def load_list(self, media, target_group=None): """ Load the media list :param media: The media :param target_group: """ media.sort(key=lambda file_name: get_locale_key(os.path.split(str(file_name))[1])) for track in media: track_info = QtCore.QFileInfo(track) item_name = None if track.startswith('optical:'): # Handle optical based item (file_name, title, audio_track, subtitle_track, start, end, clip_name) = parse_optical_path(track) item_name = QtWidgets.QListWidgetItem(clip_name) item_name.setIcon(self.optical_icon) item_name.setData(QtCore.Qt.UserRole, track) item_name.setToolTip('{name}@{start}-{end}'.format(name=file_name, start=format_milliseconds(start), end=format_milliseconds(end))) elif not os.path.exists(track): # File doesn't exist, mark as error. file_name = os.path.split(str(track))[1] item_name = QtWidgets.QListWidgetItem(file_name) item_name.setIcon(self.error_icon) item_name.setData(QtCore.Qt.UserRole, track) item_name.setToolTip(track) elif track_info.isFile(): # Normal media file handling. file_name = os.path.split(str(track))[1] item_name = QtWidgets.QListWidgetItem(file_name) search = file_name.split('.')[-1].lower() if '*.{text}'.format(text=search) in self.media_controller.audio_extensions_list: item_name.setIcon(self.audio_icon) else: item_name.setIcon(self.video_icon) item_name.setData(QtCore.Qt.UserRole, track) item_name.setToolTip(track) if item_name: self.list_view.addItem(item_name)