Skip to content

Commit 0233ef1

Browse files
Created AudioLooper.
1 parent 8233767 commit 0233ef1

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed

ui/sura_player_ui/audio_looper.py

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
from PyQt6.QtCore import QTimer
2+
from utils.audio_player import SurahPlayer
3+
from utils.universal_speech import UniversalSpeech
4+
5+
class AudioLooper:
6+
"""
7+
Manages looping functionality in the Quran player.
8+
9+
When loop is active, a timer periodically checks the player's current position.
10+
If the position exceeds the loop end point, the playback is restarted from the loop start point
11+
after a specified delay.
12+
"""
13+
14+
def __init__(self, player: SurahPlayer, loop_check_interval: int = 100):
15+
"""
16+
Initializes the AudioLooper.
17+
18+
:param player: Reference to the main player for controlling playback.
19+
:param loop_check_interval: Interval (in milliseconds) to check the player's position.
20+
"""
21+
self.player = player
22+
self.loop_start = None # Start point (A)
23+
self.loop_end = None # End point (B)
24+
self.loop_active = False # Loop state
25+
self.loop_delay = 500 # Delay (in milliseconds) before restarting the loop
26+
27+
# Timer to monitor the player's current position.
28+
self.monitor_timer = QTimer()
29+
self.monitor_timer.setInterval(loop_check_interval)
30+
self.monitor_timer.timeout.connect(self.check_loop)
31+
32+
def set_loop_start(self):
33+
"""Set the start point (A) for the repeat loop."""
34+
self.loop_start = self.player.get_position()
35+
UniversalSpeech.say(f"Start point set at {self.loop_start} seconds.")
36+
37+
def set_loop_end(self):
38+
"""Set the end point (B) for the repeat loop."""
39+
self.loop_end = self.player.get_position()
40+
UniversalSpeech.say(f"End point set at {self.loop_end} seconds.")
41+
42+
def toggle_loop(self):
43+
"""
44+
Toggle loop playback between start (A) and end (B).
45+
If loop points are not set, informs the user.
46+
"""
47+
if self.loop_start is None or self.loop_end is None:
48+
UniversalSpeech.say("Loop points not set.")
49+
return
50+
51+
self.loop_active = not self.loop_active
52+
if self.loop_active:
53+
UniversalSpeech.say(f"Looping from {self.loop_start} to {self.loop_end} seconds.")
54+
# Start playback from the loop start and start the monitor timer.
55+
self.player.set_position(self.loop_start)
56+
self.player.play()
57+
self.monitor_timer.start()
58+
else:
59+
UniversalSpeech.say("Loop stopped.")
60+
self.monitor_timer.stop()
61+
62+
return self.loop_active
63+
64+
def check_loop(self):
65+
"""
66+
Checks the player's current position.
67+
If the position exceeds loop_end, restarts the loop after the specified delay.
68+
"""
69+
current_position = self.player.get_position()
70+
if current_position >= self.loop_end:
71+
# Stop the monitor timer to avoid multiple triggers.
72+
self.monitor_timer.stop()
73+
QTimer.singleShot(self.loop_delay, self.restart_loop)
74+
75+
def restart_loop(self):
76+
"""
77+
Restarts the loop by setting the player's position to loop_start,
78+
resuming playback, and restarting the monitor timer.
79+
"""
80+
if self.loop_active:
81+
self.player.set_position(self.loop_start)
82+
self.player.play()
83+
self.monitor_timer.start()
84+
85+
def set_loop_delay(self, delay: int):
86+
"""
87+
Set the delay time (in milliseconds) before restarting the loop.
88+
89+
:param delay: Delay in milliseconds.
90+
"""
91+
self.loop_delay = delay
92+
UniversalSpeech.say(f"Loop delay set to {self.loop_delay} milliseconds.")

0 commit comments

Comments
 (0)