piwave 2.1.6__py3-none-any.whl → 2.1.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- piwave/backends/base.py +10 -6
- piwave/piwave.py +32 -34
- {piwave-2.1.6.dist-info → piwave-2.1.8.dist-info}/METADATA +4 -1
- {piwave-2.1.6.dist-info → piwave-2.1.8.dist-info}/RECORD +7 -7
- {piwave-2.1.6.dist-info → piwave-2.1.8.dist-info}/WHEEL +0 -0
- {piwave-2.1.6.dist-info → piwave-2.1.8.dist-info}/licenses/LICENSE +0 -0
- {piwave-2.1.6.dist-info → piwave-2.1.8.dist-info}/top_level.txt +0 -0
piwave/backends/base.py
CHANGED
|
@@ -232,20 +232,24 @@ class Backend(ABC):
|
|
|
232
232
|
cmd = self.build_command(wav_file, loop)
|
|
233
233
|
self.current_process = subprocess.Popen(
|
|
234
234
|
cmd,
|
|
235
|
-
stdout=subprocess.
|
|
236
|
-
stderr=subprocess.
|
|
235
|
+
stdout=subprocess.DEVNULL,
|
|
236
|
+
stderr=subprocess.DEVNULL,
|
|
237
|
+
stdin=subprocess.DEVNULL
|
|
237
238
|
)
|
|
238
239
|
return self.current_process
|
|
239
240
|
|
|
240
241
|
def stop(self):
|
|
241
242
|
if self.current_process:
|
|
242
243
|
try:
|
|
243
|
-
|
|
244
|
+
self.current_process.terminate()
|
|
244
245
|
self.current_process.wait(timeout=5)
|
|
245
|
-
except
|
|
246
|
+
except subprocess.TimeoutExpired:
|
|
246
247
|
try:
|
|
247
|
-
|
|
248
|
-
|
|
248
|
+
self.current_process.kill()
|
|
249
|
+
self.current_process.wait(timeout=2)
|
|
250
|
+
except:
|
|
249
251
|
pass
|
|
252
|
+
except ProcessLookupError:
|
|
253
|
+
pass
|
|
250
254
|
finally:
|
|
251
255
|
self.current_process = None
|
piwave/piwave.py
CHANGED
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
# Licensed under GPLv3.0, main GitHub repository at https://github.com/douxxtech/piwave/
|
|
3
3
|
# piwave/piwave.py : main entry
|
|
4
4
|
|
|
5
|
+
import atexit
|
|
5
6
|
import os
|
|
6
7
|
import subprocess
|
|
7
|
-
import signal
|
|
8
8
|
import threading
|
|
9
|
-
import time
|
|
10
9
|
|
|
11
10
|
import tempfile
|
|
12
11
|
import shutil
|
|
@@ -88,6 +87,7 @@ class PiWave:
|
|
|
88
87
|
Log.config(silent=silent)
|
|
89
88
|
|
|
90
89
|
self._validate_environment()
|
|
90
|
+
atexit.register(self._stop_curproc)
|
|
91
91
|
|
|
92
92
|
discover_backends()
|
|
93
93
|
|
|
@@ -288,7 +288,8 @@ class PiWave:
|
|
|
288
288
|
rds_info = f" (PS: {self.ps})" if self.backend.supports_rds and self.ps else ""
|
|
289
289
|
Log.broadcast(f"Playing {wav_file} ({loop_status}) at {self.frequency}MHz{rds_info}")
|
|
290
290
|
|
|
291
|
-
self.
|
|
291
|
+
self.backend.play_file(wav_file, self.loop)
|
|
292
|
+
self.current_process = self.backend.current_process
|
|
292
293
|
|
|
293
294
|
if self.on_track_change:
|
|
294
295
|
self.on_track_change(wav_file)
|
|
@@ -298,10 +299,10 @@ class PiWave:
|
|
|
298
299
|
# Only manually loop if the backend does not support it
|
|
299
300
|
while not self.stop_event.is_set():
|
|
300
301
|
if self.stop_event.wait(timeout=0.1):
|
|
301
|
-
self.
|
|
302
|
+
self._stop_curproc()
|
|
302
303
|
return False
|
|
303
304
|
|
|
304
|
-
if self.current_process.poll() is not None:
|
|
305
|
+
if self.backend.current_process.poll() is not None:
|
|
305
306
|
Log.error("Process ended unexpectedly while looping")
|
|
306
307
|
return False
|
|
307
308
|
|
|
@@ -309,9 +310,9 @@ class PiWave:
|
|
|
309
310
|
# fi backend supports looping or we are not looping, just wait for the process to finish
|
|
310
311
|
while not self.stop_event.is_set():
|
|
311
312
|
if self.stop_event.wait(timeout=0.1):
|
|
312
|
-
self.
|
|
313
|
+
self._stop_curproc()
|
|
313
314
|
return False
|
|
314
|
-
if not self.loop and self.current_process.poll() is not None:
|
|
315
|
+
if not self.loop and self.backend.current_process.poll() is not None:
|
|
315
316
|
break
|
|
316
317
|
return True
|
|
317
318
|
|
|
@@ -319,7 +320,7 @@ class PiWave:
|
|
|
319
320
|
Log.error(f"Error playing {wav_file}: {e}")
|
|
320
321
|
if self.on_error:
|
|
321
322
|
self.on_error(e)
|
|
322
|
-
self.
|
|
323
|
+
self._stop_curproc()
|
|
323
324
|
return False
|
|
324
325
|
|
|
325
326
|
|
|
@@ -373,8 +374,8 @@ class PiWave:
|
|
|
373
374
|
self.current_process = subprocess.Popen(
|
|
374
375
|
cmd,
|
|
375
376
|
stdin=subprocess.PIPE,
|
|
376
|
-
stdout=subprocess.
|
|
377
|
-
stderr=subprocess.
|
|
377
|
+
stdout=subprocess.DEVNULL,
|
|
378
|
+
stderr=subprocess.DEVNULL
|
|
378
379
|
)
|
|
379
380
|
except Exception as e:
|
|
380
381
|
Log.error(f"Failed to start live stream: {e}")
|
|
@@ -457,21 +458,6 @@ class PiWave:
|
|
|
457
458
|
pass
|
|
458
459
|
self.is_live_streaming = False
|
|
459
460
|
|
|
460
|
-
|
|
461
|
-
def _stop_current_process(self):
|
|
462
|
-
if self.current_process:
|
|
463
|
-
try:
|
|
464
|
-
os.killpg(os.getpgid(self.current_process.pid), signal.SIGTERM)
|
|
465
|
-
self.current_process.wait(timeout=5)
|
|
466
|
-
except (ProcessLookupError, subprocess.TimeoutExpired):
|
|
467
|
-
try:
|
|
468
|
-
os.killpg(os.getpgid(self.current_process.pid), signal.SIGKILL)
|
|
469
|
-
except ProcessLookupError:
|
|
470
|
-
pass
|
|
471
|
-
finally:
|
|
472
|
-
self.current_process = None
|
|
473
|
-
|
|
474
|
-
|
|
475
461
|
def _playback_worker(self):
|
|
476
462
|
self._log_debug("Playback worker started")
|
|
477
463
|
|
|
@@ -564,14 +550,7 @@ class PiWave:
|
|
|
564
550
|
except queue.Empty:
|
|
565
551
|
break
|
|
566
552
|
|
|
567
|
-
|
|
568
|
-
try:
|
|
569
|
-
os.killpg(os.getpgid(self.current_process.pid), signal.SIGTERM)
|
|
570
|
-
self.current_process.wait(timeout=5)
|
|
571
|
-
except Exception:
|
|
572
|
-
pass
|
|
573
|
-
finally:
|
|
574
|
-
self.current_process = None
|
|
553
|
+
self._stop_curproc()
|
|
575
554
|
|
|
576
555
|
if self.playback_thread and self.playback_thread.is_alive():
|
|
577
556
|
self.playback_thread.join(timeout=5)
|
|
@@ -582,6 +561,25 @@ class PiWave:
|
|
|
582
561
|
self.is_live_streaming = False
|
|
583
562
|
Log.success("Stopped")
|
|
584
563
|
|
|
564
|
+
def _stop_curproc(self):
|
|
565
|
+
if self.backend.current_process:
|
|
566
|
+
self.backend.stop()
|
|
567
|
+
elif self.current_process:
|
|
568
|
+
# live streaming
|
|
569
|
+
try:
|
|
570
|
+
self.current_process.terminate()
|
|
571
|
+
self.current_process.wait(timeout=5)
|
|
572
|
+
except subprocess.TimeoutExpired:
|
|
573
|
+
try:
|
|
574
|
+
self.current_process.kill()
|
|
575
|
+
self.current_process.wait(timeout=2)
|
|
576
|
+
except:
|
|
577
|
+
pass
|
|
578
|
+
except ProcessLookupError:
|
|
579
|
+
pass
|
|
580
|
+
finally:
|
|
581
|
+
self.current_process = None
|
|
582
|
+
|
|
585
583
|
def pause(self):
|
|
586
584
|
"""Pause the current playback.
|
|
587
585
|
|
|
@@ -592,7 +590,7 @@ class PiWave:
|
|
|
592
590
|
>>> pw.pause()
|
|
593
591
|
"""
|
|
594
592
|
if self.is_playing:
|
|
595
|
-
self.
|
|
593
|
+
self._stop_curproc()
|
|
596
594
|
Log.info("Playback paused")
|
|
597
595
|
|
|
598
596
|
def resume(self):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: piwave
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.8
|
|
4
4
|
Summary: A python module to broadcast radio waves with your Raspberry Pi.
|
|
5
5
|
Home-page: https://github.com/douxxtech/piwave
|
|
6
6
|
Author: Douxx
|
|
@@ -31,6 +31,9 @@ Dynamic: license-file
|
|
|
31
31
|
<h1>PiWave</h1>
|
|
32
32
|
</div>
|
|
33
33
|
|
|
34
|
+
> [!CAUTION]
|
|
35
|
+
> `piwave==2.1.6` is broken ! Please use `piwave==2.1.5`
|
|
36
|
+
|
|
34
37
|
**PiWave** is a Python module designed to manage and control your Raspberry Pi radio using multiple FM transmission backends. It provides a unified interface for broadcasting audio files with multiple backends support and RDS (Radio Data System) support.
|
|
35
38
|
|
|
36
39
|
## Features
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
piwave/__init__.py,sha256=jz2r-qclltKTxJjlGnqhAwIlUgjvRTR31f4hjTHP5NA,230
|
|
2
2
|
piwave/__main__.py,sha256=-Z3RI7TiicE5UwWc4dZaHX82-MpwVXWkfMZXOC457_Q,4089
|
|
3
3
|
piwave/logger.py,sha256=ipWzdNcEYob0xjXP8bbTq9enA3nryU-GKzAOKayRqlg,1149
|
|
4
|
-
piwave/piwave.py,sha256=
|
|
4
|
+
piwave/piwave.py,sha256=6ns1VmQ8hZFwrI_8HTLwvSD_CwMCzzUWGqms0u1MKeQ,32293
|
|
5
5
|
piwave/backends/__init__.py,sha256=DUbdyYf2V2XcDB05vmFWEkuJ292YTNiNJjzh1raJ5Cg,3756
|
|
6
|
-
piwave/backends/base.py,sha256=
|
|
6
|
+
piwave/backends/base.py,sha256=PJNXEEXZ8wgc343SO5FJ1oGOop--Y-7t01PUWSa5GuE,7818
|
|
7
7
|
piwave/backends/fm_transmitter.py,sha256=Wzsoyi5hqLLZF5eNPmZ7WFvP27OMs2ywJlwrJVut-8w,1403
|
|
8
8
|
piwave/backends/pi_fm_rds.py,sha256=VjcbFeje8LHVr4cBjlL36IcvA3WRfI1hHSGG2ui8Pb0,1467
|
|
9
|
-
piwave-2.1.
|
|
10
|
-
piwave-2.1.
|
|
11
|
-
piwave-2.1.
|
|
12
|
-
piwave-2.1.
|
|
13
|
-
piwave-2.1.
|
|
9
|
+
piwave-2.1.8.dist-info/licenses/LICENSE,sha256=IwGE9guuL-ryRPEKi6wFPI_zOhg7zDZbTYuHbSt_SAk,35823
|
|
10
|
+
piwave-2.1.8.dist-info/METADATA,sha256=eO1OgUr8q13UI5TVqcdzokAcUOZnh1WDFGXL5GtJItI,20890
|
|
11
|
+
piwave-2.1.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
12
|
+
piwave-2.1.8.dist-info/top_level.txt,sha256=xUbZ7Rk6OymSdDxmb9bfO8N-avJ9VYxP41GnXfwKYi8,7
|
|
13
|
+
piwave-2.1.8.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|