Merge lp:~tomasgroth/openlp/bugfixes17 into lp:openlp

Proposed by Tomas Groth
Status: Merged
Approved by: Raoul Snyman
Approved revision: 2530
Merged at revision: 2524
Proposed branch: lp:~tomasgroth/openlp/bugfixes17
Merge into: lp:openlp
Diff against target: 206 lines (+65/-40)
6 files modified
openlp/core/ui/media/mediacontroller.py (+3/-3)
openlp/core/ui/media/vlcplayer.py (+26/-31)
openlp/core/ui/media/webkitplayer.py (+1/-1)
openlp/core/ui/slidecontroller.py (+7/-2)
openlp/plugins/presentations/lib/mediaitem.py (+2/-1)
tests/functional/openlp_plugins/presentations/test_mediaitem.py (+26/-2)
To merge this branch: bzr merge lp:~tomasgroth/openlp/bugfixes17
Reviewer Review Type Date Requested Status
Raoul Snyman Approve
Tim Bentley Approve
Review via email: mp+253448@code.launchpad.net

Description of the change

Insert timeout on acquiring lock in slidecontroller to avoid hang. Fixes bug 1413324.
Run XInitThreads when using VLC to make it work correctly. Fixes bug 1433245.
Disable the stop button in the slidecontroller mediaplayer buttons instead of hiding it to stop the position and audio slider resizing. Fixes bug 1431478.
Fixed a webkit player exception. Fixes bug 1431476.
Fix crash if presentation file in the mediamanger was removed bewteen sessions. Fixes bug 1432418.
Updated the list of extensions supported by VLC.

To post a comment you must log in.
Revision history for this message
Tomas Groth (tomasgroth) wrote :

lp:~tomasgroth/openlp/bugfixes17 (revision 2530)
[SUCCESS] https//ci.openlp.io/job/Branch-01-Pull/994/
[SUCCESS] https//ci.openlp.io/job/Branch-02-Functional-Tests/917/
[SUCCESS] https//ci.openlp.io/job/Branch-03-Interface-Tests/859/
[SUCCESS] https//ci.openlp.io/job/Branch-04a-Windows_Functional_Tests/748/
[SUCCESS] https//ci.openlp.io/job/Branch-04b-Windows_Interface_Tests/347/
[SUCCESS] https//ci.openlp.io/job/Branch-05a-Code_Analysis/484/
[SUCCESS] https//ci.openlp.io/job/Branch-05b-Test_Coverage/355/

Revision history for this message
Tim Bentley (trb143) :
review: Approve
Revision history for this message
Raoul Snyman (raoul-snyman) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'openlp/core/ui/media/mediacontroller.py'
2--- openlp/core/ui/media/mediacontroller.py 2015-02-18 21:32:42 +0000
3+++ openlp/core/ui/media/mediacontroller.py 2015-03-18 22:13:54 +0000
4@@ -589,7 +589,7 @@
5 else:
6 controller.mediabar.actions['playbackPlay'].setVisible(False)
7 controller.mediabar.actions['playbackPause'].setVisible(True)
8- controller.mediabar.actions['playbackStop'].setVisible(True)
9+ controller.mediabar.actions['playbackStop'].setDisabled(False)
10 if controller.is_live:
11 if controller.hide_menu.defaultAction().isChecked() and not controller.media_info.is_background:
12 controller.hide_menu.defaultAction().trigger()
13@@ -619,7 +619,7 @@
14 display = self._define_display(controller)
15 self.current_media_players[controller.controller_type].pause(display)
16 controller.mediabar.actions['playbackPlay'].setVisible(True)
17- controller.mediabar.actions['playbackStop'].setVisible(True)
18+ controller.mediabar.actions['playbackStop'].setDisabled(False)
19 controller.mediabar.actions['playbackPause'].setVisible(False)
20
21 def media_stop_msg(self, msg):
22@@ -645,7 +645,7 @@
23 self.current_media_players[controller.controller_type].set_visible(display, False)
24 controller.seek_slider.setSliderPosition(0)
25 controller.mediabar.actions['playbackPlay'].setVisible(True)
26- controller.mediabar.actions['playbackStop'].setVisible(False)
27+ controller.mediabar.actions['playbackStop'].setDisabled(True)
28 controller.mediabar.actions['playbackPause'].setVisible(False)
29
30 def media_volume_msg(self, msg):
31
32=== modified file 'openlp/core/ui/media/vlcplayer.py'
33--- openlp/core/ui/media/vlcplayer.py 2015-01-18 13:39:21 +0000
34+++ openlp/core/ui/media/vlcplayer.py 2015-03-18 22:13:54 +0000
35@@ -27,10 +27,11 @@
36 import logging
37 import os
38 import threading
39+import sys
40
41 from PyQt4 import QtGui
42
43-from openlp.core.common import Settings, is_win, is_macosx
44+from openlp.core.common import Settings, is_win, is_macosx, is_linux
45 from openlp.core.lib import translate
46 from openlp.core.ui.media import MediaState, MediaType
47 from openlp.core.ui.media.mediaplayer import MediaPlayer
48@@ -62,36 +63,30 @@
49 if LooseVersion(VERSION.split()[0]) < LooseVersion('1.1.0'):
50 VLC_AVAILABLE = False
51 log.debug('VLC could not be loaded, because the vlc version is too old: %s' % VERSION)
52-
53-AUDIO_EXT = ['*.mp3', '*.wav', '*.wma', '*.ogg']
54-
55-VIDEO_EXT = [
56- '*.3gp',
57- '*.asf', '*.wmv',
58- '*.au',
59- '*.avi',
60- '*.divx',
61- '*.flv',
62- '*.mov',
63- '*.mp4', '*.m4v',
64- '*.ogm', '*.ogv',
65- '*.mkv', '*.mka',
66- '*.ts', '*.mpg',
67- '*.mpg', '*.mp2',
68- '*.nsc',
69- '*.nsv',
70- '*.nut',
71- '*.ra', '*.ram', '*.rm', '*.rv', '*.rmbv',
72- '*.a52', '*.dts', '*.aac', '*.flac', '*.dv', '*.vid',
73- '*.tta', '*.tac',
74- '*.ty',
75- '*.dts',
76- '*.xa',
77- '*.iso',
78- '*.vob',
79- '*.webm',
80- '*.xvid'
81-]
82+ # On linux we need to initialise X threads, but not when running tests.
83+ if VLC_AVAILABLE and is_linux() and 'nose' not in sys.argv[0]:
84+ import ctypes
85+ try:
86+ x11 = ctypes.cdll.LoadLibrary('libX11.so')
87+ x11.XInitThreads()
88+ except:
89+ log.exception('Failed to run XInitThreads(), VLC might not work properly!')
90+
91+# Audio and video extensions copied from 'include/vlc_interface.h' from vlc 2.2.0 source
92+AUDIO_EXT = ['*.3ga', '*.669', '*.a52', '*.aac', '*.ac3', '*.adt', '*.adts', '*.aif', '*.aifc', '*.aiff', '*.amr',
93+ '*.aob', '*.ape', '*.awb', '*.caf', '*.dts', '*.flac', '*.it', '*.kar', '*.m4a', '*.m4b', '*.m4p', '*.m5p',
94+ '*.mid', '*.mka', '*.mlp', '*.mod', '*.mpa', '*.mp1', '*.mp2', '*.mp3', '*.mpc', '*.mpga', '*.mus',
95+ '*.oga', '*.ogg', '*.oma', '*.opus', '*.qcp', '*.ra', '*.rmi', '*.s3m', '*.sid', '*.spx', '*.thd', '*.tta',
96+ '*.voc', '*.vqf', '*.w64', '*.wav', '*.wma', '*.wv', '*.xa', '*.xm']
97+
98+VIDEO_EXT = ['*.3g2', '*.3gp', '*.3gp2', '*.3gpp', '*.amv', '*.asf', '*.avi', '*.bik', '*.divx', '*.drc', '*.dv',
99+ '*.f4v', '*.flv', '*.gvi', '*.gxf', '*.iso', '*.m1v', '*.m2v', '*.m2t', '*.m2ts', '*.m4v', '*.mkv',
100+ '*.mov', '*.mp2', '*.mp2v', '*.mp4', '*.mp4v', '*.mpe', '*.mpeg', '*.mpeg1', '*.mpeg2', '*.mpeg4', '*.mpg',
101+ '*.mpv2', '*.mts', '*.mtv', '*.mxf', '*.mxg', '*.nsv', '*.nuv', '*.ogg', '*.ogm', '*.ogv', '*.ogx', '*.ps',
102+ '*.rec', '*.rm', '*.rmvb', '*.rpl', '*.thp', '*.tod', '*.ts', '*.tts', '*.txd', '*.vob', '*.vro', '*.webm',
103+ '*.wm', '*.wmv', '*.wtv', '*.xesc',
104+ # These extensions was not in the official list, added manually.
105+ '*.nut', '*.rv', '*.xvid']
106
107
108 class VlcPlayer(MediaPlayer):
109
110=== modified file 'openlp/core/ui/media/webkitplayer.py'
111--- openlp/core/ui/media/webkitplayer.py 2015-01-26 21:18:23 +0000
112+++ openlp/core/ui/media/webkitplayer.py 2015-03-18 22:13:54 +0000
113@@ -375,7 +375,7 @@
114 # check if conversion was ok and value is not 'NaN'
115 if length and length != float('inf'):
116 length = int(length * 1000)
117- if current_time:
118+ if current_time and length:
119 controller.media_info.length = length
120 controller.seek_slider.setMaximum(length)
121 if not controller.seek_slider.isSliderDown():
122
123=== modified file 'openlp/core/ui/slidecontroller.py'
124--- openlp/core/ui/slidecontroller.py 2015-03-09 20:57:39 +0000
125+++ openlp/core/ui/slidecontroller.py 2015-03-18 22:13:54 +0000
126@@ -1069,8 +1069,13 @@
127 :param start:
128 """
129 # Only one thread should be in here at the time. If already locked just skip, since the update will be
130- # done by the thread holding the lock. If it is a "start" slide, we must wait for the lock.
131- if not self.slide_selected_lock.acquire(start):
132+ # done by the thread holding the lock. If it is a "start" slide, we must wait for the lock, but only for 0.2
133+ # seconds, since we don't want to cause a deadlock
134+ timeout = 0.2 if start else -1
135+ if not self.slide_selected_lock.acquire(start, timeout):
136+ if start:
137+ self.log_debug('Could not get lock in slide_selected after waiting %f, skip to avoid deadlock.'
138+ % timeout)
139 return
140 row = self.preview_widget.current_slide_number()
141 self.selected_row = 0
142
143=== modified file 'openlp/plugins/presentations/lib/mediaitem.py'
144--- openlp/plugins/presentations/lib/mediaitem.py 2015-03-10 22:00:32 +0000
145+++ openlp/plugins/presentations/lib/mediaitem.py 2015-03-18 22:13:54 +0000
146@@ -245,7 +245,8 @@
147 doc = self.controllers[cidx].add_document(filepath)
148 if clean_for_update:
149 thumb_path = doc.get_thumbnail_path(1, True)
150- if not thumb_path or os.path.getmtime(thumb_path) < os.path.getmtime(filepath):
151+ if not thumb_path or not os.path.exists(filepath) or os.path.getmtime(
152+ thumb_path) < os.path.getmtime(filepath):
153 doc.presentation_deleted()
154 else:
155 doc.presentation_deleted()
156
157=== modified file 'tests/functional/openlp_plugins/presentations/test_mediaitem.py'
158--- tests/functional/openlp_plugins/presentations/test_mediaitem.py 2015-03-10 23:46:37 +0000
159+++ tests/functional/openlp_plugins/presentations/test_mediaitem.py 2015-03-18 22:13:54 +0000
160@@ -87,7 +87,7 @@
161
162 def clean_up_thumbnails_test(self):
163 """
164- Test that the clean_up_thumbnails method works as expected.
165+ Test that the clean_up_thumbnails method works as expected when files exists.
166 """
167 # GIVEN: A mocked controller, and mocked os.path.getmtime
168 mocked_controller = MagicMock()
169@@ -98,8 +98,10 @@
170 'Mocked': mocked_controller
171 }
172 presentation_file = 'file.tmp'
173- with patch('openlp.plugins.presentations.lib.mediaitem.os.path.getmtime') as mocked_getmtime:
174+ with patch('openlp.plugins.presentations.lib.mediaitem.os.path.getmtime') as mocked_getmtime, \
175+ patch('openlp.plugins.presentations.lib.mediaitem.os.path.exists') as mocked_exists:
176 mocked_getmtime.side_effect = [100, 200]
177+ mocked_exists.return_value = True
178
179 # WHEN: calling clean_up_thumbnails
180 self.media_item.clean_up_thumbnails(presentation_file, True)
181@@ -107,3 +109,25 @@
182 # THEN: doc.presentation_deleted should have been called since the thumbnails mtime will be greater than
183 # the presentation_file's mtime.
184 mocked_doc.assert_has_calls([call.get_thumbnail_path(1, True), call.presentation_deleted()], True)
185+
186+ def clean_up_thumbnails_missing_file_test(self):
187+ """
188+ Test that the clean_up_thumbnails method works as expected when file is missing.
189+ """
190+ # GIVEN: A mocked controller, and mocked os.path.exists
191+ mocked_controller = MagicMock()
192+ mocked_doc = MagicMock()
193+ mocked_controller.add_document.return_value = mocked_doc
194+ mocked_controller.supports = ['tmp']
195+ self.media_item.controllers = {
196+ 'Mocked': mocked_controller
197+ }
198+ presentation_file = 'file.tmp'
199+ with patch('openlp.plugins.presentations.lib.mediaitem.os.path.exists') as mocked_exists:
200+ mocked_exists.return_value = False
201+
202+ # WHEN: calling clean_up_thumbnails
203+ self.media_item.clean_up_thumbnails(presentation_file, True)
204+
205+ # THEN: doc.presentation_deleted should have been called since the presentation file did not exists.
206+ mocked_doc.assert_has_calls([call.get_thumbnail_path(1, True), call.presentation_deleted()], True)