Skip to content

Commit 6934080

Browse files
committed
implementing player buffering
1 parent 46cd9a5 commit 6934080

File tree

4 files changed

+189
-11
lines changed

4 files changed

+189
-11
lines changed

pyradio/edit.py

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
except:
1313
from urlparse import urlparse
1414
from .simple_curses_widgets import SimpleCursesLineEdit, SimpleCursesCheckBox, SimpleCursesHorizontalPushButtons, DisabledWidget
15+
from .player import PlayerCache
1516
from .log import Log
1617

1718
import locale
@@ -1230,6 +1231,139 @@ def keypress(self, char):
12301231
return self._get_result(ret)
12311232

12321233

1234+
class PyRadioBuffering(object):
1235+
1236+
_text = 'Buffer size in seconds: '
1237+
_help_text = ' Help '
1238+
_note_text = ' Note '
1239+
_max_lines = 12
1240+
_cache_data = None
1241+
_step = 1
1242+
_big_step = 5
1243+
_limit = 60
1244+
1245+
def __init__(self,
1246+
parent,
1247+
config,
1248+
player,
1249+
global_functions=None):
1250+
self._parent = parent
1251+
self._cnf = config
1252+
self._player = player
1253+
self._global_functions = global_functions
1254+
if self._global_functions is None:
1255+
self._global_functions = {}
1256+
self.recording = lambda: self._player.recording
1257+
self._title = ' ' + self._player.PLAYER_NAME + ' Buffering '
1258+
if self._player.PLAYER_NAME == 'mplayer':
1259+
self._text = 'Buffer size in KBytes: '
1260+
self._step = 500
1261+
self._big_step = 1000
1262+
self._limit = 100000
1263+
self._cache_data = PlayerCache(
1264+
player.PLAYER_NAME,
1265+
self._cnf.data_dir,
1266+
lambda: self._player.recording
1267+
)
1268+
if self._cnf.buffering_data:
1269+
self._delay = self._cache_data.delay
1270+
else:
1271+
self._delay = 0
1272+
1273+
def save(self):
1274+
self._cache_data._save()
1275+
1276+
def show(self, parent=None):
1277+
if parent:
1278+
self._parent = parent
1279+
y, x = self._parent.getmaxyx()
1280+
new_y = int((y - self._max_lines) / 2) + 1
1281+
new_x = int((x - len(self._text) - 9 - 4) / 2)
1282+
self.MaxX = len(self._text) + 9 + 4
1283+
self._win = None
1284+
if y < self._max_lines + 2 or x < self.MaxX + 2:
1285+
self._win = curses.newwin(3, 20, int((y-2)/2), int((x - 20) / 2))
1286+
self._win.bkgdset(' ', curses.color_pair(3))
1287+
self._win.erase()
1288+
self._win.box()
1289+
self._win.addstr(1, 2, 'Window too small', curses.color_pair(10))
1290+
else:
1291+
1292+
self._win = curses.newwin(self._max_lines, self.MaxX, new_y, new_x)
1293+
self._win.bkgdset(' ', curses.color_pair(3))
1294+
self._win.erase()
1295+
self._win.box()
1296+
1297+
# show title
1298+
x = int((self.MaxX - len(self._title)) / 2)
1299+
self._win.addstr(0, x, self._title, curses.color_pair(11))
1300+
1301+
# show content
1302+
self._win.addstr(2, 4, self._text, curses.color_pair(10))
1303+
self._win.addstr('{}'.format(self._delay), curses.color_pair(11))
1304+
1305+
# show help
1306+
try:
1307+
self._win.addstr(4, 2, '─' * (self.MaxX - 4), curses.color_pair(3))
1308+
except:
1309+
self._win.addstr(4, 2, '─'.encode('utf-8') * (self.maxX - 6), curses.color_pair(3))
1310+
self._win.addstr(4, int((self.MaxX - len(self._help_text))/2), self._help_text, curses.color_pair(3))
1311+
self._win.addstr(5, 2, 'j k UP DOWN', curses.color_pair(11))
1312+
self._win.addstr(6, 2, 'PgUp PgDown', curses.color_pair(11))
1313+
self._win.addstr(' Adjust value', curses.color_pair(10))
1314+
self._win.addstr(7, 2, 'r', curses.color_pair(11))
1315+
self._win.addstr(' Load saved value', curses.color_pair(10))
1316+
self._win.addstr(8, 2, 'z', curses.color_pair(11))
1317+
self._win.addstr(' No buffering', curses.color_pair(10))
1318+
self._win.addstr(9, 2, 'ENTER s', curses.color_pair(11))
1319+
self._win.addstr(' Accept value', curses.color_pair(10))
1320+
self._win.addstr(10, 2, 'Esc q h RIGHT', curses.color_pair(11))
1321+
self._win.addstr(' Cancel operation', curses.color_pair(10))
1322+
self._win.refresh()
1323+
1324+
def keypress(self, char):
1325+
""" Returns:
1326+
-1: Cancel - []
1327+
0: go on - []
1328+
1: Ok = [buffering parameters]
1329+
"""
1330+
if char in self._global_functions.keys():
1331+
self._global_functions[char]()
1332+
1333+
elif char in (curses.KEY_ENTER, ord('\n'), ord('\r'), ord('s')):
1334+
self._cache_data.delay = self._delay
1335+
return 1, self._cache_data.cache
1336+
1337+
elif char in (curses.KEY_EXIT, 27, ord('q'), ord('h'), curses.KEY_LEFT):
1338+
return -1, []
1339+
1340+
elif char in (ord('j'), curses.KEY_UP,
1341+
ord('k'), curses.KEY_DOWN,
1342+
curses.KEY_NPAGE, curses.KEY_PPAGE,
1343+
ord('z'), ord('r')
1344+
):
1345+
if char == ord('r'):
1346+
self._delay = self._cache_data.delay
1347+
elif char in (ord('k'), curses.KEY_UP):
1348+
self._delay += self._step
1349+
elif char in (ord('j'), curses.KEY_DOWN):
1350+
self._delay -= self._step
1351+
elif char == curses.KEY_NPAGE:
1352+
self._delay -= self._big_step
1353+
elif char == curses.KEY_PPAGE:
1354+
self._delay += self._big_step
1355+
elif char == ord('z'):
1356+
self._delay = 0
1357+
1358+
if self._delay < 0:
1359+
self._delay = 0
1360+
elif self._delay > self._limit:
1361+
self._delay = self._limit
1362+
self._win.addstr(2, len(self._text) + 4, '{:<7}'.format(self._delay), curses.color_pair(11))
1363+
self._win.refresh()
1364+
return 0, []
1365+
1366+
12331367
class PyRadioConnectionType(object):
12341368

12351369
_title = ' Connection Type '

pyradio/player.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3492,26 +3492,26 @@ class PlayerCache(object):
34923492

34933493
_data = {
34943494
'mpv': [
3495-
'--cache-secs=30',
3495+
'--cache-secs=20',
34963496
'--cache=yes',
34973497
'--cache-on-disk=yes',
34983498
'--demuxer-cache-wait=yes',
34993499
'--demuxer-readahead-secs=29',
35003500
],
35013501
'mplayer': [
3502-
'-cache=1024',
3502+
'-cache=2000',
35033503
'-cache-min=80'
35043504
],
35053505
'vlc': [
35063506
'--network-caching',
3507-
'10000'
3507+
'20'
35083508
]
35093509
}
35103510

35113511
def __init__(self, player_name, data_dir, recording):
35123512
self._player_name = player_name
35133513
self._data_file = os.path.join(data_dir, 'buffers')
3514-
self_recording = recording
3514+
self._recording = recording
35153515
self._read()
35163516

35173517
def __del__(self):
@@ -3521,7 +3521,11 @@ def __del__(self):
35213521
def cache(self):
35223522
if self._player_name == 'mpv':
35233523
self._on_disk()
3524-
return self._data[self._player_name]
3524+
if self._player_name != 'vlc':
3525+
return self._data[self._player_name]
3526+
out = self._data['vlc']
3527+
out[1] = str(int(out[1]) * 1000)
3528+
return out
35253529

35263530
@property
35273531
def delay(self):
@@ -3538,8 +3542,6 @@ def delay(self, a_delay):
35383542
x = int(a_delay)
35393543
except ValueError:
35403544
return
3541-
if self._player_name == 'vlc':
3542-
x *= 1000
35433545

35443546
if self._player_name == 'vlc':
35453547
self._data['vlc'][1] = str(x)
@@ -3582,11 +3584,11 @@ def _save(self):
35823584
self._dirty = False
35833585

35843586
def _on_disk(self):
3585-
if self._recording():
3587+
if self._recording() > 0:
35863588
self._data['mpv'][2] = '--cache-on-disk=no'
35873589
return
35883590
try:
3589-
vitr = psutil.virtual_memory()
3591+
virt = psutil.virtual_memory()
35903592
except:
35913593
self._data['mpv'][2] = '--cache-on-disk=no'
35923594
return

pyradio/radio.py

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
from .window_stack import Window_Stack
3636
from .config_window import *
3737
from .log import Log
38-
from .edit import PyRadioSearch, PyRadioEditor, PyRadioRenameFile, PyRadioConnectionType, PyRadioServerWindow
38+
from .edit import PyRadioSearch, PyRadioEditor, PyRadioRenameFile, PyRadioConnectionType, PyRadioServerWindow, PyRadioBuffering
3939
from .themes import *
4040
from .cjkwrap import cjklen, cjkcenter, cjkslices
4141
from . import player
@@ -391,6 +391,8 @@ class PyRadio(object):
391391
_remote_control_window = None
392392
_group_selection_window = None
393393

394+
_buffering_win = None # Cache editing window
395+
394396
def ll(self, msg):
395397
logger.error('DE ==========')
396398
logger.error('DE ===> {}'.format(msg))
@@ -580,6 +582,7 @@ def __init__(self, pyradio_config,
580582
self.ws.GROUP_HELP_MODE: self._show_group_help,
581583
self.ws.RECORD_WINDOW_MODE: self._show_recording_toggle_window,
582584
self.ws.WIN_VLC_NO_RECORD_MODE: self._show_win_no_record,
585+
self.ws.BUFFER_SET_MODE: self._show_buffer_set,
583586
}
584587

585588
''' list of help functions '''
@@ -914,6 +917,7 @@ def setup(self, stdscr):
914917
self.player.params = self._cnf.params[self.player.PLAYER_NAME][:]
915918
self.player.buffering_change_function = self._show_recording_status_in_header
916919
self.player.buffering_lock = self._buffering_lock
920+
self._cnf.buffering_data = []
917921
if self._request_recording:
918922
if not (platform.startswith('win') and \
919923
self.player.PLAYER_NAME == 'vlc'):
@@ -2263,6 +2267,9 @@ def stopPlayer(self,
22632267
# with self._buffering_lock:
22642268
# self._show_recording_status_in_header()
22652269

2270+
def _show_buffer_set(self):
2271+
pass
2272+
22662273
def _show_player_is_stopped(self, from_update_thread=False):
22672274
if from_update_thread:
22682275
msg_id = 2
@@ -3408,6 +3415,7 @@ def _show_extra_commands_help(self):
34083415
self.ws.previous_operation_mode == self.ws.NORMAL_MODE):
34093416
txt = '''\\ |Open previous playlist.
34103417
] |Open first opened playlist.
3418+
b |Set player |b|uffering.
34113419
l |Toggle |Open last playlist|.
34123420
m |Cahnge |m|edia player.
34133421
n |Create a |n|ew playlist.
@@ -6993,6 +7001,22 @@ def keypress(self, char):
69937001
mode_to_set=self.ws.NORMAL_MODE,
69947002
callback_function=self.refreshBody)
69957003

7004+
elif char == ord('b'):
7005+
self._update_status_bar_right(status_suffix='')
7006+
if self.ws.operation_mode == self.ws.NORMAL_MODE:
7007+
self._buffering_win = PyRadioBuffering(
7008+
parent=self.outerBodyWin,
7009+
config=self._cnf,
7010+
player=self.player,
7011+
global_functions=self._global_functions
7012+
)
7013+
self.ws.operation_mode = self.ws.BUFFER_SET_MODE
7014+
self._buffering_win.show()
7015+
else:
7016+
self._backslash_pressed = False
7017+
self._print_not_applicable()
7018+
return
7019+
69967020
else:
69977021
''' ESC or invalid char pressed - leave \ mode '''
69987022
self._update_status_bar_right(status_suffix='')
@@ -7158,6 +7182,7 @@ def keypress(self, char):
71587182
self.player.params = self._cnf.params[self.player.PLAYER_NAME][:]
71597183
self.player.buffering_change_function = self._show_recording_status_in_header
71607184
self.player.buffering_lock = self._buffering_lock
7185+
self._cnf.buffering_data = []
71617186
if not (self.player.PLAYER_NAME == 'vlc' and \
71627187
platform.startswith('win')):
71637188
self.player.recording = to_record
@@ -7279,6 +7304,21 @@ def keypress(self, char):
72797304
self.ws.close_window()
72807305
self.refreshBody()
72817306

7307+
elif self.ws.operation_mode == self.ws.BUFFER_SET_MODE:
7308+
ret, buf = self._buffering_win.keypress(char)
7309+
if ret == 0:
7310+
return
7311+
elif ret == 1:
7312+
self._cnf.buffering_data = buf[:]
7313+
if logger.isEnabledFor(logging.DEBUG):
7314+
logger.debug('buffering data = {}'.format(buf))
7315+
self._buffering_win.save()
7316+
self._buffering_win = None
7317+
elif ret == -1:
7318+
self._buffering_win = None
7319+
self.ws.close_window()
7320+
self.refreshBody()
7321+
72827322
elif self.ws.operation_mode == self.ws.CONFIG_MODE and \
72837323
char not in self._chars_to_bypass:
72847324
if char in (ord('r'), ord('d')):

pyradio/window_stack.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class Window_Stack_Constants(object):
5959
SCHEDULE_PLAYER_STOP_MODE = 75
6060
REMOVE_GROUP_MODE = 76
6161
RECORD_WINDOW_MODE = 77
62+
BUFFER_SET_MODE = 78
6263
MAIN_HELP_MODE = 100
6364
MAIN_HELP_MODE_PAGE_2 = 101
6465
MAIN_HELP_MODE_PAGE_3 = 102
@@ -283,7 +284,8 @@ class Window_Stack_Constants(object):
283284
GROUP_SEARCH_MODE: 'GROUP_SEARCH_MODE',
284285
GROUP_HELP_MODE: 'GROUP_HELP_MODE',
285286
RECORD_WINDOW_MODE: 'RECORD_WINDOW_MODE',
286-
WIN_VLC_NO_RECORD_MODE: 'WIN_VLC_NO_RECORD_MODE' ,
287+
WIN_VLC_NO_RECORD_MODE: 'WIN_VLC_NO_RECORD_MODE',
288+
BUFFER_SET_MODE: 'BUFFER_SET_MODE',
287289
}
288290

289291
''' When PASSIVE_WINDOWS target is one of them,

0 commit comments

Comments
 (0)