|
31 | 31 | # main-function |
32 | 32 | if __name__ == '__main__': |
33 | 33 | # verify that the Pulseaudio and the parec-command is installed on this system |
34 | | - if subprocess.Popen("parec --help && pacmd --help", stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, shell=True).wait() != 0: |
35 | | - exit("{} This script needs a Linux system with Pulseaudio installed (e.g. KDE) to record tracks.".format(ERROR)) |
| 34 | + if subprocess.Popen("parec --help && pw-cli --help", stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, shell=True).wait() != 0: |
| 35 | + exit("{} This script needs a Linux system with Pipewire & Pulseaudio installed (e.g. KDE) to record tracks.".format(ERROR)) |
36 | 36 |
|
37 | 37 | # always check for ctrl+c |
38 | 38 | try: |
|
47 | 47 | gap + f"██{RED}║{RST} {YELLOW}╚════{RST}██{YELLOW}║{RST} ██{GREEN}║{RST} ██{GREEN}║{RST}" + |
48 | 48 | gap + f"███████{RED}╗{RST} ███████{YELLOW}║{RST} ██████{GREEN}╔╝{RST}" + |
49 | 49 | gap + f"{RED}╚══════╝{RST} {YELLOW}╚══════╝{RST} {GREEN}╚═════╝{RST}" + |
50 | | - "\n" + " " * (T_WIDTH // 2 - 14) + " Linux-Spotify-Downloader 2.1" + |
| 50 | + "\n" + " " * (T_WIDTH // 2 - 14) + " Linux-Spotify-Downloader 2.2" + |
51 | 51 | gap + " developed by Jannis Zahn") |
52 | 52 |
|
53 | 53 | # specify the output-directory |
54 | 54 | print("\n" + "---- CONFIGURATION " + "-" * (T_WIDTH - 19) + "\n") |
55 | 55 | if not os.path.isdir(OUTPUT_DIR): |
56 | 56 | while True: |
57 | 57 | OUTPUT_DIR = input("{} Please specify an existing and writable output-directory: ".format(REQUEST)) |
58 | | - if os.path.isdir(OUTPUT_DIR): break |
| 58 | + if os.path.isdir(OUTPUT_DIR): |
| 59 | + break |
59 | 60 | OUTPUT_DIR = os.path.abspath(OUTPUT_DIR) |
60 | 61 | print("{} Output-Directory: {}".format(INFO, OUTPUT_DIR)) |
61 | 62 |
|
|
74 | 75 | print("\r{} OK, I have found a running Spotify-Application".format(INFO)) |
75 | 76 |
|
76 | 77 | # find spotify-input-sink and create monitor to record from |
77 | | - print("{} I have to play a track to create a new recording interface ...".format(INFO), end="", flush=True) |
| 78 | + print("{} I have to play a track to create a new recording interface ...".format(INFO)) |
78 | 79 | methods_if.Play() |
79 | | - time.sleep(3) |
| 80 | + time.sleep(1) |
80 | 81 | while True: |
81 | | - sink_inputs = subprocess.run(["pacmd", "list-sink-inputs"], stdout=subprocess.PIPE).stdout.decode() |
82 | | - if "application.name = \"Spotify\"" in sink_inputs: break |
| 82 | + sink_inputs = subprocess.run("pw-cli ls Node".split(), stdout=subprocess.PIPE).stdout.decode() |
| 83 | + if "application.name = \"spotify\"" in sink_inputs: |
| 84 | + break |
83 | 85 | time.sleep(1) |
84 | 86 | methods_if.Pause() |
85 | 87 | time.sleep(0.5) |
86 | | - sink_index = sink_inputs.split("application.name = \"Spotify\"")[0].split("index: ")[-1].split("\n")[0] |
87 | | - if subprocess.Popen(f"pactl load-module module-null-sink sink_name=lsd && pactl move-sink-input {sink_index} " |
88 | | - f"lsd", stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, shell=True).wait() == 0: |
89 | | - print("\r{} I have successfully created the recording interface to record from Spotify only.\n".format(INFO) |
90 | | - + "{} I will now listen for tracks to be played ... Please close Spotify as soon as you finished " |
91 | | - "playing all songs!{}".format(BOLD, RST)) |
| 88 | + sink_index = sink_inputs.split("application.name = \"spotify\"")[0].split("\tid ")[-1].split(",")[0] |
| 89 | + if subprocess.Popen("pactl load-module module-null-sink sink_name=lsd && pactl move-sink-input {} lsd".format(sink_index), |
| 90 | + stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, shell=True).wait() == 0: |
| 91 | + print("{}{} I will now listen for tracks to be played ..." |
| 92 | + "Please close Spotify as soon as you finished playing all songs!{}".format(INFO, BOLD, RST)) |
92 | 93 | else: |
93 | 94 | exit("\r{} Error while creating the recording device for Spotify.".format(ERROR)) |
94 | 95 |
|
95 | 96 | # start the recording with parec (PulseAudio-Recording) |
96 | 97 | print("\n" + "---- RECORDING " + "-" * (T_WIDTH - 15) + "\n") |
97 | | - recording_process = subprocess.Popen(f"parec -d lsd.monitor --file-format=wav".split() + [OUTPUT_DIR + "/.temp.wav"]) |
| 98 | + recording_process = subprocess.Popen("parec -d lsd.monitor --file-format=wav".split() + [OUTPUT_DIR + "/.temp.wav"]) |
98 | 99 |
|
99 | 100 | # initialize some variables |
100 | 101 | last_url = "" |
101 | 102 | counter = 0 |
102 | 103 | tracks = [] |
103 | 104 | ad = False |
104 | 105 |
|
105 | | - # wait until first song starts (to make it possible to record also the current song) |
106 | | - while prop_if.Get("org.mpris.MediaPlayer2.Player", "PlaybackStatus") != "Playing": time.sleep(0.01) |
107 | | - |
108 | 106 | # continue reading dbus-properties until Spotify gets closed |
109 | 107 | try: |
| 108 | + # wait until first song starts (to make it possible to record also the current song) |
| 109 | + while prop_if.Get("org.mpris.MediaPlayer2.Player", "PlaybackStatus") != "Playing": |
| 110 | + time.sleep(0.01) |
| 111 | + |
110 | 112 | while True: |
111 | 113 | # get all meta-information about the current track |
112 | 114 | meta = prop_if.Get("org.mpris.MediaPlayer2.Player", "Metadata") |
|
125 | 127 |
|
126 | 128 | except dbus.exceptions.DBusException: # means that Spotify is closed, because there is no bus any more |
127 | 129 | recording_process.terminate() # stop the recording |
128 | | - subprocess.Popen(["pulseaudio", "-k"]) # restore original pulseaudio-configuration |
| 130 | + subprocess.Popen("systemctl --user restart pipewire pipewire-pulse".split()) # restore original pulseaudio-configuration |
129 | 131 | print("{} I have recorded {} track(s).".format(INFO, counter)) |
130 | 132 |
|
131 | 133 | if counter > 0: |
|
149 | 151 | for idx, audio in enumerate(chunks): |
150 | 152 | if audio.duration_seconds >= 40: |
151 | 153 | song = sp.track(tracks[idx - skipped]) |
152 | | - print("\r{} Converting and tagging \"{}\" ...".format(INFO, song["name"]) + " " * (T_WIDTH - 33 - len(song["name"])), end="", flush=True) |
| 154 | + print("{} Converting and tagging \"{}\" ...".format(INFO, song["name"])) |
153 | 155 |
|
154 | | - if genius.access_token == "Bearer asd": |
| 156 | + if genius.access_token.startswith("Bearer"): |
155 | 157 | genius_song = genius.search_song(song["name"], song["artists"][0]["name"]) |
156 | 158 | if genius_song is not None: |
157 | 159 | lyrics = genius_song.lyrics |
|
177 | 179 |
|
178 | 180 | audio.export(OUTPUT_DIR + "/" + song["name"].replace("-", "~").replace("/", "~") |
179 | 181 | .replace("|", "~") + ".mp3", format="mp3", bitrate="192k", tags=tags, cover=OUTPUT_DIR + "/.cover.jpg") |
180 | | - else: skipped += 1 |
| 182 | + else: |
| 183 | + skipped += 1 |
181 | 184 | os.remove(OUTPUT_DIR + "/.temp.mp3") # remove all temporary files |
182 | 185 | os.remove(OUTPUT_DIR + "/.cover.jpg") |
183 | 186 | os.remove(OUTPUT_DIR + "/.temp.wav") |
184 | | - print("\r{}{} Done!".format(INFO, GREEN) + " " * (T_WIDTH - 9)) |
| 187 | + print("{}{} Done!".format(INFO, GREEN)) |
185 | 188 |
|
186 | 189 | except KeyboardInterrupt: |
187 | | - subprocess.Popen(["pulseaudio", "-k"]) |
| 190 | + subprocess.Popen("systemctl --user restart pipewire pipewire-pulse".split()) |
188 | 191 | exit("\n{}Detected Ctrl+C (Keyboard-Interrupt) ... Bye! :-)".format(RED)) |
0 commit comments