Skip to content

Commit fb17ead

Browse files
committed
fixing several threading issues introduced by threaded timeout counter
1 parent b54e5b4 commit fb17ead

File tree

3 files changed

+112
-112
lines changed

3 files changed

+112
-112
lines changed

pyradio/log.py

Lines changed: 93 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import curses
33
from sys import version_info
44
import logging
5+
import threading
56

67
logger = logging.getLogger(__name__)
78

@@ -19,7 +20,7 @@ class Log(object):
1920

2021
_color_change = False
2122

22-
lock = None
23+
lock = threading.Lock()
2324

2425
def __init__(self):
2526
self.width = None
@@ -41,110 +42,111 @@ def _do_i_print_last_char(self, first_print):
4142
pass
4243
return first_print
4344

44-
def write(self, msg=None, suffix=None, counter=None, help_msg=False, notify_function=None):
45+
def write(self, msg=None, suffix=None, counter=None, help_msg=False, error_msg=False, notify_function=None):
4546
if self.asked_to_stop:
4647
self.counter = None
4748
return
4849
if self.cursesScreen:
49-
#if logger.isEnabledFor(logging.DEBUG):
50-
# logger.debug('before ----------------------------')
51-
# logger.debug('msg = "{}"'.format(msg))
52-
# logger.debug('self.msg = "{}"'.format(self.msg))
53-
# logger.debug('suffix = "{}"'.format(suffix))
54-
# logger.debug('self.suffix = "{}"'.format(self.suffix))
55-
# logger.debug('counter = "{}"'.format(counter))
56-
# logger.debug('self.counter = "{}"'.format(self.counter))
57-
58-
first_print = True
59-
if msg is not None: self.msg = msg
60-
if suffix is not None: self.suffix = suffix
61-
if counter is not None: self.counter = counter
62-
63-
#if logger.isEnabledFor(logging.DEBUG):
64-
# logger.debug('after ----------------------------')
65-
# logger.debug('msg = "{}"'.format(msg))
66-
# logger.debug('self.msg = "{}"'.format(self.msg))
67-
# logger.debug('suffix = "{}"'.format(suffix))
68-
# logger.debug('self.suffix = "{}"'.format(self.suffix))
69-
# logger.debug('counter = "{}"'.format(counter))
70-
# logger.debug('self.counter = "{}"'.format(self.counter))
71-
72-
""" update main message """
73-
if self.msg:
74-
if self.lock is not None:
75-
self.lock.acquire()
76-
self.cursesScreen.erase()
77-
try:
78-
d_msg = self.msg.strip()[0: self.width].replace("\r", "").replace("\n", "")
79-
self.cursesScreen.addstr(0, 1, d_msg)
80-
except:
50+
with self.lock:
51+
#if logger.isEnabledFor(logging.DEBUG):
52+
# logger.debug('before ----------------------------')
53+
# logger.debug('msg = "{}"'.format(msg))
54+
# logger.debug('self.msg = "{}"'.format(self.msg))
55+
# logger.debug('suffix = "{}"'.format(suffix))
56+
# logger.debug('self.suffix = "{}"'.format(self.suffix))
57+
# logger.debug('counter = "{}"'.format(counter))
58+
# logger.debug('self.counter = "{}"'.format(self.counter))
59+
60+
first_print = True
61+
if msg is not None: self.msg = msg
62+
if suffix is not None: self.suffix = suffix
63+
if counter is not None: self.counter = counter
64+
self.error_msg = True if error_msg else False
65+
66+
#if logger.isEnabledFor(logging.DEBUG):
67+
# logger.debug('after ----------------------------')
68+
# logger.debug('msg = "{}"'.format(msg))
69+
# logger.debug('self.msg = "{}"'.format(self.msg))
70+
# logger.debug('suffix = "{}"'.format(suffix))
71+
# logger.debug('self.suffix = "{}"'.format(self.suffix))
72+
# logger.debug('counter = "{}"'.format(counter))
73+
# logger.debug('self.counter = "{}"'.format(self.counter))
74+
75+
if self.asked_to_stop:
76+
self.counter = None
77+
return
78+
""" update main message """
79+
if self.msg:
80+
self.cursesScreen.erase()
8181
try:
82-
d_msg = self.msg.encode('utf-8', 'replace').strip()[0: self.width].replace("\r", "").replace("\n", "")
82+
d_msg = self.msg.strip()[0: self.width].replace("\r", "").replace("\n", "")
8383
self.cursesScreen.addstr(0, 1, d_msg)
8484
except:
85-
if logger.isEnabledFor(logging.ERROR):
86-
logger.error('Cannot update the Status Bar...')
87-
if logger.isEnabledFor(logging.DEBUG):
88-
try:
89-
logger.debug('Status: "{}"'.format(self.msg))
90-
except:
91-
pass
92-
self.cursesScreen.refresh()
93-
if self.lock is not None:
94-
self.lock.release()
95-
96-
self._active_width = self.width
97-
98-
""" display suffix """
99-
if self.suffix:
100-
d_msg = ' [' + self.suffix + ']'
101-
if self.lock is not None:
102-
self.lock.acquire()
103-
self.cursesScreen.addstr(0, self._active_width - len(d_msg), d_msg)
104-
self.cursesScreen.chgat(0, self._active_width - len(d_msg) +1, len(d_msg) -1, curses.color_pair(1))
105-
first_print = self._do_i_print_last_char(first_print)
106-
self.cursesScreen.refresh()
107-
if self.lock is not None:
108-
self.lock.release()
109-
self._active_width -= len(d_msg)
110-
if logger.isEnabledFor(logging.DEBUG):
111-
logger.debug('Suffix: {}'.format(self.suffix))
112-
113-
""" display counter """
114-
if self.counter:
115-
if self.counter == '0':
85+
try:
86+
d_msg = self.msg.encode('utf-8', 'replace').strip()[0: self.width].replace("\r", "").replace("\n", "")
87+
self.cursesScreen.addstr(0, 1, d_msg)
88+
except:
89+
if logger.isEnabledFor(logging.ERROR):
90+
logger.error('Cannot update the Status Bar...')
91+
if logger.isEnabledFor(logging.DEBUG):
92+
try:
93+
logger.debug('Status: "{}"'.format(self.msg))
94+
except:
95+
pass
96+
97+
self._active_width = self.width
98+
99+
if self.asked_to_stop:
116100
self.counter = None
117-
if self.counter:
118-
if self.suffix:
119-
self._active_width += 1
120-
d_msg = ' [' + self.counter + ']'
121-
if self.lock is not None:
122-
self.lock.acquire()
101+
return
102+
""" display suffix """
103+
if self.suffix:
104+
d_msg = ' [' + self.suffix + ']'
123105
self.cursesScreen.addstr(0, self._active_width - len(d_msg), d_msg)
106+
self.cursesScreen.chgat(0, self._active_width - len(d_msg) +1, len(d_msg) -1, curses.color_pair(1))
124107
first_print = self._do_i_print_last_char(first_print)
125108
self.cursesScreen.refresh()
126-
if self.lock is not None:
127-
self.lock.release()
128109
self._active_width -= len(d_msg)
129-
if logger.isEnabledFor(logging.DEBUG):
130-
logger.debug('Counter: {}'.format(self.counter))
131-
132-
""" display press ? """
133-
if help_msg or self.display_help_message:
134-
self.counter = None
135-
suffix_string = ' Press ? for help'
136-
if self.lock is not None:
137-
self.lock.acquire()
138-
self.cursesScreen.addstr(0, self._active_width - len(suffix_string), suffix_string)
139-
self.cursesScreen.refresh()
140-
if self.lock is not None:
141-
self.lock.release()
142-
self.display_help_message = True
143110
if logger.isEnabledFor(logging.DEBUG):
144-
logger.debug('Press ? for help: yes')
145-
else:
111+
logger.debug('Suffix: {}'.format(self.suffix))
112+
113+
""" display counter """
114+
if self.counter:
115+
if self.counter == '0':
116+
self.counter = None
117+
if self.counter:
118+
if self.suffix:
119+
self._active_width += 1
120+
d_msg = ' [' + self.counter + ']'
121+
self.cursesScreen.addstr(0, self._active_width - len(d_msg), d_msg)
122+
first_print = self._do_i_print_last_char(first_print)
123+
self.cursesScreen.refresh()
124+
self._active_width -= len(d_msg)
125+
self.display_help_message = False
146126
if logger.isEnabledFor(logging.DEBUG):
147-
logger.debug('Press ? for help: no')
127+
logger.debug('Counter: {}'.format(self.counter))
128+
129+
if self.asked_to_stop:
130+
self.counter = None
131+
return
132+
""" display press ? """
133+
if help_msg or self.display_help_message:
134+
if not self.error_msg:
135+
self.counter = None
136+
suffix_string = ' Press ? for help'
137+
self.cursesScreen.addstr(0, self._active_width - len(suffix_string), suffix_string)
138+
self.cursesScreen.refresh()
139+
self.display_help_message = True
140+
if logger.isEnabledFor(logging.DEBUG):
141+
logger.debug('Press ? for help: yes')
142+
else:
143+
if logger.isEnabledFor(logging.DEBUG):
144+
logger.debug('Press ? for help: no')
145+
146+
if self.asked_to_stop:
147+
self.counter = None
148+
return
149+
self.cursesScreen.refresh()
148150

149151
def readline(self):
150152
pass

pyradio/player.py

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,6 @@ class Player(object):
122122

123123
muted = False
124124

125-
status_update_lock = threading.Lock()
126-
127125
ctrl_c_pressed = False
128126

129127
""" When found in station transmission, playback is on """
@@ -162,6 +160,7 @@ def __init__(self, outputStream,
162160
self.playback_timeout_counter = playback_timeout_counter
163161
self.playback_timeout_handler = playback_timeout_handler
164162
self.info_display_handler = info_display_handler
163+
self.status_update_lock = outputStream.lock
165164

166165
def __del__(self):
167166
self.close()
@@ -455,7 +454,7 @@ def updateStatus(self, *args):
455454
string_to_show = self._format_volume_string(subsystemOut) + self._format_title_string(self.oldUserInput['Title'])
456455

457456
if self.show_volume and self.oldUserInput['Title']:
458-
self.outputStream.write(msg=string_to_show)
457+
self.outputStream.write(msg=string_to_show, counter='')
459458
self.threadUpdateTitle()
460459
elif self._is_in_playback_token(subsystemOut):
461460
self.stop_timeout_counter_thread = True
@@ -470,7 +469,7 @@ def updateStatus(self, *args):
470469
new_input = 'Playing: "{}"'.format(self.name)
471470
else:
472471
new_input = self.oldUserInput['Title']
473-
self.outputStream.write(msg=new_input)
472+
self.outputStream.write(msg=new_input, counter='')
474473
self.playback_is_on = True
475474
if 'AO: [' in subsystemOut:
476475
with self.status_update_lock:
@@ -506,7 +505,7 @@ def updateStatus(self, *args):
506505
ok_to_display = True
507506
if ok_to_display and self.playback_is_on:
508507
string_to_show = self.title_prefix + title
509-
self.outputStream.write(msg=string_to_show)
508+
self.outputStream.write(msg=string_to_show, counter='')
510509
else:
511510
ok_to_display = True
512511
if (logger.isEnabledFor(logging.INFO)):
@@ -515,11 +514,11 @@ def updateStatus(self, *args):
515514
title = 'Playing: "{}"'.format(self.name)
516515
self.oldUserInput['Title'] = title
517516
string_to_show = self.title_prefix + title
518-
self.outputStream.write(msg=string_to_show)
517+
self.outputStream.write(msg=string_to_show, counter='')
519518
#else:
520519
# if self.oldUserInput['Title'] == '':
521520
# self.oldUserInput['Title'] = 'Connecting to: "{}"'.format(self.name)
522-
# self.outputStream.write(msg=self.oldUserInput['Title'])
521+
# self.outputStream.write(msg=self.oldUserInput['Title'], counter='')
523522

524523
else:
525524
for a_token in self.icy_audio_tokens.keys():
@@ -688,7 +687,7 @@ def _get_mpv_metadata(self, *args):
688687
string_to_show = self.title_prefix + self.oldUserInput['Title']
689688
if stop():
690689
return False
691-
self.outputStream.write(msg=string_to_show)
690+
self.outputStream.write(msg=string_to_show, counter='')
692691
if not self.playback_is_on:
693692
return self._set_mpv_playback_is_on(stop)
694693
else:
@@ -698,7 +697,7 @@ def _get_mpv_metadata(self, *args):
698697
string_to_show = self.title_prefix + title
699698
if stop():
700699
return False
701-
self.outputStream.write(msg=string_to_show)
700+
self.outputStream.write(msg=string_to_show, counter='')
702701
self.oldUserInput['Title'] = title
703702

704703
#logger.info('DE a_data {}'.format(a_data))
@@ -781,7 +780,7 @@ def _set_mpv_playback_is_on(self, stop):
781780
if (not self.playback_is_on) and (logger.isEnabledFor(logging.INFO)):
782781
logger.info('*** _set_mpv_playback_is_on(): Start of playback detected ***')
783782
new_input = 'Playing: "{}"'.format(self.name)
784-
self.outputStream.write(msg=new_input)
783+
self.outputStream.write(msg=new_input, counter='')
785784
if self.oldUserInput['Title'] == '':
786785
self.oldUserInput['Input'] = new_input
787786
else:
@@ -848,7 +847,7 @@ def play(self, name, streamUrl, encoding = ''):
848847
self.show_volume = True
849848
self.title_prefix = ''
850849
self.playback_is_on = False
851-
self.outputStream.write(msg='Station: "{}" - Opening connection...'.format(name))
850+
self.outputStream.write(msg='Station: "{}" - Opening connection...'.format(name), counter='')
852851
if logger.isEnabledFor(logging.INFO):
853852
logger.info('Selected Station: "{}"'.format(name))
854853
if encoding:
@@ -956,9 +955,9 @@ def toggleMute(self):
956955
self.title_prefix = ''
957956
self.show_volume = True
958957
if self.oldUserInput['Title'] == '':
959-
self.outputStream.write(msg=self.title_prefix + self._format_title_string(self.oldUserInput['Input']))
958+
self.outputStream.write(msg=self.title_prefix + self._format_title_string(self.oldUserInput['Input']), counter='')
960959
else:
961-
self.outputStream.write(msg=self.title_prefix + self._format_title_string(self.oldUserInput['Title']))
960+
self.outputStream.write(msg=self.title_prefix + self._format_title_string(self.oldUserInput['Title']), counter='')
962961

963962
def _mute(self):
964963
""" to be implemented on subclasses """
@@ -1326,7 +1325,7 @@ def _display_mpv_volume_value(self):
13261325
else:
13271326
info_string = self._format_title_string(self.oldUserInput['Input'])
13281327
string_to_show = self._format_volume_string('Volume: ' + str(vol) + '%') + info_string
1329-
self.outputStream.write(msg=string_to_show)
1328+
self.outputStream.write(msg=string_to_show, counter='')
13301329
self.threadUpdateTitle()
13311330
self.volume = vol
13321331

pyradio/radio.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,6 @@ def setup(self, stdscr):
390390
self.playbackTimeoutCounter,
391391
self.connectionFailed,
392392
self._show_station_info_from_thread)
393-
self.log.lock = self.player.status_update_lock
394393
except:
395394
# no player
396395
self.ws.operation_mode = self.ws.NO_PLAYER_ERROR_MODE
@@ -686,15 +685,15 @@ def __displayBodyLine(self, lineNum, pad, station):
686685
def run(self):
687686
if self.ws.operation_mode == self.ws.NO_PLAYER_ERROR_MODE:
688687
if platform.startswith('win'):
689-
self.log.write(msg='mplayer not found. Press any key to exit....')
688+
self.log.write(msg='mplayer not found. Press any key to exit....', error_msg=True)
690689
else:
691690
if self.requested_player:
692691
if ',' in self.requested_player:
693-
self.log.write(msg='None of "{}" players is available. Press any key to exit....'.format(self.requested_player))
692+
self.log.write(msg='None of "{}" players is available. Press any key to exit....'.format(self.requested_player), error_msg=True)
694693
else:
695-
self.log.write(msg='Player "{}" not available. Press any key to exit....'.format(self.requested_player))
694+
self.log.write(msg='Player "{}" not available. Press any key to exit....'.format(self.requested_player), error_msg=True)
696695
else:
697-
self.log.write(msg="No player available. Press any key to exit....")
696+
self.log.write(msg="No player available. Press any key to exit....", error_msg=True)
698697
try:
699698
self.bodyWin.getch()
700699
except KeyboardInterrupt:
@@ -954,7 +953,7 @@ def stopPlayer(self, show_message=True):
954953
self._show_player_is_stopped()
955954

956955
def _show_player_is_stopped(self):
957-
self.log.write(msg='{}: Playback stopped'.format(self._format_player_string()), help_msg=True, suffix=self._status_suffix)
956+
self.log.write(msg='{}: Playback stopped'.format(self._format_player_string()), help_msg=True, suffix=self._status_suffix, counter='')
958957

959958
def removeStation(self):
960959
if self._cnf.confirm_station_deletion and not self._cnf.is_register:
@@ -3177,7 +3176,7 @@ def keypress(self, char):
31773176
# get station to register
31783177
# accept a-z, 0-9 and -
31793178
if char == ord('\''):
3180-
self._status_suffix = self.log.suffix = "'"
3179+
self._status_suffix = "'"
31813180
self._update_status_bar_right(status_suffix="'")
31823181
self._cnf.open_register_list = True
31833182
""" set selections 0,1,2 to saved values """

0 commit comments

Comments
 (0)