Skip to content

Commit

Permalink
Use select() in status thread.
Browse files Browse the repository at this point in the history
The ``StatusThread`` now uses ``select.select()`` calls with a timeout
to check whether the MPD ``idle`` command has new information already or
not. This prevents a blocked client if something goes wrong.

Refs #45.
  • Loading branch information
dbrgn committed Feb 2, 2014
1 parent 47b6dbc commit f960309
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 3 deletions.
25 changes: 23 additions & 2 deletions orochi/backends/mpd.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from __future__ import print_function, division, absolute_import, unicode_literals

import os
import select
import threading
import functools
import logging
Expand Down Expand Up @@ -69,18 +70,38 @@ def __init__(self, host, port, timeout):
def run(self):
"""Start the thread."""
logger.debug('[status thread] Starting.')

# Connect
self.client.connect(self.host, self.port)

# Store old state
oldstate = self.client.status().get('state')

# Send an asynchronous IDLE command
self.client.send_idle('player')

# Set the timeout for the select() command in seconds. This allows the
# ``self._stop`` flag to be checked regularly. Not doing so would
# result in an indefinitely blocked client if something goes wrong.
select_timeout = 1.0

while not self._stop:
systems = self.client.idle() # Blocking call
if not 'player' in systems:
# Do a select() call to see if socket is ready
changes = select.select([self.client], [], [], select_timeout)
# If nothing has changed, loop again.
if self.client not in changes[0]:
continue
# Otherwise, reset the IDLE command and query / process status.
logger.debug('[status thread] Player status has changed.')
self.client.noidle()
status = self.client.status()
newstate = status.get('state')
if oldstate == 'play' and newstate == 'stop' and status.get('songid') is None:
logger.debug('[status thread] Song has ended.')
os.kill(os.getpid(), signals.SONG_ENDED)
oldstate = newstate
# Back to IDLE state.
self.client.send_idle('player')
logger.debug('[status thread] Exiting.')

def stop(self):
Expand Down
1 change: 0 additions & 1 deletion orochi/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,6 @@ def _song_end_handler(self, signum, frame):
"""Signal handler for SIGUSR1. Advance to the next track, if
available."""
print('')
print('Song has ended!')
if self.status['at_last_track']:
print('Playlist has ended!')
self.do_next_mix()
Expand Down

0 comments on commit f960309

Please sign in to comment.