Merge lp:~trb143/openlp/bug-892571 into lp:openlp

Proposed by Tim Bentley
Status: Merged
Approved by: Raoul Snyman
Approved revision: 1804
Merged at revision: 1808
Proposed branch: lp:~trb143/openlp/bug-892571
Merge into: lp:openlp
Diff against target: 71 lines (+30/-6)
1 file modified
openlp/core/ui/slidecontroller.py (+30/-6)
To merge this branch: bzr merge lp:~trb143/openlp/bug-892571
Reviewer Review Type Date Requested Status
Raoul Snyman Approve
Andreas Preikschat Pending
Review via email: mp+83658@code.launchpad.net

This proposal supersedes a proposal from 2011-11-27.

Description of the change

Stop keyboard floods getting the slide controller and service manager out of set.
Key presses are only accepted when the previous updates have happened.

To Test set preview next song to on.
Add 5 songs to service manager
Select the first one.
Press the right arrow key fast.

To post a comment you must log in.
Revision history for this message
Andreas Preikschat (googol-deactivatedaccount) wrote : Posted in a previous version of this proposal

Now "right arrow", "right arrow" does not work (only the first "right arrow" is recognised). If I press the "right arrow" twice, I want to go to the song after the next one.

review: Needs Fixing
Revision history for this message
Tim Bentley (trb143) wrote : Posted in a previous version of this proposal

Well If I use a mutex it locks up.
Without a major (2-3 month) re-write of the code path as it is very long and impacts plugins etc I am not sure what else to try.
The code
   looks up the current selected service item
   Selects the next one.
   Flushes the events to add a cursor
   Adds a service item
   This signals plugins twice to turn off and then hand new service item.
   selects the next service item to preview it.
   Flushes the events to remove the cursor

The Keyboard will start this flow BEFORE the previous has finished so you get a number of calling chains running at the same time.

Revision history for this message
Andreas Preikschat (googol-deactivatedaccount) wrote : Posted in a previous version of this proposal

I just do not think this is the right attempt. I see that it is difficult (impossible ?) to fix this!?

Revision history for this message
Jonathan Stafford (staffj01) wrote : Posted in a previous version of this proposal

I'm still new to this so sorry if my comments don't make much sense.

Rather than disabling keypresses while the slide controller is proccessing an action, would it be possible to somehow queue keypresses and then execute them one at a time afterwards?

Alternatively, could the code that looks up the currently selected service item somehow be delayed if another keypress is currently being processed? I guess that could still lead to multiple keypresses being process out of order though couldn't it?

Not sure if any of those ideas have any merit or not...

Revision history for this message
Raoul Snyman (raoul-snyman) wrote :

Tried to break it, and I couldn't.

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/slidecontroller.py'
2--- openlp/core/ui/slidecontroller.py 2011-10-31 09:14:07 +0000
3+++ openlp/core/ui/slidecontroller.py 2011-11-28 18:10:49 +0000
4@@ -26,9 +26,9 @@
5 ###############################################################################
6
7 import logging
8-import os
9 import time
10 import copy
11+from collections import deque
12
13 from PyQt4 import QtCore, QtGui
14 from PyQt4.phonon import Phonon
15@@ -91,6 +91,8 @@
16 self.typeLabel.setText(UiStrings().Live)
17 self.split = 1
18 self.typePrefix = u'live'
19+ self.keypress_queue = deque()
20+ self.keypress_loop = False
21 else:
22 self.typeLabel.setText(UiStrings().Preview)
23 self.split = 0
24@@ -578,12 +580,34 @@
25 self.display.videoStop()
26
27 def servicePrevious(self):
28- time.sleep(0.1)
29- Receiver.send_message('servicemanager_previous_item')
30+ """
31+ Live event to select the previous service item from the service manager.
32+ """
33+ self.keypress_queue.append(u'previous')
34+ self._process_queue()
35+
36
37 def serviceNext(self):
38- time.sleep(0.1)
39- Receiver.send_message('servicemanager_next_item')
40+ """
41+ Live event to select the next service item from the service manager.
42+ """
43+ self.keypress_queue.append(u'next')
44+ self._process_queue()
45+
46+ def _process_queue(self):
47+ """
48+ Process the service item request queue. The key presses can arrive
49+ faster than the processing so implement a FIFO queue.
50+ """
51+ if len(self.keypress_queue):
52+ while len(self.keypress_queue) and not self.keypress_loop:
53+ self.keypress_loop = True
54+ if self.keypress_queue.popleft() == u'previous':
55+ Receiver.send_message('servicemanager_previous_item')
56+ else:
57+ Receiver.send_message('servicemanager_next_item')
58+ self.keypress_loop = False
59+
60
61 def screenSizeChanged(self):
62 """
63@@ -771,7 +795,7 @@
64 log.debug(u'processManagerItem live = %s' % self.isLive)
65 self.onStopLoop()
66 old_item = self.serviceItem
67- # take a copy not a link to the servicemeanager copy.
68+ # take a copy not a link to the servicemanager copy.
69 self.serviceItem = copy.copy(serviceItem)
70 if old_item and self.isLive and old_item.is_capable(
71 ItemCapabilities.ProvidesOwnDisplay):