From e11e1b8f5c0aeea47d82636bc4fcca510030af2f Mon Sep 17 00:00:00 2001 From: Robert Kaye Date: Sun, 28 Jan 2024 22:57:37 +0100 Subject: [PATCH] All generated playlists can now be written to subsonic, m3u or jspf. --- lb_content_resolver/playlist.py | 9 +++++++ resolve.py | 47 ++++++++++++++++++++------------- 2 files changed, 37 insertions(+), 19 deletions(-) diff --git a/lb_content_resolver/playlist.py b/lb_content_resolver/playlist.py index 3f7b93f..c674794 100644 --- a/lb_content_resolver/playlist.py +++ b/lb_content_resolver/playlist.py @@ -18,6 +18,15 @@ def read_jspf_playlist(jspf_file): return playlist_element +def write_jspf_playlist(jspf_file, jspf): + """ + Write a JSPF playlist to disk. + """ + + with open(jspf_file, "w") as f: + f.write(json.dumps(jspf.get_jspf())) + + def write_m3u_playlist(file_name, playlist_element): """ Given a Troi playlist, write an m3u playlist to disk. diff --git a/resolve.py b/resolve.py index 7ec89b3..bfc93af 100755 --- a/resolve.py +++ b/resolve.py @@ -16,7 +16,7 @@ from lb_content_resolver.duplicates import FindDuplicates from lb_content_resolver.artist_search import LocalRecordingSearchByArtistService from lb_content_resolver.troi.periodic_jams import LocalPeriodicJams -from lb_content_resolver.playlist import read_jspf_playlist, write_m3u_playlist +from lb_content_resolver.playlist import read_jspf_playlist, write_m3u_playlist, write_jspf_playlist from lb_content_resolver.unresolved_recording import UnresolvedRecordingTracker from troi.playlist import PLAYLIST_TRACK_EXTENSION_URI @@ -29,7 +29,7 @@ DEFAULT_CHUNKSIZE = 100 -def output_playlist(db, playlist, upload_to_subsonic, save_to_playlist, dont_ask): +def output_playlist(db, playlist, upload_to_subsonic, save_to_m3u, save_to_jspf, dont_ask): try: recording = playlist.playlists[0].recordings[0] except (KeyError, IndexError): @@ -49,16 +49,22 @@ def output_playlist(db, playlist, upload_to_subsonic, save_to_playlist, dont_ask db.upload_playlist(playlist) return - if save_to_playlist: - try: - _ = recording.musicbrainz["filename"] - except KeyError: - print("Playlist does not appear to contain file paths. Can't write a local playlist.") - return - if dont_ask or ask_yes_no_question(f"Save to '{save_to_playlist}'? (Y/n)"): + try: + _ = recording.musicbrainz["filename"] + except KeyError: + print("Playlist does not appear to contain file paths. Can't write a local playlist.") + return + + if save_to_m3u: + if dont_ask or ask_yes_no_question(f"Save to '{save_to_m3u}'? (Y/n)"): print("saving playlist") - write_m3u_playlist(save_to_playlist, playlist) + write_m3u_playlist(save_to_m3u, playlist) + return + if save_to_jspf: + if dont_ask or ask_yes_no_question(f"Save to '{save_to_jspf}'? (Y/n)"): + print("saving playlist") + write_jspf_playlist(save_to_jspf, playlist) return print("Playlist displayed, but not saved. Use -p or -u options to save/upload playlists.") @@ -165,10 +171,11 @@ def subsonic(db_file): @click.option("-d", "--db_file", help="Database file for the local collection", required=False, is_flag=False) @click.option('-t', '--threshold', default=.80) @click.option('-u', '--upload-to-subsonic', required=False, is_flag=True) -@click.option('-p', '--save-to-playlist', required=False) +@click.option('-m', '--save-to-m3u', required=False) +@click.option('-j', '--save-to-jspf', required=False) @click.option('-y', '--dont-ask', required=False, is_flag=True, help="write playlist to m3u file") @click.argument('jspf_playlist') -def playlist(db_file, threshold, upload_to_subsonic, save_to_playlist, dont_ask, jspf_playlist): +def playlist(db_file, threshold, upload_to_subsonic, save_to_m3u, save_to_jspf, dont_ask, jspf_playlist): """ Resolve a JSPF file with MusicBrainz recording MBIDs to files in the local collection""" db_file = db_file_check(db_file) db = SubsonicDatabase(db_file, config) @@ -176,18 +183,19 @@ def playlist(db_file, threshold, upload_to_subsonic, save_to_playlist, dont_ask, lbrl = ListenBrainzRadioLocal() playlist = read_jspf_playlist(jspf_playlist) lbrl.resolve_playlist(threshold, playlist) - output_playlist(db, playlist, upload_to_subsonic, save_to_playlist, dont_ask) + output_playlist(db, playlist, upload_to_subsonic, save_to_m3u, save_to_jspf, dont_ask) @click.command() @click.option("-d", "--db_file", help="Database file for the local collection", required=False, is_flag=False) @click.option('-t', '--threshold', default=.80) @click.option('-u', '--upload-to-subsonic', required=False, is_flag=True) -@click.option('-p', '--save-to-playlist', required=False) +@click.option('-m', '--save-to-m3u', required=False) +@click.option('-j', '--save-to-jspf', required=False) @click.option('-y', '--dont-ask', required=False, is_flag=True, help="write playlist to m3u file") @click.argument('mode') @click.argument('prompt') -def lb_radio(db_file, threshold, upload_to_subsonic, save_to_playlist, dont_ask, mode, prompt): +def lb_radio(db_file, threshold, upload_to_subsonic, save_to_m3u, save_to_jspf, dont_ask, mode, prompt): """Use the ListenBrainz Radio engine to create a playlist from a prompt, using a local music collection""" db_file = db_file_check(db_file) db = SubsonicDatabase(db_file, config) @@ -200,17 +208,18 @@ def lb_radio(db_file, threshold, upload_to_subsonic, save_to_playlist, dont_ask, db.metadata_sanity_check(include_subsonic=upload_to_subsonic) return - output_playlist(db, playlist, upload_to_subsonic, save_to_playlist, dont_ask) + output_playlist(db, playlist, upload_to_subsonic, save_to_m3u, save_to_jspf, dont_ask) @click.command() @click.option("-d", "--db_file", help="Database file for the local collection", required=False, is_flag=False) @click.option('-t', '--threshold', default=.80) @click.option('-u', '--upload-to-subsonic', required=False, is_flag=True, default=False) -@click.option('-p', '--save-to-playlist', required=False) +@click.option('-m', '--save-to-m3u', required=False) +@click.option('-j', '--save-to-jspf', required=False) @click.option('-y', '--dont-ask', required=False, is_flag=True, help="write playlist to m3u file") @click.argument('user_name') -def periodic_jams(db_file, threshold, upload_to_subsonic, save_to_playlist, dont_ask, user_name): +def periodic_jams(db_file, threshold, upload_to_subsonic, save_to_m3u, save_to_jspf, dont_ask, user_name): "Generate a periodic jams playlist" db_file = db_file_check(db_file) db = SubsonicDatabase(db_file, config) @@ -224,7 +233,7 @@ def periodic_jams(db_file, threshold, upload_to_subsonic, save_to_playlist, dont db.metadata_sanity_check(include_subsonic=upload_to_subsonic) return - output_playlist(db, playlist, upload_to_subsonic, save_to_playlist, dont_ask) + output_playlist(db, playlist, upload_to_subsonic, save_to_m3u, save_to_jspf, dont_ask) @click.command()