@@ -88,6 +88,37 @@ non_utf8 = mswin or not "UTF-8" in os.environ.get("LANG", "")
8888member_var = lambda x : not (x .startswith ("__" ) or callable (x ))
8989locale .setlocale (locale .LC_ALL , "" ) # for date formatting
9090
91+ # A: 175.6 (02:55.5) of 258.8 (04:18.7) 0.0%
92+ re_mplayer_audio_status = re .compile (r"""
93+ A:\s*(?:[0-9.]+)?
94+ \s+\(
95+ (?:(?P<elapsed_h>\d+):)??
96+ (?:(?P<elapsed_m>\d+):)?
97+ (?P<elapsed_s>\d+)
98+ (?:\.[0-9]+)?
99+ \)\s+of\s+
100+ (?:[0-9.]+)?
101+ \s+\(
102+ (?:(?P<total_h>\d+):)??
103+ (?:(?P<total_m>\d+):)?
104+ (?P<total_s>\d+)
105+ (?:\.[0-9]+)?
106+ \)
107+ """ , re .VERBOSE )
108+
109+ # A: 00:00:07 / 00:05:37 (2%) Cache: 46%
110+ # AV: 00:00:03 / 00:03:30 (1%) A-V: -0.000 Cache: 14%
111+ re_mpv_status = re .compile (r"""
112+ AV?:\s*
113+ (?P<elapsed_h>\d+):
114+ (?P<elapsed_m>\d+):
115+ (?P<elapsed_s>\d+)
116+ \s+/\s+
117+ (?P<total_h>\d+):
118+ (?P<total_m>\d+):
119+ (?P<total_s>\d+)
120+ """ , re .VERBOSE )
121+
91122
92123def non_utf8_encode (txt ):
93124 """ Encoding for non UTF8 environments. """
@@ -1236,45 +1267,36 @@ def playsong(song, failcount=0, override=False):
12361267 return
12371268
12381269 cmd , songdata = generate_real_playerargs (song , override )
1239- stdout = stderr = None
12401270 now = time .time ()
12411271 songdata = "%s; %s; %s Mb" % songdata
12421272 writestatus (songdata )
12431273
1244- with open ( os . devnull , "w" ) as fnull :
1274+ for quiet in ( '-really-quiet' , '--really-quiet' ) :
12451275
1246- if "mpv" in Config . PLAYER or "mplayer" in Config . PLAYER :
1247- stderr = fnull
1276+ try :
1277+ cmd . remove ( quiet )
12481278
1249- if mswin :
1250- stdout = stderr = fnull
1279+ except ValueError :
1280+ pass
12511281
1252- for quiet in ('-really-quiet' , '--really-quiet' ):
1282+ logging .info ("playing %s (%s)" , song .title , failcount )
1283+ dbg ("calling %s" , cmd )
12531284
1254- try :
1255- cmd .remove (quiet )
1256-
1257- except ValueError :
1258- pass
1285+ try :
1286+ p = subprocess .Popen (cmd , shell = False , stdout = subprocess .PIPE ,
1287+ stderr = subprocess .STDOUT , bufsize = 1 )
1288+ mplayer_status (p , songdata + ";" )
12591289
1260- logging .info ("playing %s (%s)" , song .title , failcount )
1261- dbg ("calling %s" , cmd )
1290+ except OSError :
1291+ g .message = F ('no player' ) % Config .PLAYER
1292+ return
12621293
1294+ finally :
12631295 try :
1264- p = subprocess .Popen (cmd , shell = False , stdout = subprocess .PIPE ,
1265- stderr = stderr , bufsize = 1 )
1266- mplayer_status (p , songdata + ";" )
1267-
1268- except OSError :
1269- g .message = F ('no player' ) % Config .PLAYER
1270- return
1296+ p .terminate () # make sure to kill mplayer if mpsyt crashes
12711297
1272- finally :
1273- try :
1274- p .terminate () # make sure to kill mplayer if mpsyt crashes
1275-
1276- except :
1277- pass
1298+ except :
1299+ pass
12781300
12791301 fin = time .time ()
12801302 failed = fin - now < 1 and song .length > 1
@@ -1293,19 +1315,6 @@ def playsong(song, failcount=0, override=False):
12931315
12941316
12951317def mplayer_status (popen_object , prefix = "" ):
1296-
1297- # A: 175.6 (02:55.5) of 258.8 (04:18.7) 0.0%
1298- re_mplayer_audio_status = re .compile (r"""
1299- A:\s*(?P<sec>[0-9.]+)?
1300- \s+
1301- \((?P<elapsed_h>\d+:)??
1302- (?P<elapsed_m>\d+:)?
1303- (?P<elapsed_s>\d+)
1304- (?P<elapsed_ms>\.[0-9]+)?\)
1305- \s+of\s+
1306- (?P<sec_total>[0-9.]+)?
1307- """ , re .VERBOSE )
1308-
13091318 buff = ''
13101319 last_displayed_line = None
13111320
@@ -1314,12 +1323,14 @@ def mplayer_status(popen_object, prefix=""):
13141323
13151324 if char in '\r \n ' :
13161325 m = re_mplayer_audio_status .match (buff )
1326+ if not m :
1327+ m = re_mpv_status .match (buff )
13171328
13181329 if m :
13191330 line = make_status_line (m )
13201331
13211332 if line != last_displayed_line :
1322- writestatus (prefix + line )
1333+ writestatus (prefix + ( " " if prefix else "" ) + line )
13231334 last_displayed_line = line
13241335
13251336 buff = ''
@@ -1328,34 +1339,62 @@ def mplayer_status(popen_object, prefix=""):
13281339 buff += char
13291340
13301341
1331- def make_status_line (match_object ):
1332-
1342+ def make_status_line (match_object , progress_bar_size = 30 ):
1343+ """
1344+ Assume match_object have groups:
1345+ - elapsed_h
1346+ - elapsed_m
1347+ - elapsed_s
1348+ - total_h
1349+ - total_m
1350+ - total_s
1351+ which hold either an empty string or an integer value as a string
1352+
1353+ >>> make_status_line(re_mplayer_audio_status.match("A: 0.0 (0.0) of 258.8 (04:18.7) 0.0%"))
1354+ '00:00:00 (0%) [>.............................]'
1355+ >>> make_status_line(re_mplayer_audio_status.match("A: 175.6 (02:55.5) of 258.8 (04:18.7) 0.0%"))
1356+ '00:02:55 (68%) [====================>.........]'
1357+ >>> make_status_line(re_mplayer_audio_status.match("A: 258.8 (04:18.7) of 258.8 (04:18.7) 0.0%"))
1358+ '00:04:18 (100%) [=============================>]'
1359+
1360+ >>> make_status_line(re_mpv_status.match("A: 00:00:00 / 00:05:37 (0%) Cache: 46%"))
1361+ '00:00:00 (0%) [>.............................]'
1362+ >>> make_status_line(re_mpv_status.match("A: 00:02:32 / 00:05:37 (45%) Cache: 60%"))
1363+ '00:02:32 (45%) [=============>................]'
1364+ >>> make_status_line(re_mpv_status.match("A: 00:05:37 / 00:05:37 (100%) Cache: 100%"))
1365+ '00:05:37 (100%) [=============================>]'
1366+
1367+ >>> make_status_line(re_mpv_status.match("AV: 00:00:00 / 00:03:30 (0%) A-V: -0.000 Cache: 14%"))
1368+ '00:00:00 (0%) [>.............................]'
1369+ >>> make_status_line(re_mpv_status.match("AV: 00:02:32 / 00:03:30 (73%) A-V: -0.000 Cache: 14%"))
1370+ '00:02:32 (72%) [=====================>........]'
1371+ >>> make_status_line(re_mpv_status.match("AV: 00:03:30 / 00:03:30 (100%) A-V: -0.000 Cache: 100%"))
1372+ '00:03:30 (100%) [=============================>]'
1373+ """
13331374 try :
1334- current = float (match_object .group ('sec' ))
1335-
1375+ elapsed_h = int (match_object .group ('elapsed_h' ) or '0' )
1376+ elapsed_m = int (match_object .group ('elapsed_m' ) or '0' )
1377+ elapsed_s = int (match_object .group ('elapsed_s' ) or '0' )
1378+ total_h = int (match_object .group ('total_h' ) or '0' )
1379+ total_m = int (match_object .group ('total_m' ) or '0' )
1380+ total_s = int (match_object .group ('total_s' ) or '0' )
13361381 except ValueError :
1337- current = 0.0
1382+ return ""
13381383
1339- try :
1340- total = float (match_object .group ('sec_total' ))
1341-
1342- except ValueError :
1343- total = 0.0
1384+ current_sec = elapsed_h * 60 * 60 + elapsed_m * 60 + elapsed_s
1385+ total_sec = total_h * 60 * 60 + total_m * 60 + total_s
13441386
13451387 try :
1346- pct = (current / total * 100 )
1388+ pct = (float ( current_sec ) / total_sec * 100 )
13471389
13481390 except ZeroDivisionError :
13491391 pct = 0
13501392
1351- status_line = " %s%s%s %s" % (
1352- match_object .group ('elapsed_h' ) or '' ,
1353- match_object .group ('elapsed_m' ) or '00:' ,
1354- match_object .group ('elapsed_s' ),
1393+ status_line = "%02i:%02i:%02i %s" % (
1394+ elapsed_h , elapsed_m , elapsed_s ,
13551395 ("(%.0f%%)" % pct ).ljust (6 )
13561396 )
13571397
1358- progress_bar_size = 30
13591398 progress = int (ceil (pct / 100 * progress_bar_size ))
13601399 status_line += " [%s]" % ("=" * (progress - 1 ) + ">" ).ljust (progress_bar_size , '.' )
13611400
0 commit comments