Fixes for DVD

bzr-revno: 2421
This commit is contained in:
Tomas Groth 2014-09-17 21:43:53 +01:00 committed by Tim Bentley
commit 5dceb1a0e6
4 changed files with 136 additions and 30 deletions

View File

@ -28,31 +28,29 @@
###############################################################################
import os
if os.name == 'nt':
from win32com.client import Dispatch
import string
import sys
if sys.platform.startswith('linux'):
import dbus
import logging
import re
from time import sleep
from datetime import datetime
from PyQt4 import QtCore, QtGui
from openlp.core.common import translate
from openlp.core.common import translate, is_win, is_linux, is_macosx, RegistryProperties
from openlp.plugins.media.forms.mediaclipselectordialog import Ui_MediaClipSelector
from openlp.core.lib.ui import critical_error_message_box
from openlp.core.ui.media import format_milliseconds
if is_win():
from win32com.client import Dispatch
if is_linux():
import dbus
try:
from openlp.core.ui.media.vendor import vlc
except (ImportError, NameError, NotImplementedError):
pass
except OSError as e:
if sys.platform.startswith('win'):
if is_win():
if not isinstance(e, WindowsError) and e.winerror != 126:
raise
else:
@ -61,7 +59,7 @@ except OSError as e:
log = logging.getLogger(__name__)
class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector, RegistryProperties):
"""
Class to manage the clip selection
"""
@ -144,9 +142,9 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
# You have to give the id of the QFrame (or similar object)
# to vlc, different platforms have different functions for this.
win_id = int(self.preview_frame.winId())
if sys.platform == "win32":
if is_win():
self.vlc_media_player.set_hwnd(win_id)
elif sys.platform == "darwin":
elif is_macosx():
# We have to use 'set_nsobject' since Qt4 on OSX uses Cocoa
# framework and not the old Carbon.
self.vlc_media_player.set_nsobject(win_id)
@ -190,7 +188,7 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
self.audio_cd = True
self.titles_combo_box.setDisabled(False)
self.titles_combo_box.setCurrentIndex(0)
self.on_title_combo_box_currentIndexChanged(0)
self.on_titles_combo_box_currentIndexChanged(0)
return True
@ -203,18 +201,21 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
"""
log.debug('on_load_disc_button_clicked')
self.disable_all()
self.application.set_busy_cursor()
path = self.media_path_combobox.currentText()
# Check if given path is non-empty and exists before starting VLC
if not path:
log.debug('no given path')
critical_error_message_box(message=translate('MediaPlugin.MediaClipSelectorForm', 'No path was given'))
self.toggle_disable_load_media(False)
self.application.set_normal_cursor()
return
if not os.path.exists(path):
log.debug('Given path does not exists')
critical_error_message_box(message=translate('MediaPlugin.MediaClipSelectorForm',
'Given path does not exists'))
self.toggle_disable_load_media(False)
self.application.set_normal_cursor()
return
# VLC behaves a bit differently on windows and linux when loading, which creates problems when trying to
# detect if we're dealing with a DVD or CD, so we use different loading approaches depending on the OS.
@ -231,6 +232,7 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
critical_error_message_box(message=translate('MediaPlugin.MediaClipSelectorForm',
'An error happened during initialization of VLC player'))
self.toggle_disable_load_media(False)
self.application.set_normal_cursor()
return
# put the media in the media player
self.vlc_media_player.set_media(self.vlc_media)
@ -241,6 +243,8 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
critical_error_message_box(message=translate('MediaPlugin.MediaClipSelectorForm',
'VLC player failed playing the media'))
self.toggle_disable_load_media(False)
self.application.set_normal_cursor()
self.vlc_media_player.audio_set_mute(False)
return
self.vlc_media_player.audio_set_mute(True)
if not self.media_state_wait(vlc.State.Playing):
@ -249,23 +253,32 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
critical_error_message_box(message=translate('MediaPlugin.MediaClipSelectorForm',
'VLC player failed playing the media'))
self.toggle_disable_load_media(False)
self.application.set_normal_cursor()
self.vlc_media_player.audio_set_mute(False)
return
self.vlc_media_player.audio_set_mute(True)
# pause
self.vlc_media_player.set_time(0)
self.vlc_media_player.set_pause(1)
self.media_state_wait(vlc.State.Paused)
self.toggle_disable_load_media(False)
self.application.set_normal_cursor()
self.vlc_media_player.audio_set_mute(False)
if not self.audio_cd:
# Temporarily disable signals
self.blockSignals(True)
# Get titles, insert in combobox
titles = self.vlc_media_player.video_get_title_description()
self.titles_combo_box.clear()
for title in titles:
self.titles_combo_box.addItem(title[1].decode(), title[0])
# Re-enable signals
self.blockSignals(False)
# Main title is usually title #1
if len(titles) > 1:
self.titles_combo_box.setCurrentIndex(1)
else:
self.titles_combo_box.setCurrentIndex(0)
# Enable audio track combobox if anything is in it
if len(titles) > 0:
self.titles_combo_box.setDisabled(False)
self.toggle_disable_load_media(False)
log.debug('load_disc_button end - vlc_media_player state: %s' % self.vlc_media_player.get_state())
@QtCore.pyqtSlot(bool)
@ -378,6 +391,7 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
if not self.vlc_media_player:
log.error('vlc_media_player was None')
return
self.application.set_busy_cursor()
if self.audio_cd:
self.vlc_media = self.audio_cd_tracks.item_at_index(index)
self.vlc_media_player.set_media(self.vlc_media)
@ -385,14 +399,14 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
self.vlc_media_player.play()
if not self.media_state_wait(vlc.State.Playing):
log.error('Could not start playing audio cd, needed to get track info')
self.application.set_normal_cursor()
return
self.vlc_media_player.audio_set_mute(True)
# Sleep 1 second to make sure VLC has the needed metadata
sleep(1)
# pause
self.vlc_media_player.set_time(0)
self.vlc_media_player.set_pause(1)
self.vlc_media_player.audio_set_mute(False)
self.application.set_normal_cursor()
self.toggle_disable_player(False)
else:
self.vlc_media_player.set_title(index)
@ -400,13 +414,13 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
self.vlc_media_player.play()
if not self.media_state_wait(vlc.State.Playing):
log.error('Could not start playing dvd, needed to get track info')
self.application.set_normal_cursor()
return
self.vlc_media_player.audio_set_mute(True)
# Sleep 1 second to make sure VLC has the needed metadata
sleep(1)
self.vlc_media_player.set_time(0)
# Get audio tracks, insert in combobox
# Get audio tracks
audio_tracks = self.vlc_media_player.audio_get_track_description()
log.debug('number of audio tracks: %d' % len(audio_tracks))
# Clear the audio track combobox, insert new tracks
self.audio_tracks_combobox.clear()
for audio_track in audio_tracks:
self.audio_tracks_combobox.addItem(audio_track[1].decode(), audio_track[0])
@ -447,6 +461,7 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
self.vlc_media_player.set_pause(1)
loop_count += 1
log.debug('titles_combo_box end - vlc_media_player state: %s' % self.vlc_media_player.get_state())
self.application.set_normal_cursor()
@QtCore.pyqtSlot(int)
def on_audio_tracks_combobox_currentIndexChanged(self, index):
@ -535,7 +550,7 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
"""
Saves the current media and trackinfo as a clip to the mediamanager
"""
log.debug('in on_save_button_clicked')
log.debug('in MediaClipSelectorForm.accept')
start_time = self.start_position_edit.time()
start_time_ms = start_time.hour() * 60 * 60 * 1000 + \
start_time.minute() * 60 * 1000 + \
@ -550,10 +565,23 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
path = self.media_path_combobox.currentText()
optical = ''
if self.audio_cd:
# Check for load problems
if start_time_ms is None or end_time_ms is None or title is None:
critical_error_message_box(translate('MediaPlugin.MediaClipSelectorForm', 'CD not loaded correctly'),
translate('MediaPlugin.MediaClipSelectorForm',
'The CD was not loaded correctly, please re-load and try again.'))
return
optical = 'optical:%d:-1:-1:%d:%d:' % (title, start_time_ms, end_time_ms)
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())
# Check for load problems
if start_time_ms is None or end_time_ms is None or title is None or audio_track is None\
or subtitle_track is None:
critical_error_message_box(translate('MediaPlugin.MediaClipSelectorForm', 'DVD not loaded correctly'),
translate('MediaPlugin.MediaClipSelectorForm',
'The DVD was not loaded correctly, please re-load and try again.'))
return
optical = 'optical:%d:%d:%d:%d:%d:' % (title, audio_track, subtitle_track, start_time_ms, end_time_ms)
# Ask for an alternative name for the mediaclip
while True:
@ -595,7 +623,7 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
while media_state != self.vlc_media_player.get_state():
if self.vlc_media_player.get_state() == vlc.State.Error:
return False
if (datetime.now() - start).seconds > 30:
if (datetime.now() - start).seconds > 15:
return False
return True
@ -606,7 +634,7 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
"""
# Clear list first
self.media_path_combobox.clear()
if os.name == 'nt':
if is_win():
# use win api to find optical drives
fso = Dispatch('scripting.filesystemobject')
for drive in fso.Drives:
@ -614,7 +642,7 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
# if type is 4, it is a cd-rom drive
if drive.DriveType == 4:
self.media_path_combobox.addItem('%s:\\' % drive.DriveLetter)
elif sys.platform.startswith('linux'):
elif is_linux():
# Get disc devices from dbus and find the ones that are optical
bus = dbus.SystemBus()
try:
@ -646,7 +674,7 @@ class MediaClipSelectorForm(QtGui.QDialog, Ui_MediaClipSelector):
if chr(c) != '\x00':
block_file += chr(c)
self.media_path_combobox.addItem(block_file)
elif sys.platform.startswith('darwin'):
elif is_macosx():
# Look for DVD folders in devices to find optical devices
volumes = os.listdir('/Volumes')
candidates = list()

View File

@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2014 Raoul Snyman #
# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################

View File

@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=120 tabstop=4 softtabstop=4
###############################################################################
# OpenLP - Open Source Lyrics Projection #
# --------------------------------------------------------------------------- #
# Copyright (c) 2008-2014 Raoul Snyman #
# Portions copyright (c) 2008-2014 Tim Bentley, Gerald Britton, Jonathan #
# Corwin, Samuel Findlay, Michael Gorven, Scott Guerrieri, Matthias Hub, #
# Meinert Jordan, Armin Köhler, Erik Lundin, Edwin Lunando, Brian T. Meyer. #
# Joshua Miller, Stevan Pettit, Andreas Preikschat, Mattias Põldaru, #
# Christian Richter, Philip Ridout, Simon Scudder, Jeffrey Smith, #
# Maikel Stuivenberg, Martin Thompson, Jon Tibble, Dave Warnock, #
# Frode Woldsund, Martin Zibricky, Patrick Zimmermann #
# --------------------------------------------------------------------------- #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the Free #
# Software Foundation; version 2 of the License. #
# #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or #
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for #
# more details. #
# #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., 59 #
# Temple Place, Suite 330, Boston, MA 02111-1307 USA #
###############################################################################

View File

@ -60,6 +60,7 @@ class TestMediaClipSelectorForm(TestCase, TestMixin):
# Mock VLC so we don't actually use it
self.vlc_patcher = patch('openlp.plugins.media.forms.mediaclipselectorform.vlc')
self.vlc_patcher.start()
Registry().register('application', self.app)
# Mock the media item
self.mock_media_item = MagicMock()
# create form to test
@ -67,6 +68,9 @@ class TestMediaClipSelectorForm(TestCase, TestMixin):
mock_media_state_wait = MagicMock()
mock_media_state_wait.return_value = True
self.form.media_state_wait = mock_media_state_wait
self.form.application.set_busy_cursor = MagicMock()
self.form.application.set_normal_cursor = MagicMock()
self.form.find_optical_devices = MagicMock()
def tearDown(self):
"""
@ -155,3 +159,21 @@ class TestMediaClipSelectorForm(TestCase, TestMixin):
self.form.audio_tracks_combobox.itemData.assert_any_call(0)
self.form.audio_tracks_combobox.itemData.assert_any_call(1)
self.form.subtitle_tracks_combobox.itemData.assert_any_call(0)
def click_save_button_test(self):
"""
Test that the correct function is called when save is clicked, and that it behaves as expected.
"""
# GIVEN: Mocked methods.
with patch('openlp.plugins.media.forms.mediaclipselectorform.critical_error_message_box') as \
mocked_critical_error_message_box,\
patch('PyQt4.QtGui.QDialog.exec_') as mocked_exec:
self.form.exec_()
# WHEN: The save button is clicked with a NoneType in start_time_ms or end_time_ms
self.form.accept()
# THEN: we should get an error message
mocked_critical_error_message_box.assert_called_with('DVD not loaded correctly',
'The DVD was not loaded correctly, '
'please re-load and try again.')