diff -urN v9/gui.py v10/gui.py --- v9/gui.py 2020-01-27 21:45:06.000000000 +0900 +++ v10/gui.py 1970-01-01 09:00:00.000000000 +0900 @@ -1,226 +0,0 @@ -#!/usr/bin/env python - -import sys -import threading -from decimal import Decimal -import wx -import thr -import io_ut -import dbg - -def wrap( lsts, border=4 ): - vsz = wx.BoxSizer(wx.VERTICAL) - for lst in lsts: - hsz = wx.BoxSizer(wx.HORIZONTAL) - for o in lst: - flag = wx.LEFT | ( wx.RIGHT if o == lst[-1] else 0 ) - flag |= wx.ALIGN_CENTER_VERTICAL - hsz.Add(o, 0, flag, border) - flag = wx.TOP | ( wx.BOTTOM if lst == lsts[-1] else 0 ) - vsz.Add( hsz, 0, flag, border ) - return vsz - -def set_min_w(o, w): - o.SetMinSize((w, -1)) - -cls_evt_dic = { - wx.Button: wx.EVT_BUTTON, - wx.ToggleButton: wx.EVT_TOGGLEBUTTON, - wx.CheckBox: wx.EVT_CHECKBOX, - wx.Choice: wx.EVT_CHOICE, -} - -def init(app, title): - rdr = io_ut.reader_new( sys.stdin, 1, no_buf=True ) - - lock = threading.Lock() - - def comm(cmd, rep_func=None): - lock.acquire() - if cmd: - dbg.out(cmd) - rep = None - if rep_func: - while rep == None: - rep = rep_func() - if rep == '': - break - lock.release() - return rep - - while True: - s = comm('', rdr.readline) - if s == 'ready\n': - break - if not s: - sys.exit(1) - - frame = wx.Frame(None, wx.ID_ANY, title) - - obj_cls_dic = {} - def wx_new(cls, *args, **kwds): - (k, w) = ('min_w', -1) - if k in kwds: - w = kwds.pop(k) - o = cls( frame, wx.ID_ANY, *args, **kwds ) - if w != -1: - set_min_w(o, w) - obj_cls_dic[o] = cls - return o - - def bind_o(o, hdl): - cls = obj_cls_dic.get(o) - evt = cls_evt_dic.get(cls) - if evt: - frame.Bind(evt, hdl, o) - - def bind_objs(objs, hdl): - for o in objs: - bind_o(o, hdl) - - play_lbs = ( ' Play |>', ' Play <|', 'Pause ||' ) - btn_play = wx_new( wx.ToggleButton, play_lbs[0], min_w=104 ) - lb_pause = play_lbs[-1] - is_play = lambda : btn_play.GetValue() - - cbox_reverse = wx_new( wx.CheckBox, 'reverse' ) - is_reverse = lambda : cbox_reverse.GetValue() - - speed_lbs = ('x4', 'x2', 'x1', 'x0.5') - menu_speed = wx_new( wx.Choice, choices=speed_lbs ) - #menu_speed.SetSelection(2) - menu_speed.SetStringSelection('x1') - shifts = (2, 1, 0, -1) - get_shift = lambda : shifts[ menu_speed.GetSelection() ] - - btn_rw = wx_new( wx.Button, '<<', min_w=50 ) - btn_ff = wx_new( wx.Button, '>>', min_w=50 ) - - btn_div = wx_new( wx.Button, '', min_w=50 ) - btn_div.Enable(False) - area = wx_new( wx.StaticText, '-/-', min_w=50 ) - - def div_update(): - cmd = 'dbg.out( snd.div_join_label() )' - s = comm(cmd, rdr.readline).strip() - btn_div.SetLabel(s) - en = (s != '') - btn_div.Enable(en) - - def area_update(): - cmd = 'dbg.out("{}".format( snd.curr_area() ) )' - s = comm(cmd, rdr.readline).strip() - area.SetLabel(s) - - pos = wx_new( wx.StaticText, '-', min_w=50 ) - def pos_update(): - cmd = 'dbg.out("{}".format( snd.get_sec() ) )' - s = comm(cmd, rdr.readline).strip() - s = str( Decimal(s).quantize( Decimal('.01') ) ) - wx.CallAfter( pos.SetLabel, s ) - - btn_save = wx_new( wx.Button, 'save', min_w=50 ) - - def save(): - dlg = wx.FileDialog( frame, style=wx.FD_SAVE ) - ret = dlg.ShowModal() - dlg.Destroy() - if ret != wx.ID_OK: - return - - name = dlg.GetPath() - s = area.GetLabel() - s = s.split('/')[0] - i = ( 1 if s == '-' else int(s) ) - 1 - cmd = 'snd.save({}, "{}")'.format(i, name) - - def do_save(): - s = comm(cmd, rdr.readline) # skip 'OK' - frame.Enable(True) - - frame.Enable(False) - wx.CallAfter(do_save) - - pos_ev = threading.Event() - def th_func(): - tmout = 0.2 if is_play() else None - pos_ev.wait(tmout) - pos_ev.clear() - pos_update() - wx.CallAfter(area_update) - - th = thr.loop_new(th_func) - def th_stop(): - th.quit_ev.set() - pos_ev.set() - th.stop() - th.start() - - - def lb_update(): - lb = lb_pause if is_play() else play_lbs[ 1 if is_reverse() else 0 ] - btn_play.SetLabel(lb) - - def hdl(evt): - o = evt.GetEventObject() - if o in ( btn_play, cbox_reverse ): - lb_update() - s = '' - if o == btn_play: - s = 'snd.{}()'.format( 'start' if is_play() else 'stop' ) - elif o == cbox_reverse: - s = 'snd.reverse={}'.format( o.GetValue() ) - elif o == menu_speed: - s = 'snd.shift={}'.format( get_shift() ) - elif o == btn_div: - s = 'snd.div_join()' - elif o == btn_rw: - s = 'snd.rw()' - elif o == btn_ff: - s = 'snd.ff()' - elif o == btn_save: - save() - - if o in (cbox_reverse, menu_speed, btn_rw, btn_ff) and is_play(): - s = '\n'.join( ( 'snd.stop()', s, 'snd.start()' ) ) - if s: - comm(s) - if o in (btn_play, btn_div, btn_rw, btn_ff): - pos_ev.set() - wx.CallAfter( div_update ) - wx.CallAfter( area_update ) - - def quit_hdl(evt): - dbg.err('quit') - th_stop() - wx.Exit() - - objs = ( - btn_rw, btn_play, btn_ff, - cbox_reverse, menu_speed, - btn_div, btn_save, - ) - bind_objs(objs, hdl) - frame.Bind( wx.EVT_CLOSE, quit_hdl ) - - szr = wrap( [ - (btn_rw, btn_play, btn_ff), - (cbox_reverse, menu_speed), - (pos, btn_div, area, btn_save), - ] ) - frame.SetSizer(szr) - frame.Layout() - frame.Fit() - app.SetTopWindow(frame) - frame.Show() - -def wx_run(title=''): - class MyApp(wx.App): - def OnInit(self): - init(self, title) - return 1 - MyApp(0).MainLoop() - -if __name__ == "__main__": - wx_run('snd') -# EOF diff -urN v9/snddiv.py v10/snddiv.py --- v9/snddiv.py 2020-01-27 21:45:06.000000000 +0900 +++ v10/snddiv.py 2020-02-01 12:37:41.000000000 +0900 @@ -12,6 +12,7 @@ import thr import io_ut import dbg +import arg silent = False @@ -286,28 +287,24 @@ return empty.to_attr( e, locals() ) -def get_args(): - def get_idx_pop(av, k): - if k in av: - i = av.index(k) - av.pop(i) - return i - return -1 - - av = sys.argv[1:] - k = '-S' - sudo_passwd = '' - try: - i = get_idx_pop(av, k) - if i >= 0: - sudo_passwd = av.pop(i) - silent = ( get_idx_pop(av, '-silent') >= 0 ) - return ( av[0], sudo_passwd, silent ) - except: - dbg.err_exit( 'Usage: {} [-S sudo_passwd] [-silent] filename_mp3'.format( sys.argv[0], k ) ) - if __name__ == "__main__": - ( filename_mp3, sudo_passwd, silent ) = get_args() + a = arg.new() + if a.is_pop('-g'): + cmd1 = 'python -m snddiv_gui' + + av = a.get_av() + k = '-silent' + if k not in av: + av.append(k) + cmd2 = 'python -m snddiv ' + ' '.join(av) + cmd_ut.call_stdio_conn(cmd1, cmd2) + sys.exit(0) + + sudo_passwd = a.pop_str('-S') + silent = a.is_pop('-silent') + filename_mp3 = a.pop() + if not filename_mp3: + dbg.err_exit( 'Usage: {} [-g] [-S sudo_passwd] [-silent] filename_mp3'.format( sys.argv[0] ) ) dbg_out = lambda s, tail='\n': None if silent else dbg.out diff -urN v9/snddiv.sh v10/snddiv.sh --- v9/snddiv.sh 2020-01-27 21:45:17.000000000 +0900 +++ v10/snddiv.sh 1970-01-01 09:00:00.000000000 +0900 @@ -1,10 +0,0 @@ -#!/bin/bash - -if [ $# == 0 ]; then - echo Usage: $0 [-S sudo_pass] filename_mp3 - exit 1 -fi - -./stdio.sh ./gui.py "./snddiv.py -silent $*" - -# EOF diff -urN v9/snddiv_gui.py v10/snddiv_gui.py --- v9/snddiv_gui.py 1970-01-01 09:00:00.000000000 +0900 +++ v10/snddiv_gui.py 2020-02-01 12:37:41.000000000 +0900 @@ -0,0 +1,226 @@ +#!/usr/bin/env python + +import sys +import threading +from decimal import Decimal +import wx +import thr +import io_ut +import dbg + +def wrap( lsts, border=4 ): + vsz = wx.BoxSizer(wx.VERTICAL) + for lst in lsts: + hsz = wx.BoxSizer(wx.HORIZONTAL) + for o in lst: + flag = wx.LEFT | ( wx.RIGHT if o == lst[-1] else 0 ) + flag |= wx.ALIGN_CENTER_VERTICAL + hsz.Add(o, 0, flag, border) + flag = wx.TOP | ( wx.BOTTOM if lst == lsts[-1] else 0 ) + vsz.Add( hsz, 0, flag, border ) + return vsz + +def set_min_w(o, w): + o.SetMinSize((w, -1)) + +cls_evt_dic = { + wx.Button: wx.EVT_BUTTON, + wx.ToggleButton: wx.EVT_TOGGLEBUTTON, + wx.CheckBox: wx.EVT_CHECKBOX, + wx.Choice: wx.EVT_CHOICE, +} + +def init(app, title): + rdr = io_ut.reader_new( sys.stdin, 1, no_buf=True ) + + lock = threading.Lock() + + def comm(cmd, rep_func=None): + lock.acquire() + if cmd: + dbg.out(cmd) + rep = None + if rep_func: + while rep == None: + rep = rep_func() + if rep == '': + break + lock.release() + return rep + + while True: + s = comm('', rdr.readline) + if s == 'ready\n': + break + if not s: + sys.exit(1) + + frame = wx.Frame(None, wx.ID_ANY, title) + + obj_cls_dic = {} + def wx_new(cls, *args, **kwds): + (k, w) = ('min_w', -1) + if k in kwds: + w = kwds.pop(k) + o = cls( frame, wx.ID_ANY, *args, **kwds ) + if w != -1: + set_min_w(o, w) + obj_cls_dic[o] = cls + return o + + def bind_o(o, hdl): + cls = obj_cls_dic.get(o) + evt = cls_evt_dic.get(cls) + if evt: + frame.Bind(evt, hdl, o) + + def bind_objs(objs, hdl): + for o in objs: + bind_o(o, hdl) + + play_lbs = ( ' Play |>', ' Play <|', 'Pause ||' ) + btn_play = wx_new( wx.ToggleButton, play_lbs[0], min_w=104 ) + lb_pause = play_lbs[-1] + is_play = lambda : btn_play.GetValue() + + cbox_reverse = wx_new( wx.CheckBox, 'reverse' ) + is_reverse = lambda : cbox_reverse.GetValue() + + speed_lbs = ('x4', 'x2', 'x1', 'x0.5') + menu_speed = wx_new( wx.Choice, choices=speed_lbs ) + #menu_speed.SetSelection(2) + menu_speed.SetStringSelection('x1') + shifts = (2, 1, 0, -1) + get_shift = lambda : shifts[ menu_speed.GetSelection() ] + + btn_rw = wx_new( wx.Button, '<<', min_w=50 ) + btn_ff = wx_new( wx.Button, '>>', min_w=50 ) + + btn_div = wx_new( wx.Button, '', min_w=50 ) + btn_div.Enable(False) + area = wx_new( wx.StaticText, '-/-', min_w=50 ) + + def div_update(): + cmd = 'dbg.out( snd.div_join_label() )' + s = comm(cmd, rdr.readline).strip() + btn_div.SetLabel(s) + en = (s != '') + btn_div.Enable(en) + + def area_update(): + cmd = 'dbg.out("{}".format( snd.curr_area() ) )' + s = comm(cmd, rdr.readline).strip() + area.SetLabel(s) + + pos = wx_new( wx.StaticText, '-', min_w=50 ) + def pos_update(): + cmd = 'dbg.out("{}".format( snd.get_sec() ) )' + s = comm(cmd, rdr.readline).strip() + s = str( Decimal(s).quantize( Decimal('.01') ) ) + wx.CallAfter( pos.SetLabel, s ) + + btn_save = wx_new( wx.Button, 'save', min_w=50 ) + + def save(): + dlg = wx.FileDialog( frame, style=wx.FD_SAVE ) + ret = dlg.ShowModal() + dlg.Destroy() + if ret != wx.ID_OK: + return + + name = dlg.GetPath() + s = area.GetLabel() + s = s.split('/')[0] + i = ( 1 if s == '-' else int(s) ) - 1 + cmd = 'snd.save({}, "{}")'.format(i, name) + + def do_save(): + s = comm(cmd, rdr.readline) # skip 'OK' + frame.Enable(True) + + frame.Enable(False) + wx.CallAfter(do_save) + + pos_ev = threading.Event() + def th_func(): + tmout = 0.2 if is_play() else None + pos_ev.wait(tmout) + pos_ev.clear() + pos_update() + wx.CallAfter(area_update) + + th = thr.loop_new(th_func) + def th_stop(): + th.quit_ev.set() + pos_ev.set() + th.stop() + th.start() + + + def lb_update(): + lb = lb_pause if is_play() else play_lbs[ 1 if is_reverse() else 0 ] + btn_play.SetLabel(lb) + + def hdl(evt): + o = evt.GetEventObject() + if o in ( btn_play, cbox_reverse ): + lb_update() + s = '' + if o == btn_play: + s = 'snd.{}()'.format( 'start' if is_play() else 'stop' ) + elif o == cbox_reverse: + s = 'snd.reverse={}'.format( o.GetValue() ) + elif o == menu_speed: + s = 'snd.shift={}'.format( get_shift() ) + elif o == btn_div: + s = 'snd.div_join()' + elif o == btn_rw: + s = 'snd.rw()' + elif o == btn_ff: + s = 'snd.ff()' + elif o == btn_save: + save() + + if o in (cbox_reverse, menu_speed, btn_rw, btn_ff) and is_play(): + s = '\n'.join( ( 'snd.stop()', s, 'snd.start()' ) ) + if s: + comm(s) + if o in (btn_play, btn_div, btn_rw, btn_ff): + pos_ev.set() + wx.CallAfter( div_update ) + wx.CallAfter( area_update ) + + def quit_hdl(evt): + dbg.err('quit') + th_stop() + wx.Exit() + + objs = ( + btn_rw, btn_play, btn_ff, + cbox_reverse, menu_speed, + btn_div, btn_save, + ) + bind_objs(objs, hdl) + frame.Bind( wx.EVT_CLOSE, quit_hdl ) + + szr = wrap( [ + (btn_rw, btn_play, btn_ff), + (cbox_reverse, menu_speed), + (pos, btn_div, area, btn_save), + ] ) + frame.SetSizer(szr) + frame.Layout() + frame.Fit() + app.SetTopWindow(frame) + frame.Show() + +def wx_run(title=''): + class MyApp(wx.App): + def OnInit(self): + init(self, title) + return 1 + MyApp(0).MainLoop() + +if __name__ == "__main__": + wx_run('snd') +# EOF diff -urN v9/stdio.sh v10/stdio.sh --- v9/stdio.sh 2020-01-27 21:45:06.000000000 +0900 +++ v10/stdio.sh 1970-01-01 09:00:00.000000000 +0900 @@ -1,12 +0,0 @@ -#!/bin/bash -rm -f fifo -mkfifo fifo - -# for debug -#$1 < fifo | $2 | tee fifo - -$1 < fifo | $2 > fifo - -rm -f fifo -# EOF -