1use async_trait::async_trait;
2use hearth_interconnect::messages::Message;
3use hearth_interconnect::worker_communication::{DWCActionType, DirectWorkerCommunication};
4use std::time::Duration;
5use nanoid::nanoid;
6use crate::background::connector::BoilerplateParseIPCError;
7use crate::background::processor::IPCData;
8use crate::PlayerObject;
9use snafu::prelude::*;
10use tokio::sync::broadcast::error::SendError;
11
12#[derive(Debug, Snafu)]
13pub enum TrackActionError {
14 #[snafu(display("Failed to send IPC request to Background thread"))]
15 FailedToSendIPCRequest { source: SendError<IPCData> },
16 #[snafu(display("Did not receive metadata result within timeout time-frame"))]
17 TimedOutWaitingForMetadataResult { source: BoilerplateParseIPCError },
18}
19
20#[async_trait]
21pub trait TrackManager {
23 async fn set_playback_volume(&self, playback_volume: f32) -> Result<(), TrackActionError>;
25 async fn force_stop_loop(&self) -> Result<(), TrackActionError>;
27 async fn loop_indefinitely(&self) -> Result<(), TrackActionError>;
29 async fn loop_x_times(&self, times: usize) -> Result<(), TrackActionError>;
31 async fn seek_to_position(&self, position: Duration) -> Result<(), TrackActionError>;
33 async fn resume_playback(&self) -> Result<(), TrackActionError>;
35 async fn pause_playback(&self) -> Result<(), TrackActionError>;
37 async fn get_metadata(&mut self) -> Result<(), TrackActionError>;
39}
40#[async_trait]
41impl TrackManager for PlayerObject {
42 async fn set_playback_volume(&self, playback_volume: f32) -> Result<(), TrackActionError> {
43 self.bg_com_tx
44 .send(IPCData::new_from_main(
45 Message::DirectWorkerCommunication(DirectWorkerCommunication {
46 job_id: self.job_id.read().await.clone().unwrap(),
47 action_type: DWCActionType::SetPlaybackVolume,
48 play_audio_url: None,
49 guild_id: self.guild_id.clone(),
50 request_id: Some(nanoid!()),
51 new_volume: Some(playback_volume),
52 seek_position: None,
53 loop_times: None,
54 worker_id: self.worker_id.read().await.clone().unwrap(),
55 voice_channel_id: None,
56 }),
57 self.tx.clone(),
58 self.guild_id.clone(),
59 ))
60 .context(FailedToSendIPCRequestSnafu)?;
61 Ok(())
62 }
63 async fn force_stop_loop(&self) -> Result<(), TrackActionError> {
64 self.bg_com_tx
65 .send(IPCData::new_from_main(
66 Message::DirectWorkerCommunication(DirectWorkerCommunication {
67 job_id: self.job_id.read().await.clone().unwrap(),
68 action_type: DWCActionType::ForceStopLoop,
69 play_audio_url: None,
70 guild_id: self.guild_id.clone(),
71 request_id: Some(nanoid!()),
72 new_volume: None,
73 seek_position: None,
74 loop_times: None,
75 worker_id: self.worker_id.read().await.clone().unwrap(),
76 voice_channel_id: None,
77 }),
78 self.tx.clone(),
79 self.guild_id.clone(),
80 ))
81 .context(FailedToSendIPCRequestSnafu)?;
82
83 Ok(())
84 }
85 async fn loop_indefinitely(&self) -> Result<(), TrackActionError> {
86 self.bg_com_tx
87 .send(IPCData::new_from_main(
88 Message::DirectWorkerCommunication(DirectWorkerCommunication {
89 job_id: self.job_id.read().await.clone().unwrap(),
90 action_type: DWCActionType::LoopForever,
91 play_audio_url: None,
92 guild_id: self.guild_id.clone(),
93 request_id: Some(nanoid!()),
94 new_volume: None,
95 seek_position: None,
96 loop_times: None,
97 worker_id: self.worker_id.read().await.clone().unwrap(),
98 voice_channel_id: None,
99 }),
100 self.tx.clone(),
101 self.guild_id.clone(),
102 ))
103 .context(FailedToSendIPCRequestSnafu)?;
104
105 Ok(())
106 }
107
108 async fn loop_x_times(&self, times: usize) -> Result<(), TrackActionError> {
109 self.bg_com_tx
110 .send(IPCData::new_from_main(
111 Message::DirectWorkerCommunication(DirectWorkerCommunication {
112 job_id: self.job_id.read().await.clone().unwrap(),
113 action_type: DWCActionType::LoopXTimes,
114 play_audio_url: None,
115 guild_id: self.guild_id.clone(),
116 request_id: Some(nanoid!()),
117 new_volume: None,
118 seek_position: None,
119 loop_times: Some(times),
120 worker_id: self.worker_id.read().await.clone().unwrap(),
121 voice_channel_id: None,
122 }),
123 self.tx.clone(),
124 self.guild_id.clone(),
125 ))
126 .context(FailedToSendIPCRequestSnafu)?;
127
128 Ok(())
129 }
130 async fn seek_to_position(&self, position: Duration) -> Result<(), TrackActionError> {
131 self.bg_com_tx
132 .send(IPCData::new_from_main(
133 Message::DirectWorkerCommunication(DirectWorkerCommunication {
134 job_id: self.job_id.read().await.clone().unwrap(),
135 action_type: DWCActionType::SeekToPosition,
136 play_audio_url: None,
137 guild_id: self.guild_id.clone(),
138 request_id: Some(nanoid!()),
139 new_volume: None,
140 seek_position: Some(position.as_millis() as u64),
141 loop_times: None,
142 worker_id: self.worker_id.read().await.clone().unwrap(),
143 voice_channel_id: None,
144 }),
145 self.tx.clone(),
146 self.guild_id.clone(),
147 ))
148 .context(FailedToSendIPCRequestSnafu)?;
149
150 Ok(())
151 }
152 async fn resume_playback(&self) -> Result<(), TrackActionError> {
153 self.bg_com_tx
154 .send(IPCData::new_from_main(
155 Message::DirectWorkerCommunication(DirectWorkerCommunication {
156 job_id: self.job_id.read().await.clone().unwrap(),
157 action_type: DWCActionType::ResumePlayback,
158 play_audio_url: None,
159 guild_id: self.guild_id.clone(),
160 request_id: Some(nanoid!()),
161 new_volume: None,
162 seek_position: None,
163 loop_times: None,
164 worker_id: self.worker_id.read().await.clone().unwrap(),
165 voice_channel_id: None,
166 }),
167 self.tx.clone(),
168 self.guild_id.clone(),
169 ))
170 .context(FailedToSendIPCRequestSnafu)?;
171
172 Ok(())
173 }
174 async fn pause_playback(&self) -> Result<(), TrackActionError> {
175 self.bg_com_tx
176 .send(IPCData::new_from_main(
177 Message::DirectWorkerCommunication(DirectWorkerCommunication {
178 job_id: self.job_id.read().await.clone().unwrap(),
179 action_type: DWCActionType::PausePlayback,
180 play_audio_url: None,
181 guild_id: self.guild_id.clone(),
182 request_id: Some(nanoid!()),
183 new_volume: None,
184 seek_position: None,
185 loop_times: None,
186 worker_id: self.worker_id.read().await.clone().unwrap(),
187 voice_channel_id: None,
188 }),
189 self.tx.clone(),
190 self.guild_id.clone(),
191 ))
192 .context(FailedToSendIPCRequestSnafu)?;
193
194 Ok(())
195 }
196 async fn get_metadata(&mut self) -> Result<(), TrackActionError> {
197 self.bg_com_tx
198 .send(IPCData::new_from_main(
199 Message::DirectWorkerCommunication(DirectWorkerCommunication {
200 job_id: self.job_id.read().await.clone().unwrap(),
201 action_type: DWCActionType::GetMetaData,
202 play_audio_url: None,
203 guild_id: self.guild_id.clone(),
204 request_id: Some(nanoid!()),
205 new_volume: None,
206 seek_position: None,
207 loop_times: None,
208 worker_id: self.worker_id.read().await.clone().unwrap(),
209 voice_channel_id: None,
210 }),
211 self.tx.clone(),
212 self.guild_id.clone(),
213 ))
214 .context(FailedToSendIPCRequestSnafu)?;
215
216 Ok(())
217 }
218}