1
1
use std:: sync:: Arc ;
2
2
3
3
use thiserror:: Error ;
4
- use tokio:: sync:: broadcast;
5
- use tokio:: { select, sync:: mpsc} ;
4
+ use tokio:: {
5
+ select,
6
+ sync:: { broadcast, mpsc, oneshot} ,
7
+ } ;
6
8
9
+ use crate :: api:: types:: PriorityInfo ;
7
10
use crate :: models:: Color ;
8
11
use crate :: {
9
12
global:: { Global , InputMessage } ,
@@ -37,7 +40,9 @@ pub enum InstanceError {
37
40
}
38
41
39
42
pub struct Instance {
43
+ config : Arc < InstanceConfig > ,
40
44
device : InstanceDevice ,
45
+ handle_rx : mpsc:: Receiver < InstanceMessage > ,
41
46
receiver : broadcast:: Receiver < InputMessage > ,
42
47
local_receiver : mpsc:: Receiver < InputMessage > ,
43
48
muxer : PriorityMuxer ,
@@ -46,7 +51,7 @@ pub struct Instance {
46
51
}
47
52
48
53
impl Instance {
49
- pub async fn new ( global : Global , config : InstanceConfig ) -> Self {
54
+ pub async fn new ( global : Global , config : InstanceConfig ) -> ( Self , InstanceHandle ) {
50
55
let device: InstanceDevice =
51
56
Device :: new ( & config. instance . friendly_name , config. device . clone ( ) )
52
57
. await
@@ -92,14 +97,22 @@ impl Instance {
92
97
None
93
98
} ;
94
99
95
- Self {
96
- device,
97
- receiver,
98
- local_receiver,
99
- muxer,
100
- core,
101
- _boblight_server,
102
- }
100
+ let ( tx, handle_rx) = mpsc:: channel ( 1 ) ;
101
+ let id = config. instance . id ;
102
+
103
+ (
104
+ Self {
105
+ config,
106
+ device,
107
+ handle_rx,
108
+ receiver,
109
+ local_receiver,
110
+ muxer,
111
+ core,
112
+ _boblight_server,
113
+ } ,
114
+ InstanceHandle { id, tx } ,
115
+ )
103
116
}
104
117
105
118
async fn on_input_message ( & mut self , message : InputMessage ) {
@@ -109,6 +122,19 @@ impl Instance {
109
122
}
110
123
}
111
124
125
+ pub fn id ( & self ) -> i32 {
126
+ self . config . instance . id
127
+ }
128
+
129
+ async fn handle_instance_message ( & mut self , message : InstanceMessage ) {
130
+ match message {
131
+ InstanceMessage :: PriorityInfo ( tx) => {
132
+ // unwrap: the receiver should not have dropped
133
+ tx. send ( self . muxer . current_priorities ( ) . await ) . unwrap ( ) ;
134
+ }
135
+ }
136
+ }
137
+
112
138
pub async fn run ( mut self ) -> Result < ( ) , InstanceError > {
113
139
loop {
114
140
select ! {
@@ -123,7 +149,7 @@ impl Instance {
123
149
} ,
124
150
Err ( tokio:: sync:: broadcast:: error:: RecvError :: Closed ) => {
125
151
// No more input messages
126
- return Ok ( ( ) ) ;
152
+ break Ok ( ( ) ) ;
127
153
} ,
128
154
Err ( tokio:: sync:: broadcast:: error:: RecvError :: Lagged ( skipped) ) => {
129
155
warn!( "skipped {} input messages" , skipped) ;
@@ -147,6 +173,14 @@ impl Instance {
147
173
// LED data changed
148
174
self . device. set_led_data( led_data) . await ?;
149
175
} ,
176
+ message = self . handle_rx. recv( ) => {
177
+ if let Some ( message) = message {
178
+ self . handle_instance_message( message) . await ;
179
+ } else {
180
+ // If the handle is dropped, it means the instance was unregistered
181
+ break Ok ( ( ) ) ;
182
+ }
183
+ }
150
184
}
151
185
}
152
186
}
@@ -181,3 +215,32 @@ impl From<Result<Device, DeviceError>> for InstanceDevice {
181
215
Self { inner }
182
216
}
183
217
}
218
+
219
+ #[ derive( Debug ) ]
220
+ enum InstanceMessage {
221
+ PriorityInfo ( oneshot:: Sender < Vec < PriorityInfo > > ) ,
222
+ }
223
+
224
+ #[ derive( Clone ) ]
225
+ pub struct InstanceHandle {
226
+ id : i32 ,
227
+ tx : mpsc:: Sender < InstanceMessage > ,
228
+ }
229
+
230
+ impl InstanceHandle {
231
+ pub fn id ( & self ) -> i32 {
232
+ self . id
233
+ }
234
+
235
+ pub async fn current_priorities ( & self ) -> Vec < PriorityInfo > {
236
+ let ( tx, rx) = oneshot:: channel ( ) ;
237
+
238
+ // TODO: Don't unwrap and propagate?
239
+ self . tx
240
+ . send ( InstanceMessage :: PriorityInfo ( tx) )
241
+ . await
242
+ . unwrap ( ) ;
243
+ // unwrap: if the previous didn't fail, the instance will be there to answer
244
+ rx. await . unwrap ( )
245
+ }
246
+ }
0 commit comments