From 48dc481f268e1ecdcd8d5e0126df553781e40a78 Mon Sep 17 00:00:00 2001 From: Dirk Alders Date: Thu, 12 Sep 2024 20:21:16 +0200 Subject: [PATCH] Initial console based pyrip implementation --- .gitmodules | 12 ++ .vscode/launch.json | 16 ++ .vscode/settings.json | 14 ++ config.py | 1 + fstools | 1 + icon.xpm | 295 ++++++++++++++++++++++++++++++++ media | 1 + pyrip.py | 105 ++++++++++++ pyrip.wxg | 384 ++++++++++++++++++++++++++++++++++++++++++ report | 1 + task | 1 + 11 files changed, 831 insertions(+) create mode 100644 .gitmodules create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 config.py create mode 160000 fstools create mode 100644 icon.xpm create mode 160000 media create mode 100644 pyrip.py create mode 100644 pyrip.wxg create mode 160000 report create mode 160000 task diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..25998f4 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,12 @@ +[submodule "fstools"] + path = fstools + url = https://git.mount-mockery.de/pylib/fstools.git +[submodule "report"] + path = report + url = https://git.mount-mockery.de/pylib/report.git +[submodule "task"] + path = task + url = https://git.mount-mockery.de/pylib/task.git +[submodule "media"] + path = media + url = https://git.mount-mockery.de/pylib/media.git diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..8d48992 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Verwendet IntelliSense zum Ermitteln möglicher Attribute. + // Zeigen Sie auf vorhandene Attribute, um die zugehörigen Beschreibungen anzuzeigen. + // Weitere Informationen finden Sie unter https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Main File execution", + "type": "debugpy", + "request": "launch", + "program": "${workspaceFolder}/pyrip.py", + "console": "integratedTerminal", + "justMyCode": true + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..ee25f90 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,14 @@ +{ + "python.defaultInterpreterPath": "./venv/bin/python", + "autopep8.args": ["--max-line-length=150"], + "[python]": { + "python.formatting.provider": "none", + "editor.defaultFormatter": "ms-python.autopep8", + "editor.formatOnSave": true + }, + "editor.fontSize": 14, + "emmet.includeLanguages": { "django-html": "html" }, + "python.testing.pytestArgs": ["-v", "--cov", "--cov-report=xml", "__test__"], + "python.testing.unittestEnabled": false, + "python.testing.pytestEnabled": true +} diff --git a/config.py b/config.py new file mode 100644 index 0000000..05e5497 --- /dev/null +++ b/config.py @@ -0,0 +1 @@ +APP_NAME = 'pyrip' diff --git a/fstools b/fstools new file mode 160000 index 0000000..c10e879 --- /dev/null +++ b/fstools @@ -0,0 +1 @@ +Subproject commit c10e8792abb05671dab6de51cdadda3bf8ead50f diff --git a/icon.xpm b/icon.xpm new file mode 100644 index 0000000..0d26223 --- /dev/null +++ b/icon.xpm @@ -0,0 +1,295 @@ +/* XPM */ +static char *sound-juicer[] = { +/* columns rows colors chars-per-pixel */ +"32 32 257 2", +" c #79604B", +". c #7E6754", +"X c #7F756A", +"o c #7D7D7B", +"O c #974503", +"+ c #9B4701", +"@ c #9E4803", +"# c #9A4B0D", +"$ c #9C571D", +"% c #875937", +"& c #925B2E", +"* c #9F683C", +"= c #A34B02", +"- c #AA4D02", +"; c #A6520B", +": c #A4591D", +"> c #AF5D1A", +", c #BA5300", +"< c #BC5807", +"1 c #BC5B0C", +"2 c #B35912", +"3 c #B55F1B", +"4 c #BC5D10", +"5 c #AC5F21", +"6 c #BF6311", +"7 c #B9621C", +"8 c #A4622B", +"9 c #AB6025", +"0 c #AA652C", +"q c #AD682E", +"w c #A36635", +"e c #A0673A", +"r c #A1693D", +"t c #A86733", +"y c #AE6A33", +"u c #A96D3C", +"i c #B36222", +"p c #B46628", +"a c #B2692D", +"s c #BA6A2A", +"d c #B16C33", +"f c #B5733C", +"g c #9C6A43", +"h c #917B69", +"j c #9B7E67", +"k c #A87144", +"l c #AC7950", +"z c #B37544", +"x c #BE7C49", +"c c #C35700", +"v c #C55800", +"b c #C85E01", +"n c #C06012", +"m c #C36619", +"M c #C46A1F", +"N c #D46905", +"B c #D66D0D", +"V c #DE6F06", +"C c #D77114", +"Z c #D8761B", +"A c #C67026", +"S c #C7732D", +"D c #C87228", +"F c #C0773B", +"G c #CB7931", +"H c #D77928", +"J c #DA7A22", +"K c #DB7E29", +"L c #E46D02", +"P c #E67104", +"I c #EF7500", +"U c #EE7F16", +"Y c #F47800", +"T c #F47D0A", +"R c #C17B43", +"E c #AC815E", +"W c #B3835C", +"Q c #BB885E", +"! c #AB8F78", +"~ c #AE917B", +"^ c #B1957E", +"/ c #BD9A7D", +"( c #CF833E", +") c #D0823C", +"_ c #DC8433", +"` c #DE8B3E", +"' c #F48214", +"] c #F18319", +"[ c #F5881F", +"{ c #EA8E3B", +"} c #F58A22", +"| c #F99A25", +" . c #F99C29", +".. c #FAA12E", +"X. c #FAA432", +"o. c #FBA739", +"O. c #FAA835", +"+. c #FBAC3B", +"@. c #C6834E", +"#. c #C28856", +"$. c #CA8D57", +"%. c #D58C4A", +"&. c #DF8F45", +"*. c #DD944D", +"=. c #D69459", +"-. c #C39673", +";. c #C79E7C", +":. c #CF9C73", +">. c #DB9F69", +",. c #DFA36A", +"<. c #D4A074", +"1. c #E1944D", +"2. c #E29753", +"3. c #E39B5A", +"4. c #F79C44", +"5. c #E19B63", +"6. c #E5A45D", +"7. c #FBAE42", +"8. c #FBAE4B", +"9. c #F5A353", +"0. c #FBB144", +"q. c #FBB44C", +"w. c #FFBF40", +"e. c #F6B153", +"r. c #F4B75C", +"t. c #FBB452", +"y. c #FCB854", +"u. c #FCBA5B", +"i. c #E5A362", +"p. c #E5AA6D", +"a. c #E8A566", +"s. c #E3AC7A", +"d. c #E5B17F", +"f. c #E3B87C", +"g. c #E8B677", +"h. c #E8B07D", +"j. c #EEBF7B", +"k. c #F5AB64", +"l. c #F0AD6F", +"z. c #F4B06F", +"x. c #F0B969", +"c. c #F9B069", +"v. c #FABC63", +"b. c #FBBF68", +"n. c #F0BB72", +"m. c #F1BA78", +"M. c yellow", +"N. c #EFC17D", +"B. c #FBC06D", +"V. c #F4C07C", +"C. c #FCC372", +"Z. c #FCC57B", +"A. c #808080", +"S. c #8A8B87", +"D. c #8C8D8A", +"F. c #929292", +"G. c #9B9793", +"H. c #9A9A9A", +"J. c #9EA19D", +"K. c #AE9886", +"L. c #A99D94", +"P. c #B59982", +"I. c #B99C86", +"U. c #BC9F89", +"Y. c #BDA28B", +"T. c #BAA492", +"R. c #BDAA9B", +"E. c #A3A3A3", +"W. c #A6ABA6", +"Q. c #AAACA7", +"!. c #ACACAB", +"~. c #B6B6AD", +"^. c #BEB5AE", +"/. c #B3B3B3", +"(. c #BBBBBB", +"). c #D9AB85", +"_. c #D9B98B", +"`. c #D5BC97", +"'. c #D8BD96", +"]. c #C7BBA4", +"[. c #CDBDA0", +"{. c #CCBAAC", +"}. c #C0BBB8", +"|. c #E6B68A", +" X c #E7BA88", +".X c #E9B680", +"XX c #EAB88F", +"oX c #F5BC87", +"OX c #CDC4BA", +"+X c #DAC6AA", +"@X c #F5CB8D", +"#X c #FAC28B", +"$X c #FDCB82", +"%X c #FCCE8C", +"&X c #F5C395", +"*X c #FBCB9C", +"=X c #FDD497", +"-X c #FDD59A", +";X c #E0CDBE", +":X c #EFD0A6", +">X c #EFD4AB", +",X c #E3D1B5", +" YXYXYXYXYXYXYX", +"YXYXYXYXg p G ZXUXSX-XKX6X+.O.+.O.+.C.UXUXIXCXx i 8 YXYXYXYXYXYX", +"YXYXYX8 p %.IXIX%X+.O.q.$XX...O. .+.8.8XMXeXIXUX:.3 2 YXYXYXYXYX", +"YXYXYXd D SXKXu.+.X.+. .-X .X.o. .+.8.wXt.y.v.HXIX@.a YXYXYXYXYX", +"YXYXw 1 9XUXZ.O.O.X... .6Xo.+.0.o.q.7X$Xb.b.b.C.KXPXs t YXYXYXYX", +"YXYX7 6.HXSX+.+.| +...+.v.b.q.t.e.V.NX@X@X@X@X@X4XPXuXl YXYXYXYX", +"YXt M 9XIXIX0.X.0.o.q.8.t.eXv.n.f.cX1X>X5X5X5X:X:XHXDX).h YXYXYX", +"YXa p.UXAX9X9XZ.X.t.t.v.b.ZXg._.+XCX.UXq.+... ...+.t.N.VXPXYXYXYXYXJ.E././.rXU.a.Y T l.f (.A.YXYX", +"5 .XUX+.X...X.+.q.x._.[.iXYXYXw.YXD.S.(./.rXU.5.Y Y } =.T.A.YXYX", +"5 ,.UXr.+.O.O.+.r.f.`.aXW.YXM.YXYXo o /./.}.I.3.n N ] 9.y A.YXYX", +"> ) UX-X+.O.+.q.j.hXjXdXQ.YXYXYX+ . F.!.!.rXI.2.5 I.7 U R & YXYX", +"> A BXUX8XB.4XnXcXOXtXdX!.S.o % # (.Q.!.(.P.1.y dX}.9 P ; O YX", +", 1 %XHXUXNX>X2XsXfXfXdXdX/.h k ).K.W.W./.rXP.&.0 yXiXiX8 @ + @ ", +"YX7 XIXKXqXhXvXFXDXdXdXyX}.u 0X0Xw E.W.(.rXK.&.y yXyXyXF.O O O ", +"YX5 f UXGXmXGXLXFXFXDXdXyX(.u XX5.R L./.(.(.P.K 0 yXyX/.A.YXYXYX", +"YX, 1 VXUXJXPXLXLXFXFXDXdXyXd } I H k (.(.(.P.K 0 tXyXF.YXYXYXYX", +"YXYX9 -.UXUXPXLXLXFXFXDXfXdXy L L c l (./.(.~ K 0 yXE.A.YXYXYXYX", +"YXYXc E uXUXUXPXLXLXFXDXfXfX{.u 5 u (.(.(./.! J 0 /.F.YXYXYXYXYX", +"YXYXYX7 G.FXPXUXLXLXFXFXDXfXfXdXyXyXrXrX(.(.! Z 8 F.A.YXYXYXYXYX", +"YXYXYXYXA.H.dXUXUXLXLXFXDXDXfXfXdXyXyXtXrX(.^ C $ A.YXYXYXYXYXYX", +"YXYXYXYXYXA.H./.LXPXLXFXDXDXDXfXfXdXtXR.R.}.j B = YXYXYXYXYXYXYX", +"YXYXYXYXYXYXYXA.H.rXFXLXFXFXDXfXQ Q <.|.s.$.p V = YXYXYXYXYXYXYX", +"YXYXYXYXYXYXYXYXYXA.H.J./.(.tXW h.*X*X#Xc.4.} ] = YXYXYXYXYXYXYX", +"YXYXYXYXYXYXYXYXYXYXYXYXA.A.A.$ *.oX*X&Xl.{ L b = YXYXYXYXYXYXYX", +"YXYXYXYXYXYXYXYXYXYXYXYXYXYXYXO @ = - , , - = + O YXYXYXYXYXYXYX", +"YXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXYXO O O O YXYXYXYXYXYXYXYXYXYX" +}; diff --git a/media b/media new file mode 160000 index 0000000..402e837 --- /dev/null +++ b/media @@ -0,0 +1 @@ +Subproject commit 402e8375511470c61021956edad72e1080f51c8e diff --git a/pyrip.py b/pyrip.py new file mode 100644 index 0000000..a20cb44 --- /dev/null +++ b/pyrip.py @@ -0,0 +1,105 @@ +import argparse +import config +import logging +import media +import report +import sys +import os +import fstools + +try: + from config import APP_NAME as ROOT_LOGGER_NAME +except ImportError: + ROOT_LOGGER_NAME = 'root' +logger = logging.getLogger(ROOT_LOGGER_NAME).getChild(__name__) + + +def progress_callback_rip(p: float): + bar_length = 40 + progress = int(bar_length * p) + out = "\rRipping.... - [ " + out += "*" * progress + out += "-" * (bar_length - progress) + out += " ] %5.1f%%" % (p * 100) + sys.stdout.write(out) + + +def progress_callback_enc(p: float): + bar_length = 40 + progress = int(bar_length * p) + out = "\rEncoding... - [ " + out += "*" * progress + out += "-" * (bar_length - progress) + out += " ] %5.1f%%" % (p * 100) + sys.stdout.write(out) + + +def cddb_user_callback(what: int, info: dict): + if what == media.CALLBACK_CDDB_CHOICE: + keys = tuple(info.keys()) + print("Multiple cddb entries detected:") + print("-------------------------------") + for i in range(0, len(keys)): + print("%2d. %s" % (i + 1, info[keys[i]])) + n = None + while not n: + fb = input("Choose: ") + try: + fb = int(fb) + except ValueError: + n = None + else: + if fb > 0 and fb <= len(keys): + n = fb + if n is None: + print("Use a choice from above!") + print() + return keys[n - 1] + elif what == media.CALLBACK_MAN_INPUT: + print("No cddb entries detected:") + print("-------------------------") + for key in info: + info[key] = input(key[0].upper() + key[1:] + ": ") + return info + + +def main(**kwargs): + disc_data = media.get_media_data(media.get_disc_device(), cddb_user_callback) + + if disc_data is None: + logger.error("Could not reading disc_data") + sys.exit(1) + print("Found Disc:") + print("===========") + print() + print(disc_data[media.common.KEY_ARTIST], "-", disc_data[media.common.KEY_ALBUM]) + print("-" * (len(disc_data[media.common.KEY_ARTIST]) + len(disc_data[media.common.KEY_ALBUM]) + 3)) + for track_info in disc_data["tracks"]: + i = track_info[media.common.KEY_TRACK] + print("%2d. %s" % (i, track_info[media.common.KEY_TITLE])) + wavfile = media.track_to_targetpath(kwargs.get("basepath"), track_info, 'wav') + try: + fstools.mkdir(os.path.dirname(wavfile)) + except PermissionError: + logger.exception("Unable to create ripping target path: %s", os.path.dirname(wavfile)) + sys.exit(1) + rv = media.disc_track_rip(i, wavfile, progress_callback_rip) + if rv == 0: + print() + rv = media.wav_to_mp3(wavfile, kwargs.get("basepath"), track_info, progress_callback_enc) + print() + os.remove(wavfile) + if rv != 0: + logger.error("Error while ripping or encoding...") + + +if __name__ == "__main__": + default_baspath = os.path.join(os.getenv("HOME"), "rip") + parser = argparse.ArgumentParser(description='Description') + parser.add_argument('-v', '--verbose', help='Description for foo argument', action='store_true') + parser.add_argument('-b', '--basepath', help=f'The rip and encode basepath (default is {default_baspath})', default=default_baspath) + args = vars(parser.parse_args()) + + report.stdoutLoggingConfigure(log_name_lvl=((config.APP_NAME, logging.DEBUG if args.get('verbose') else logging.ERROR),)) + + main(**args) diff --git a/pyrip.wxg b/pyrip.wxg new file mode 100644 index 0000000..b60ef78 --- /dev/null +++ b/pyrip.wxg @@ -0,0 +1,384 @@ + + + + + + PyRip + 1033, 761 + + wxVERTICAL + + wxEXPAND + 0 + + + + Rip + Config + + + + + wxVERTICAL + + wxEXPAND + 0 + + + wxHORIZONTAL + + wxEXPAND + 0 + + + + 0 + + + + evt_tracklist + + + + + wxEXPAND + 0 + + + wxVERTICAL + + wxEXPAND + 0 + + + wxVERTICAL + + + wxEXPAND + 0 + + + + evt_artist_changed + + + + + + + wxEXPAND + 0 + + + wxVERTICAL + + + wxEXPAND + 0 + + + + evt_album_changed + + + + + + + wxEXPAND + 0 + + + wxVERTICAL + + + wxEXPAND + 0 + + + + evt_year_changed + + + + + + + wxEXPAND + 0 + + + wxVERTICAL + + + wxEXPAND + 0 + + + + evt_genre_changed + + + + + + + wxEXPAND + 0 + + + wxVERTICAL + + + wxEXPAND + 0 + + + + evt_title_changed + + + + + + + wxEXPAND + 0 + + + wxVERTICAL + + + wxEXPAND + 0 + + + + evt_track_no_changed + + + + + + + wxEXPAND + 0 + + + wxVERTICAL + + + wxEXPAND + 0 + + + + evt_comment_changed + + + + + + + 0 + + + 20 + 20 + + + + wxEXPAND + 0 + + + wxVERTICAL + + + wxEXPAND + 0 + + + 1000 + + + + + + wxEXPAND + 0 + + + wxVERTICAL + + + wxEXPAND + 0 + + + 1000 + + + + + + wxEXPAND + 0 + + + wxVERTICAL + + + wxEXPAND + 0 + + + 1000 + + + + + + + + + + 0 + + + wxHORIZONTAL + + 0 + + + 20 + 20 + + + + 0 + + + + + evt_rip + + + + + 0 + + + 20 + 20 + + + + 0 + + + + + evt_new_disc + + + + + 0 + + + 20 + 20 + + + + + + + + + + wxVERTICAL + + wxEXPAND + 0 + + + wxVERTICAL + + + wxEXPAND + 0 + + + + evt_target_path_changed + + + + + + + wxEXPAND + 0 + + + wxVERTICAL + + + wxEXPAND + 0 + + + + evt_device_changed + + + + + + + wxEXPAND + 0 + + + wxVERTICAL + + + wxEXPAND + 0 + + + + evt_default_comment_changed + + + + + + + wxEXPAND + 0 + + + wxVERTICAL + + + wxEXPAND + 0 + + + + evt_track_list_string_changed + + + + + + + + + + + + diff --git a/report b/report new file mode 160000 index 0000000..7003c13 --- /dev/null +++ b/report @@ -0,0 +1 @@ +Subproject commit 7003c13ef8c7e7c3a55a545cbbad4039cc024a9f diff --git a/task b/task new file mode 160000 index 0000000..7583bb5 --- /dev/null +++ b/task @@ -0,0 +1 @@ +Subproject commit 7583bb5f3bd2420c901374ba95b678af6ce88433