1 /* Media proxy */
2
3 /*
4 * Copyright (c) 2021 Nordic Semiconductor ASA
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #include <errno.h>
10 #include <stdbool.h>
11 #include <stddef.h>
12 #include <stdint.h>
13
14 #include <zephyr/autoconf.h>
15 #include <zephyr/bluetooth/audio/media_proxy.h>
16 #include <zephyr/bluetooth/audio/mcc.h>
17 #include <zephyr/bluetooth/conn.h>
18 #include <zephyr/bluetooth/services/ots.h>
19 #include <zephyr/logging/log.h>
20 #include <zephyr/sys/check.h>
21
22 #include "media_proxy_internal.h"
23 #include "mcs_internal.h"
24
25 LOG_MODULE_REGISTER(media_proxy, CONFIG_MCTL_LOG_LEVEL);
26
27 /* Media player */
28 struct media_player {
29 struct media_proxy_pl_calls *calls;
30 struct bt_conn *conn; /* TODO: Treat local and remote player differently */
31 bool registered;
32 };
33
34 /* Synchronous controller - controller using the synchronous API */
35 struct scontroller {
36 struct media_proxy_sctrl_cbs *cbs;
37 };
38
39 /* Asynchronous controller - controller using the asynchronous API */
40 struct controller {
41 struct media_proxy_ctrl_cbs *cbs;
42 };
43 /* Media proxy */
44 struct mprx {
45
46 #if defined(CONFIG_MCTL_LOCAL_PLAYER_REMOTE_CONTROL)
47 /* Controller using the synchronous interface - e.g. remote controller via
48 * the media control service
49 */
50 struct scontroller sctrlr;
51 #endif /* CONFIG_MCTL_LOCAL_PLAYER_REMOTE_CONTROL */
52
53 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
54 /* Controller using the callback interface - i.e. upper layer */
55 struct controller ctrlr;
56 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
57
58 #if defined(CONFIG_MCTL_LOCAL_PLAYER_CONTROL)
59 /* The local media player */
60 struct media_player local_player;
61 #endif /* CONFIG_MCTL_LOCAL_PLAYER_CONTROL */
62
63 /* Control of remote players is currently only supported over Bluetooth, via MCC */
64 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL)
65 /* Remote media player - to have a player instance for the user */
66 struct media_player remote_player;
67
68 /* MCC callbacks */
69 struct bt_mcc_cb mcc_cbs;
70 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL */
71 };
72
73 static struct mprx mprx = { 0 };
74
75
76 #if defined(CONFIG_MCTL_LOCAL_PLAYER_REMOTE_CONTROL)
77 /* Synchronous controller calls ***********************************************/
78
79 /* The synchronous controller is the media control service, representing a remote controller.
80 * It only gets access to the local player, not remote players.
81 * I.e., the calls from the synchronous controller are always routed to the local_player.
82 */
83
media_proxy_sctrl_register(struct media_proxy_sctrl_cbs * sctrl_cbs)84 int media_proxy_sctrl_register(struct media_proxy_sctrl_cbs *sctrl_cbs)
85 {
86 mprx.sctrlr.cbs = sctrl_cbs;
87 return 0;
88 };
89
media_proxy_sctrl_get_player_name(void)90 const char *media_proxy_sctrl_get_player_name(void)
91 {
92 /* TODO: Add check for whether function pointer is non-NULL everywhere */
93 return mprx.local_player.calls->get_player_name();
94 }
95
96 #ifdef CONFIG_BT_MPL_OBJECTS
media_proxy_sctrl_get_icon_id(void)97 uint64_t media_proxy_sctrl_get_icon_id(void)
98 {
99 return mprx.local_player.calls->get_icon_id();
100 }
101 #endif /* CONFIG_BT_MPL_OBJECTS */
102
media_proxy_sctrl_get_icon_url(void)103 const char *media_proxy_sctrl_get_icon_url(void)
104 {
105 return mprx.local_player.calls->get_icon_url();
106 }
107
media_proxy_sctrl_get_track_title(void)108 const char *media_proxy_sctrl_get_track_title(void)
109 {
110 return mprx.local_player.calls->get_track_title();
111 }
112
media_proxy_sctrl_get_track_duration(void)113 int32_t media_proxy_sctrl_get_track_duration(void)
114 {
115 return mprx.local_player.calls->get_track_duration();
116 }
117
media_proxy_sctrl_get_track_position(void)118 int32_t media_proxy_sctrl_get_track_position(void)
119 {
120 return mprx.local_player.calls->get_track_position();
121 }
122
media_proxy_sctrl_set_track_position(int32_t position)123 void media_proxy_sctrl_set_track_position(int32_t position)
124 {
125 mprx.local_player.calls->set_track_position(position);
126 }
127
media_proxy_sctrl_get_playback_speed(void)128 int8_t media_proxy_sctrl_get_playback_speed(void)
129 {
130 return mprx.local_player.calls->get_playback_speed();
131 }
132
media_proxy_sctrl_set_playback_speed(int8_t speed)133 void media_proxy_sctrl_set_playback_speed(int8_t speed)
134 {
135 mprx.local_player.calls->set_playback_speed(speed);
136 }
137
media_proxy_sctrl_get_seeking_speed(void)138 int8_t media_proxy_sctrl_get_seeking_speed(void)
139 {
140 return mprx.local_player.calls->get_seeking_speed();
141 }
142
143 #ifdef CONFIG_BT_MPL_OBJECTS
media_proxy_sctrl_get_track_segments_id(void)144 uint64_t media_proxy_sctrl_get_track_segments_id(void)
145 {
146 return mprx.local_player.calls->get_track_segments_id();
147 }
148
media_proxy_sctrl_get_current_track_id(void)149 uint64_t media_proxy_sctrl_get_current_track_id(void)
150 {
151 return mprx.local_player.calls->get_current_track_id();
152 }
153
media_proxy_sctrl_set_current_track_id(uint64_t id)154 void media_proxy_sctrl_set_current_track_id(uint64_t id)
155 {
156 mprx.local_player.calls->set_current_track_id(id);
157 }
158
media_proxy_sctrl_get_next_track_id(void)159 uint64_t media_proxy_sctrl_get_next_track_id(void)
160 {
161 return mprx.local_player.calls->get_next_track_id();
162 }
163
media_proxy_sctrl_set_next_track_id(uint64_t id)164 void media_proxy_sctrl_set_next_track_id(uint64_t id)
165 {
166 mprx.local_player.calls->set_next_track_id(id);
167 }
168
media_proxy_sctrl_get_parent_group_id(void)169 uint64_t media_proxy_sctrl_get_parent_group_id(void)
170 {
171 return mprx.local_player.calls->get_parent_group_id();
172 }
173
media_proxy_sctrl_get_current_group_id(void)174 uint64_t media_proxy_sctrl_get_current_group_id(void)
175 {
176 return mprx.local_player.calls->get_current_group_id();
177 }
178
media_proxy_sctrl_set_current_group_id(uint64_t id)179 void media_proxy_sctrl_set_current_group_id(uint64_t id)
180 {
181 mprx.local_player.calls->set_current_group_id(id);
182 }
183 #endif /* CONFIG_BT_MPL_OBJECTS */
184
media_proxy_sctrl_get_playing_order(void)185 uint8_t media_proxy_sctrl_get_playing_order(void)
186 {
187 return mprx.local_player.calls->get_playing_order();
188 }
189
media_proxy_sctrl_set_playing_order(uint8_t order)190 void media_proxy_sctrl_set_playing_order(uint8_t order)
191 {
192 mprx.local_player.calls->set_playing_order(order);
193 }
194
media_proxy_sctrl_get_playing_orders_supported(void)195 uint16_t media_proxy_sctrl_get_playing_orders_supported(void)
196 {
197 return mprx.local_player.calls->get_playing_orders_supported();
198 }
199
media_proxy_sctrl_get_media_state(void)200 uint8_t media_proxy_sctrl_get_media_state(void)
201 {
202 return mprx.local_player.calls->get_media_state();
203 }
204
media_proxy_sctrl_send_command(const struct mpl_cmd * cmd)205 void media_proxy_sctrl_send_command(const struct mpl_cmd *cmd)
206 {
207 mprx.local_player.calls->send_command(cmd);
208 }
209
media_proxy_sctrl_get_commands_supported(void)210 uint32_t media_proxy_sctrl_get_commands_supported(void)
211 {
212 return mprx.local_player.calls->get_commands_supported();
213 }
214
215 #ifdef CONFIG_BT_MPL_OBJECTS
media_proxy_sctrl_send_search(const struct mpl_search * search)216 void media_proxy_sctrl_send_search(const struct mpl_search *search)
217 {
218 mprx.local_player.calls->send_search(search);
219 }
220
media_proxy_sctrl_get_search_results_id(void)221 uint64_t media_proxy_sctrl_get_search_results_id(void)
222 {
223 return mprx.local_player.calls->get_search_results_id();
224 }
225 void media_proxy_sctrl_search_results_id_cb(uint64_t id);
226 #endif /* CONFIG_BT_MPL_OBJECTS */
227
media_proxy_sctrl_get_content_ctrl_id(void)228 uint8_t media_proxy_sctrl_get_content_ctrl_id(void)
229 {
230 return mprx.local_player.calls->get_content_ctrl_id();
231 }
232 #endif /* CONFIG_MCTL_LOCAL_PLAYER_REMOTE_CONTROL */
233
234
235 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL)
236 /* Media control client callbacks *********************************************/
237
mcc_discover_mcs_cb(struct bt_conn * conn,int err)238 static void mcc_discover_mcs_cb(struct bt_conn *conn, int err)
239 {
240 if (err) {
241 LOG_ERR("Discovery failed (%d)", err);
242 }
243
244 LOG_DBG("Discovered player");
245
246 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->discover_player) {
247 mprx.ctrlr.cbs->discover_player(&mprx.remote_player, err);
248 } else {
249 LOG_DBG("No callback");
250 }
251 }
252
mcc_read_player_name_cb(struct bt_conn * conn,int err,const char * name)253 static void mcc_read_player_name_cb(struct bt_conn *conn, int err, const char *name)
254 {
255 /* Debug statements for at least a couple of the callbacks, to show flow */
256 LOG_DBG("MCC player name callback");
257
258 if (err) {
259 LOG_ERR("Player name failed");
260 }
261
262 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->player_name_recv) {
263 mprx.ctrlr.cbs->player_name_recv(&mprx.remote_player, err, name);
264 } else {
265 LOG_DBG("No callback");
266 }
267 }
268
269 #ifdef CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS
mcc_read_icon_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)270 static void mcc_read_icon_obj_id_cb(struct bt_conn *conn, int err, uint64_t id)
271 {
272 LOG_DBG("Icon Object ID callback");
273
274 if (err) {
275 LOG_ERR("Icon Object ID read failed (%d)", err);
276 }
277
278 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->icon_id_recv) {
279 mprx.ctrlr.cbs->icon_id_recv(&mprx.remote_player, err, id);
280 } else {
281 LOG_DBG("No callback");
282 }
283 }
284 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
285
286 #if defined(CONFIG_BT_MCC_READ_MEDIA_PLAYER_ICON_URL)
mcc_read_icon_url_cb(struct bt_conn * conn,int err,const char * url)287 static void mcc_read_icon_url_cb(struct bt_conn *conn, int err, const char *url)
288 {
289 if (err) {
290 LOG_ERR("Icon URL read failed (%d)", err);
291 }
292
293 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->icon_url_recv) {
294 mprx.ctrlr.cbs->icon_url_recv(&mprx.remote_player, err, url);
295 } else {
296 LOG_DBG("No callback");
297 }
298 }
299 #endif /* defined(CONFIG_BT_MCC_READ_MEDIA_PLAYER_ICON_URL) */
300
mcc_track_changed_ntf_cb(struct bt_conn * conn,int err)301 static void mcc_track_changed_ntf_cb(struct bt_conn *conn, int err)
302 {
303 if (err) {
304 LOG_ERR("Track change notification failed (%d)", err);
305 return;
306 }
307
308 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_changed_recv) {
309 mprx.ctrlr.cbs->track_changed_recv(&mprx.remote_player, err);
310 } else {
311 LOG_DBG("No callback");
312 }
313 }
314
315 #if defined(CONFIG_BT_MCC_READ_TRACK_TITLE)
mcc_read_track_title_cb(struct bt_conn * conn,int err,const char * title)316 static void mcc_read_track_title_cb(struct bt_conn *conn, int err, const char *title)
317 {
318 if (err) {
319 LOG_ERR("Track title read failed (%d)", err);
320 }
321
322 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_title_recv) {
323 mprx.ctrlr.cbs->track_title_recv(&mprx.remote_player, err, title);
324 } else {
325 LOG_DBG("No callback");
326 }
327 }
328 #endif /* defined(CONFIG_BT_MCC_READ_TRACK_TITLE) */
329
330 #if defined(CONFIG_BT_MCC_READ_TRACK_DURATION)
mcc_read_track_duration_cb(struct bt_conn * conn,int err,int32_t dur)331 static void mcc_read_track_duration_cb(struct bt_conn *conn, int err, int32_t dur)
332 {
333 if (err) {
334 LOG_ERR("Track duration read failed (%d)", err);
335 }
336
337 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_duration_recv) {
338 mprx.ctrlr.cbs->track_duration_recv(&mprx.remote_player, err, dur);
339 } else {
340 LOG_DBG("No callback");
341 }
342 }
343 #endif /* defined(CONFIG_BT_MCC_READ_TRACK_DURATION) */
344
345 #if defined(CONFIG_BT_MCC_READ_TRACK_POSITION)
mcc_read_track_position_cb(struct bt_conn * conn,int err,int32_t pos)346 static void mcc_read_track_position_cb(struct bt_conn *conn, int err, int32_t pos)
347 {
348 if (err) {
349 LOG_ERR("Track position read failed (%d)", err);
350 }
351
352 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_position_recv) {
353 mprx.ctrlr.cbs->track_position_recv(&mprx.remote_player, err, pos);
354 } else {
355 LOG_DBG("No callback");
356 }
357 }
358 #endif /* defined(CONFIG_BT_MCC_READ_TRACK_POSITION) */
359
360 #if defined(CONFIG_BT_MCC_SET_TRACK_POSITION)
mcc_set_track_position_cb(struct bt_conn * conn,int err,int32_t pos)361 static void mcc_set_track_position_cb(struct bt_conn *conn, int err, int32_t pos)
362 {
363 if (err) {
364 LOG_ERR("Track Position set failed (%d)", err);
365 }
366
367 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_position_write) {
368 mprx.ctrlr.cbs->track_position_write(&mprx.remote_player, err, pos);
369 } else {
370 LOG_DBG("No callback");
371 }
372 }
373 #endif /* defined(CONFIG_BT_MCC_SET_TRACK_POSITION) */
374
375 #if defined(CONFIG_BT_MCC_READ_PLAYBACK_SPEED)
mcc_read_playback_speed_cb(struct bt_conn * conn,int err,int8_t speed)376 static void mcc_read_playback_speed_cb(struct bt_conn *conn, int err, int8_t speed)
377 {
378 if (err) {
379 LOG_ERR("Playback speed read failed (%d)", err);
380 }
381
382 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->playback_speed_recv) {
383 mprx.ctrlr.cbs->playback_speed_recv(&mprx.remote_player, err, speed);
384 } else {
385 LOG_DBG("No callback");
386 }
387 }
388 #endif /* defined (CONFIG_BT_MCC_READ_PLAYBACK_SPEED) */
389
390 #if defined(CONFIG_BT_MCC_SET_PLAYBACK_SPEED)
mcc_set_playback_speed_cb(struct bt_conn * conn,int err,int8_t speed)391 static void mcc_set_playback_speed_cb(struct bt_conn *conn, int err, int8_t speed)
392 {
393 if (err) {
394 LOG_ERR("Playback speed set failed (%d)", err);
395 }
396
397 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->playback_speed_write) {
398 mprx.ctrlr.cbs->playback_speed_write(&mprx.remote_player, err, speed);
399 } else {
400 LOG_DBG("No callback");
401 }
402 }
403 #endif /* defined (CONFIG_BT_MCC_SET_PLAYBACK_SPEED) */
404
405 #if defined(CONFIG_BT_MCC_READ_SEEKING_SPEED)
mcc_read_seeking_speed_cb(struct bt_conn * conn,int err,int8_t speed)406 static void mcc_read_seeking_speed_cb(struct bt_conn *conn, int err, int8_t speed)
407 {
408 if (err) {
409 LOG_ERR("Seeking speed read failed (%d)", err);
410 }
411
412 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->seeking_speed_recv) {
413 mprx.ctrlr.cbs->seeking_speed_recv(&mprx.remote_player, err, speed);
414 } else {
415 LOG_DBG("No callback");
416 }
417 }
418 #endif /* defined (CONFIG_BT_MCC_READ_SEEKING_SPEED) */
419
420 #ifdef CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS
mcc_read_segments_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)421 static void mcc_read_segments_obj_id_cb(struct bt_conn *conn, int err, uint64_t id)
422 {
423 if (err) {
424 LOG_ERR("Track Segments Object ID read failed (%d)", err);
425 }
426
427 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_segments_id_recv) {
428 mprx.ctrlr.cbs->track_segments_id_recv(&mprx.remote_player, err, id);
429 } else {
430 LOG_DBG("No callback");
431 }
432 }
433
mcc_read_current_track_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)434 static void mcc_read_current_track_obj_id_cb(struct bt_conn *conn, int err, uint64_t id)
435 {
436 if (err) {
437 LOG_ERR("Current Track Object ID read failed (%d)", err);
438 }
439
440 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->current_track_id_recv) {
441 mprx.ctrlr.cbs->current_track_id_recv(&mprx.remote_player, err, id);
442 } else {
443 LOG_DBG("No callback");
444 }
445 }
446
447 /* TODO: current track set callback - must be added to MCC first */
448
mcc_read_next_track_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)449 static void mcc_read_next_track_obj_id_cb(struct bt_conn *conn, int err, uint64_t id)
450 {
451 if (err) {
452 LOG_ERR("Next Track Object ID read failed (%d)", err);
453 }
454
455 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->next_track_id_recv) {
456 mprx.ctrlr.cbs->next_track_id_recv(&mprx.remote_player, err, id);
457 } else {
458 LOG_DBG("No callback");
459 }
460 }
461
462 /* TODO: next track set callback - must be added to MCC first */
463
mcc_read_parent_group_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)464 static void mcc_read_parent_group_obj_id_cb(struct bt_conn *conn, int err, uint64_t id)
465 {
466 if (err) {
467 LOG_ERR("Parent Group Object ID read failed (%d)", err);
468 }
469
470 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->parent_group_id_recv) {
471 mprx.ctrlr.cbs->parent_group_id_recv(&mprx.remote_player, err, id);
472 } else {
473 LOG_DBG("No callback");
474 }
475 }
476
mcc_read_current_group_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)477 static void mcc_read_current_group_obj_id_cb(struct bt_conn *conn, int err, uint64_t id)
478 {
479 if (err) {
480 LOG_ERR("Current Group Object ID read failed (%d)", err);
481 }
482
483 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->current_group_id_recv) {
484 mprx.ctrlr.cbs->current_group_id_recv(&mprx.remote_player, err, id);
485 } else {
486 LOG_DBG("No callback");
487 }
488 }
489
490 /* TODO: current group set callback - must be added to MCC first */
491
492 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
493
494 #if defined(CONFIG_BT_MCC_READ_PLAYING_ORDER)
mcc_read_playing_order_cb(struct bt_conn * conn,int err,uint8_t order)495 static void mcc_read_playing_order_cb(struct bt_conn *conn, int err, uint8_t order)
496 {
497 if (err) {
498 LOG_ERR("Playing order read failed (%d)", err);
499 }
500
501 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->playing_order_recv) {
502 mprx.ctrlr.cbs->playing_order_recv(&mprx.remote_player, err, order);
503 } else {
504 LOG_DBG("No callback");
505 }
506 }
507 #endif /* defined(CONFIG_BT_MCC_READ_PLAYING_ORDER) */
508
509 #if defined(CONFIG_BT_MCC_SET_PLAYING_ORDER)
mcc_set_playing_order_cb(struct bt_conn * conn,int err,uint8_t order)510 static void mcc_set_playing_order_cb(struct bt_conn *conn, int err, uint8_t order)
511 {
512 if (err) {
513 LOG_ERR("Playing order set failed (%d)", err);
514 }
515
516 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->playing_order_write) {
517 mprx.ctrlr.cbs->playing_order_write(&mprx.remote_player, err, order);
518 } else {
519 LOG_DBG("No callback");
520 }
521 }
522 #endif /* defined(CONFIG_BT_MCC_SET_PLAYING_ORDER) */
523
524 #if defined(CONFIG_BT_MCC_READ_PLAYING_ORDER_SUPPORTED)
mcc_read_playing_orders_supported_cb(struct bt_conn * conn,int err,uint16_t orders)525 static void mcc_read_playing_orders_supported_cb(struct bt_conn *conn, int err, uint16_t orders)
526 {
527 if (err) {
528 LOG_ERR("Playing orders supported read failed (%d)", err);
529 }
530
531 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->playing_orders_supported_recv) {
532 mprx.ctrlr.cbs->playing_orders_supported_recv(&mprx.remote_player, err, orders);
533 } else {
534 LOG_DBG("No callback");
535 }
536 }
537 #endif /* defined(CONFIG_BT_MCC_READ_PLAYING_ORDER_SUPPORTED) */
538
539 #if defined(CONFIG_BT_MCC_READ_MEDIA_STATE)
mcc_read_media_state_cb(struct bt_conn * conn,int err,uint8_t state)540 static void mcc_read_media_state_cb(struct bt_conn *conn, int err, uint8_t state)
541 {
542 if (err) {
543 LOG_ERR("Media State read failed (%d)", err);
544 }
545
546 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->media_state_recv) {
547 mprx.ctrlr.cbs->media_state_recv(&mprx.remote_player, err, state);
548 } else {
549 LOG_DBG("No callback");
550 }
551 }
552 #endif /* defined(CONFIG_BT_MCC_READ_MEDIA_STATE) */
553
554 #if defined(CONFIG_BT_MCC_SET_MEDIA_CONTROL_POINT)
mcc_send_cmd_cb(struct bt_conn * conn,int err,const struct mpl_cmd * cmd)555 static void mcc_send_cmd_cb(struct bt_conn *conn, int err, const struct mpl_cmd *cmd)
556 {
557 if (err) {
558 LOG_ERR("Command send failed (%d) - opcode: %d, param: %d", err, cmd->opcode,
559 cmd->param);
560 }
561
562 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->command_send) {
563 mprx.ctrlr.cbs->command_send(&mprx.remote_player, err, cmd);
564 } else {
565 LOG_DBG("No callback");
566 }
567 }
568 #endif /* defined(CONFIG_BT_MCC_SET_MEDIA_CONTROL_POINT) */
569
mcc_cmd_ntf_cb(struct bt_conn * conn,int err,const struct mpl_cmd_ntf * ntf)570 static void mcc_cmd_ntf_cb(struct bt_conn *conn, int err,
571 const struct mpl_cmd_ntf *ntf)
572 {
573 if (err) {
574 LOG_ERR("Command notification error (%d) - command opcode: %d, result: %d", err,
575 ntf->requested_opcode, ntf->result_code);
576 }
577
578 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->command_recv) {
579 mprx.ctrlr.cbs->command_recv(&mprx.remote_player, err, ntf);
580 } else {
581 LOG_DBG("No callback");
582 }
583 }
584
585 #if defined(CONFIG_BT_MCC_READ_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED)
mcc_read_opcodes_supported_cb(struct bt_conn * conn,int err,uint32_t opcodes)586 static void mcc_read_opcodes_supported_cb(struct bt_conn *conn, int err, uint32_t opcodes)
587 {
588 if (err) {
589 LOG_ERR("Opcodes supported read failed (%d)", err);
590 }
591
592 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->commands_supported_recv) {
593 mprx.ctrlr.cbs->commands_supported_recv(&mprx.remote_player, err, opcodes);
594 } else {
595 LOG_DBG("No callback");
596 }
597 }
598 #endif /* defined(CONFIG_BT_MCC_READ_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED) */
599
600 #ifdef CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS
mcc_send_search_cb(struct bt_conn * conn,int err,const struct mpl_search * search)601 static void mcc_send_search_cb(struct bt_conn *conn, int err, const struct mpl_search *search)
602 {
603 if (err) {
604 LOG_ERR("Search send failed (%d)", err);
605 }
606
607 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->search_send) {
608 mprx.ctrlr.cbs->search_send(&mprx.remote_player, err, search);
609 } else {
610 LOG_DBG("No callback");
611 }
612 }
613
mcc_search_ntf_cb(struct bt_conn * conn,int err,uint8_t result_code)614 static void mcc_search_ntf_cb(struct bt_conn *conn, int err, uint8_t result_code)
615 {
616 if (err) {
617 LOG_ERR("Search notification error (%d), result code: %d", err, result_code);
618 }
619
620 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->search_recv) {
621 mprx.ctrlr.cbs->search_recv(&mprx.remote_player, err, result_code);
622 } else {
623 LOG_DBG("No callback");
624 }
625 }
626
mcc_read_search_results_obj_id_cb(struct bt_conn * conn,int err,uint64_t id)627 static void mcc_read_search_results_obj_id_cb(struct bt_conn *conn, int err, uint64_t id)
628 {
629 if (err) {
630 LOG_ERR("Search Results Object ID read failed (%d)", err);
631 }
632
633 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->search_results_id_recv) {
634 mprx.ctrlr.cbs->search_results_id_recv(&mprx.remote_player, err, id);
635 } else {
636 LOG_DBG("No callback");
637 }
638 }
639 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
640
641 #if defined(CONFIG_BT_MCC_READ_CONTENT_CONTROL_ID)
mcc_read_content_control_id_cb(struct bt_conn * conn,int err,uint8_t ccid)642 static void mcc_read_content_control_id_cb(struct bt_conn *conn, int err, uint8_t ccid)
643 {
644 if (err) {
645 LOG_ERR("Content Control ID read failed (%d)", err);
646 }
647
648 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->content_ctrl_id_recv) {
649 mprx.ctrlr.cbs->content_ctrl_id_recv(&mprx.remote_player, err, ccid);
650 } else {
651 LOG_DBG("No callback");
652 }
653 }
654 #endif /* defined(CONFIG_BT_MCC_READ_CONTENT_CONTROL_ID) */
655
656 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL */
657
658
659 /* Asynchronous controller calls **********************************************/
660
661 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
media_proxy_ctrl_register(struct media_proxy_ctrl_cbs * ctrl_cbs)662 int media_proxy_ctrl_register(struct media_proxy_ctrl_cbs *ctrl_cbs)
663 {
664 CHECKIF(ctrl_cbs == NULL) {
665 LOG_DBG("NULL callback pointer");
666 return -EINVAL;
667 }
668
669 mprx.ctrlr.cbs = ctrl_cbs;
670
671 if (mprx.local_player.registered) {
672 if (mprx.ctrlr.cbs->local_player_instance) {
673 mprx.ctrlr.cbs->local_player_instance(&mprx.local_player, 0);
674 }
675 }
676
677 /* TODO: Return error code if too many controllers registered */
678 return 0;
679 };
680 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
681
682 #ifdef CONFIG_MCTL_REMOTE_PLAYER_CONTROL
disconnected(struct bt_conn * conn,uint8_t reason)683 static void disconnected(struct bt_conn *conn, uint8_t reason)
684 {
685 if (mprx.remote_player.conn == conn) {
686 bt_conn_unref(mprx.remote_player.conn);
687 mprx.remote_player.conn = NULL;
688 }
689 }
690
691 BT_CONN_CB_DEFINE(conn_callbacks) = {
692 .disconnected = disconnected,
693 };
694
media_proxy_ctrl_discover_player(struct bt_conn * conn)695 int media_proxy_ctrl_discover_player(struct bt_conn *conn)
696 {
697 int err;
698
699 CHECKIF(!conn) {
700 LOG_DBG("NUll conn pointer");
701 return -EINVAL;
702 }
703
704 /* Initialize MCC */
705 mprx.mcc_cbs.discover_mcs = mcc_discover_mcs_cb;
706 mprx.mcc_cbs.read_player_name = mcc_read_player_name_cb;
707 #ifdef CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS
708 mprx.mcc_cbs.read_icon_obj_id = mcc_read_icon_obj_id_cb;
709 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
710 #if defined(CONFIG_BT_MCC_READ_MEDIA_PLAYER_ICON_URL)
711 mprx.mcc_cbs.read_icon_url = mcc_read_icon_url_cb;
712 #endif /* defined(CONFIG_BT_MCC_READ_MEDIA_PLAYER_ICON_URL) */
713 mprx.mcc_cbs.track_changed_ntf = mcc_track_changed_ntf_cb;
714 #if defined(CONFIG_BT_MCC_READ_TRACK_TITLE)
715 mprx.mcc_cbs.read_track_title = mcc_read_track_title_cb;
716 #endif /* defined(CONFIG_BT_MCC_READ_TRACK_TITLE) */
717 #if defined(CONFIG_BT_MCC_READ_TRACK_DURATION)
718 mprx.mcc_cbs.read_track_duration = mcc_read_track_duration_cb;
719 #endif /* defined(CONFIG_BT_MCC_READ_TRACK_DURATION) */
720 #if defined(CONFIG_BT_MCC_READ_TRACK_POSITION)
721 mprx.mcc_cbs.read_track_position = mcc_read_track_position_cb;
722 #endif /* defined(CONFIG_BT_MCC_READ_TRACK_POSITION) */
723 #if defined(CONFIG_BT_MCC_SET_TRACK_POSITION)
724 mprx.mcc_cbs.set_track_position = mcc_set_track_position_cb;
725 #endif /* defined(CONFIG_BT_MCC_SET_TRACK_POSITION) */
726 #if defined(CONFIG_BT_MCC_READ_PLAYBACK_SPEED)
727 mprx.mcc_cbs.read_playback_speed = mcc_read_playback_speed_cb;
728 #endif /* defined (CONFIG_BT_MCC_READ_PLAYBACK_SPEED) */
729 #if defined(CONFIG_BT_MCC_SET_PLAYBACK_SPEED)
730 mprx.mcc_cbs.set_playback_speed = mcc_set_playback_speed_cb;
731 #endif /* defined (CONFIG_BT_MCC_SET_PLAYBACK_SPEED) */
732 #if defined(CONFIG_BT_MCC_READ_SEEKING_SPEED)
733 mprx.mcc_cbs.read_seeking_speed = mcc_read_seeking_speed_cb;
734 #endif /* defined (CONFIG_BT_MCC_READ_SEEKING_SPEED) */
735 #ifdef CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS
736 mprx.mcc_cbs.read_segments_obj_id = mcc_read_segments_obj_id_cb;
737 mprx.mcc_cbs.read_current_track_obj_id = mcc_read_current_track_obj_id_cb;
738 mprx.mcc_cbs.read_next_track_obj_id = mcc_read_next_track_obj_id_cb;
739 mprx.mcc_cbs.read_parent_group_obj_id = mcc_read_parent_group_obj_id_cb;
740 mprx.mcc_cbs.read_current_group_obj_id = mcc_read_current_group_obj_id_cb;
741 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
742 #if defined(CONFIG_BT_MCC_READ_PLAYING_ORDER)
743 mprx.mcc_cbs.read_playing_order = mcc_read_playing_order_cb;
744 #endif /* defined(CONFIG_BT_MCC_READ_PLAYING_ORDER) */
745 #if defined(CONFIG_BT_MCC_SET_PLAYING_ORDER)
746 mprx.mcc_cbs.set_playing_order = mcc_set_playing_order_cb;
747 #endif /* defined(CONFIG_BT_MCC_SET_PLAYING_ORDER) */
748 #if defined(CONFIG_BT_MCC_READ_PLAYING_ORDER_SUPPORTED)
749 mprx.mcc_cbs.read_playing_orders_supported = mcc_read_playing_orders_supported_cb;
750 #endif /* defined(CONFIG_BT_MCC_READ_PLAYING_ORDER_SUPPORTED) */
751 #if defined(CONFIG_BT_MCC_READ_MEDIA_STATE)
752 mprx.mcc_cbs.read_media_state = mcc_read_media_state_cb;
753 #endif /* defined(CONFIG_BT_MCC_READ_MEDIA_STATE) */
754 #if defined(CONFIG_BT_MCC_SET_MEDIA_CONTROL_POINT)
755 mprx.mcc_cbs.send_cmd = mcc_send_cmd_cb;
756 #endif /* defined(CONFIG_BT_MCC_SET_MEDIA_CONTROL_POINT) */
757 mprx.mcc_cbs.cmd_ntf = mcc_cmd_ntf_cb;
758 #if defined(CONFIG_BT_MCC_READ_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED)
759 mprx.mcc_cbs.read_opcodes_supported = mcc_read_opcodes_supported_cb;
760 #endif /* defined(CONFIG_BT_MCC_READ_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED) */
761 #ifdef CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS
762 mprx.mcc_cbs.send_search = mcc_send_search_cb;
763 mprx.mcc_cbs.search_ntf = mcc_search_ntf_cb;
764 mprx.mcc_cbs.read_search_results_obj_id = mcc_read_search_results_obj_id_cb;
765 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
766 #if defined(CONFIG_BT_MCC_READ_CONTENT_CONTROL_ID)
767 mprx.mcc_cbs.read_content_control_id = mcc_read_content_control_id_cb;
768 #endif /* defined(CONFIG_BT_MCC_READ_CONTENT_CONTROL_ID) */
769
770 err = bt_mcc_init(&mprx.mcc_cbs);
771 if (err) {
772 LOG_ERR("Failed to initialize MCC");
773 return err;
774 }
775
776 /* Start discovery of remote MCS, subscribe to notifications */
777 err = bt_mcc_discover_mcs(conn, 1);
778 if (err) {
779 LOG_ERR("Discovery failed");
780 return err;
781 }
782
783 if (mprx.remote_player.conn != NULL) {
784 bt_conn_unref(mprx.remote_player.conn);
785 }
786 mprx.remote_player.conn = bt_conn_ref(conn);
787 mprx.remote_player.registered = true; /* TODO: Do MCC init and "registration" at startup */
788
789 return 0;
790 }
791 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL */
792
793
794 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL) || defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL)
media_proxy_ctrl_get_player_name(struct media_player * player)795 int media_proxy_ctrl_get_player_name(struct media_player *player)
796 {
797 CHECKIF(player == NULL) {
798 LOG_DBG("player is NULL");
799 return -EINVAL;
800 }
801
802 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
803 if (mprx.local_player.registered && player == &mprx.local_player) {
804 LOG_DBG("Local player");
805 if (mprx.local_player.calls->get_player_name) {
806 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->player_name_recv) {
807 const char *name = mprx.local_player.calls->get_player_name();
808
809 mprx.ctrlr.cbs->player_name_recv(&mprx.local_player, 0, name);
810 } else {
811 LOG_DBG("No callback");
812 }
813
814 return 0;
815 }
816
817 LOG_DBG("No call");
818 return -EOPNOTSUPP;
819 }
820 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
821
822 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL)
823 if (mprx.remote_player.registered && player == &mprx.remote_player) {
824 LOG_DBG("Remote player");
825 return bt_mcc_read_player_name(mprx.remote_player.conn);
826 }
827 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL */
828
829 return -EINVAL;
830 }
831
media_proxy_ctrl_get_icon_id(struct media_player * player)832 int media_proxy_ctrl_get_icon_id(struct media_player *player)
833 {
834 CHECKIF(player == NULL) {
835 LOG_DBG("player is NULL");
836 return -EINVAL;
837 }
838
839 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
840 if (mprx.local_player.registered && player == &mprx.local_player) {
841 if (mprx.local_player.calls->get_icon_id) {
842 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->icon_id_recv) {
843 const uint64_t id = mprx.local_player.calls->get_icon_id();
844
845 mprx.ctrlr.cbs->icon_id_recv(&mprx.local_player, 0, id);
846 } else {
847 LOG_DBG("No callback");
848 }
849
850 return 0;
851 }
852
853 LOG_DBG("No call");
854 return -EOPNOTSUPP;
855 }
856 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
857
858 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS)
859 if (mprx.remote_player.registered && player == &mprx.remote_player) {
860 return bt_mcc_read_icon_obj_id(mprx.remote_player.conn);
861 }
862 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
863
864 return -EINVAL;
865 }
866
media_proxy_ctrl_get_icon_url(struct media_player * player)867 int media_proxy_ctrl_get_icon_url(struct media_player *player)
868 {
869 CHECKIF(player == NULL) {
870 LOG_DBG("player is NULL");
871 return -EINVAL;
872 }
873
874 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
875 if (mprx.local_player.registered && player == &mprx.local_player) {
876 if (mprx.local_player.calls->get_icon_url) {
877 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->icon_url_recv) {
878 const char *url = mprx.local_player.calls->get_icon_url();
879
880 mprx.ctrlr.cbs->icon_url_recv(player, 0, url);
881 } else {
882 LOG_DBG("No callback");
883 }
884
885 return 0;
886 }
887
888 LOG_DBG("No call");
889 return -EOPNOTSUPP;
890 }
891 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
892
893 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && defined(CONFIG_BT_MCC_READ_MEDIA_PLAYER_ICON_URL)
894 if (mprx.remote_player.registered && player == &mprx.remote_player) {
895 return bt_mcc_read_icon_url(mprx.remote_player.conn);
896 }
897 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL && CONFIG_BT_MCC_READ_MEDIA_PLAYER_ICON_URL */
898
899 return -EINVAL;
900 }
901
media_proxy_ctrl_get_track_title(struct media_player * player)902 int media_proxy_ctrl_get_track_title(struct media_player *player)
903 {
904 CHECKIF(player == NULL) {
905 LOG_DBG("player is NULL");
906 return -EINVAL;
907 }
908
909 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
910 if (mprx.local_player.registered && player == &mprx.local_player) {
911 if (mprx.local_player.calls->get_track_title) {
912 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_title_recv) {
913
914 const char *title = mprx.local_player.calls->get_track_title();
915 mprx.ctrlr.cbs->track_title_recv(player, 0, title);
916 } else {
917 LOG_DBG("No callback");
918 }
919
920 return 0;
921 }
922
923 LOG_DBG("No call");
924 return -EOPNOTSUPP;
925 }
926 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
927
928 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && defined(CONFIG_BT_MCC_READ_TRACK_TITLE)
929 if (mprx.remote_player.registered && player == &mprx.remote_player) {
930 return bt_mcc_read_track_title(mprx.remote_player.conn);
931 }
932 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL && CONFIG_BT_MCC_READ_TRACK_TITLE */
933
934 return -EINVAL;
935 }
936
media_proxy_ctrl_get_track_duration(struct media_player * player)937 int media_proxy_ctrl_get_track_duration(struct media_player *player)
938 {
939 CHECKIF(player == NULL) {
940 LOG_DBG("player is NULL");
941 return -EINVAL;
942 }
943
944 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
945 if (mprx.local_player.registered && player == &mprx.local_player) {
946 if (mprx.local_player.calls->get_track_duration) {
947 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_duration_recv) {
948 const int32_t duration =
949 mprx.local_player.calls->get_track_duration();
950
951 mprx.ctrlr.cbs->track_duration_recv(player, 0, duration);
952 } else {
953 LOG_DBG("No callback");
954 }
955
956 return 0;
957 }
958
959 LOG_DBG("No call");
960 return -EOPNOTSUPP;
961 }
962 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
963
964 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && defined(CONFIG_BT_MCC_READ_TRACK_DURATION)
965 if (mprx.remote_player.registered && player == &mprx.remote_player) {
966 return bt_mcc_read_track_duration(mprx.remote_player.conn);
967 }
968 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL && CONFIG_BT_MCC_READ_TRACK_DURATION */
969
970 return -EINVAL;
971 }
972
media_proxy_ctrl_get_track_position(struct media_player * player)973 int media_proxy_ctrl_get_track_position(struct media_player *player)
974 {
975 CHECKIF(player == NULL) {
976 LOG_DBG("player is NULL");
977 return -EINVAL;
978 }
979
980 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
981 if (mprx.local_player.registered && player == &mprx.local_player) {
982 if (mprx.local_player.calls->get_track_position) {
983 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_position_recv) {
984 const int32_t position =
985 mprx.local_player.calls->get_track_position();
986
987 mprx.ctrlr.cbs->track_position_recv(player, 0, position);
988 } else {
989 LOG_DBG("No callback");
990 }
991
992 return 0;
993 }
994
995 LOG_DBG("No call");
996 return -EOPNOTSUPP;
997 }
998 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
999
1000 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && defined(CONFIG_BT_MCC_READ_TRACK_POSITION)
1001 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1002 return bt_mcc_read_track_position(mprx.remote_player.conn);
1003 }
1004 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL && CONFIG_BT_MCC_READ_TRACK_POSITION */
1005
1006 return -EINVAL;
1007 }
1008
media_proxy_ctrl_set_track_position(struct media_player * player,int32_t position)1009 int media_proxy_ctrl_set_track_position(struct media_player *player, int32_t position)
1010 {
1011 CHECKIF(player == NULL) {
1012 LOG_DBG("player is NULL");
1013 return -EINVAL;
1014 }
1015
1016 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1017 if (mprx.local_player.registered && player == &mprx.local_player) {
1018 if (mprx.local_player.calls->set_track_position) {
1019 mprx.local_player.calls->set_track_position(position);
1020
1021 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_position_write) {
1022 mprx.ctrlr.cbs->track_position_write(player, 0, position);
1023 } else {
1024 LOG_DBG("No callback");
1025 }
1026
1027 return 0;
1028 }
1029
1030 LOG_DBG("No call");
1031 return -EOPNOTSUPP;
1032 }
1033 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1034
1035 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && CONFIG_BT_MCC_SET_TRACK_POSITION
1036 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1037 return bt_mcc_set_track_position(mprx.remote_player.conn, position);
1038 }
1039 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL && CONFIG_BT_MCC_SET_TRACK_POSITION */
1040
1041 return -EINVAL;
1042 }
1043
media_proxy_ctrl_get_playback_speed(struct media_player * player)1044 int media_proxy_ctrl_get_playback_speed(struct media_player *player)
1045 {
1046 CHECKIF(player == NULL) {
1047 LOG_DBG("player is NULL");
1048 return -EINVAL;
1049 }
1050
1051 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1052 if (mprx.local_player.registered && player == &mprx.local_player) {
1053 if (mprx.local_player.calls->get_playback_speed) {
1054 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->playback_speed_recv) {
1055 const int8_t speed = mprx.local_player.calls->get_playback_speed();
1056
1057 mprx.ctrlr.cbs->playback_speed_recv(player, 0, speed);
1058 } else {
1059 LOG_DBG("No callback");
1060 }
1061
1062 return 0;
1063 }
1064
1065 LOG_DBG("No call");
1066 return -EOPNOTSUPP;
1067 }
1068 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1069
1070 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && defined(CONFIG_BT_MCC_READ_PLAYBACK_SPEED)
1071 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1072 return bt_mcc_read_playback_speed(mprx.remote_player.conn);
1073 }
1074 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL && CONFIG_BT_MCC_READ_PLAYBACK_SPEED */
1075
1076 return -EINVAL;
1077 }
1078
media_proxy_ctrl_set_playback_speed(struct media_player * player,int8_t speed)1079 int media_proxy_ctrl_set_playback_speed(struct media_player *player, int8_t speed)
1080 {
1081 CHECKIF(player == NULL) {
1082 LOG_DBG("player is NULL");
1083 return -EINVAL;
1084 }
1085
1086 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1087 if (mprx.local_player.registered && player == &mprx.local_player) {
1088 if (mprx.local_player.calls->set_playback_speed) {
1089 mprx.local_player.calls->set_playback_speed(speed);
1090
1091 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->playback_speed_write) {
1092 mprx.ctrlr.cbs->playback_speed_write(player, 0, speed);
1093 } else {
1094 LOG_DBG("No callback");
1095 }
1096
1097 return 0;
1098 }
1099
1100 LOG_DBG("No call");
1101 return -EOPNOTSUPP;
1102 }
1103 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1104
1105 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && defined(CONFIG_BT_MCC_SET_PLAYBACK_SPEED)
1106 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1107 return bt_mcc_set_playback_speed(mprx.remote_player.conn, speed);
1108 }
1109 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL && CONFIG_BT_MCC_SET_PLAYBACK_SPEED */
1110
1111 return -EINVAL;
1112 }
1113
media_proxy_ctrl_get_seeking_speed(struct media_player * player)1114 int media_proxy_ctrl_get_seeking_speed(struct media_player *player)
1115 {
1116 CHECKIF(player == NULL) {
1117 LOG_DBG("player is NULL");
1118 return -EINVAL;
1119 }
1120
1121 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1122 if (mprx.local_player.registered && player == &mprx.local_player) {
1123 if (mprx.local_player.calls->get_seeking_speed) {
1124 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->seeking_speed_recv) {
1125 const int8_t speed = mprx.local_player.calls->get_seeking_speed();
1126
1127 mprx.ctrlr.cbs->seeking_speed_recv(player, 0, speed);
1128 } else {
1129 LOG_DBG("No callback");
1130 }
1131
1132 return 0;
1133 }
1134
1135 LOG_DBG("No call");
1136 return -EOPNOTSUPP;
1137 }
1138 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1139
1140 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && defined(CONFIG_BT_MCC_READ_SEEKING_SPEED)
1141 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1142 return bt_mcc_read_seeking_speed(mprx.remote_player.conn);
1143 }
1144 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL && CONFIG_BT_MCC_READ_SEEKING_SPEED */
1145
1146 return -EINVAL;
1147 }
1148
media_proxy_ctrl_get_track_segments_id(struct media_player * player)1149 int media_proxy_ctrl_get_track_segments_id(struct media_player *player)
1150 {
1151 CHECKIF(player == NULL) {
1152 LOG_DBG("player is NULL");
1153 return -EINVAL;
1154 }
1155
1156 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1157 if (mprx.local_player.registered && player == &mprx.local_player) {
1158 if (mprx.local_player.calls->get_track_segments_id) {
1159 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_segments_id_recv) {
1160 const uint64_t id =
1161 mprx.local_player.calls->get_track_segments_id();
1162
1163 mprx.ctrlr.cbs->track_segments_id_recv(player, 0, id);
1164 } else {
1165 LOG_DBG("No callback");
1166 }
1167
1168 return 0;
1169 }
1170
1171 LOG_DBG("No call");
1172 return -EOPNOTSUPP;
1173 }
1174 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1175
1176 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS)
1177 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1178 return bt_mcc_read_segments_obj_id(mprx.remote_player.conn);
1179 }
1180 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
1181
1182 return -EINVAL;
1183 }
1184
media_proxy_ctrl_get_current_track_id(struct media_player * player)1185 int media_proxy_ctrl_get_current_track_id(struct media_player *player)
1186 {
1187 CHECKIF(player == NULL) {
1188 LOG_DBG("player is NULL");
1189 return -EINVAL;
1190 }
1191
1192 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1193 if (mprx.local_player.registered && player == &mprx.local_player) {
1194 if (mprx.local_player.calls->get_current_track_id) {
1195 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->current_track_id_recv) {
1196 const uint64_t id = mprx.local_player.calls->get_current_track_id();
1197
1198 mprx.ctrlr.cbs->current_track_id_recv(player, 0, id);
1199 } else {
1200 LOG_DBG("No callback");
1201 }
1202
1203 return 0;
1204 }
1205
1206 LOG_DBG("No call");
1207 return -EOPNOTSUPP;
1208 }
1209 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1210
1211 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS)
1212 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1213 return bt_mcc_read_current_track_obj_id(mprx.remote_player.conn);
1214 }
1215 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
1216
1217 return -EINVAL;
1218 }
1219
media_proxy_ctrl_set_current_track_id(struct media_player * player,uint64_t id)1220 int media_proxy_ctrl_set_current_track_id(struct media_player *player, uint64_t id)
1221 {
1222 CHECKIF(player == NULL) {
1223 LOG_DBG("player is NULL");
1224 return -EINVAL;
1225 }
1226
1227 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1228 CHECKIF(!BT_MCS_VALID_OBJ_ID(id)) {
1229 LOG_DBG("Object ID 0x%016llx invalid", id);
1230
1231 return -EINVAL;
1232 }
1233
1234 if (mprx.local_player.registered && player == &mprx.local_player) {
1235 if (mprx.local_player.calls->set_current_track_id) {
1236 mprx.local_player.calls->set_current_track_id(id);
1237
1238 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->current_track_id_write) {
1239 mprx.ctrlr.cbs->current_track_id_write(player, 0, id);
1240 } else {
1241 LOG_DBG("No callback");
1242 }
1243
1244 return 0;
1245 }
1246
1247 LOG_DBG("No call");
1248 return -EOPNOTSUPP;
1249 }
1250 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1251
1252 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS)
1253 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1254 /* TODO: Uncomment when function is implemented */
1255 /* return bt_mcc_set_current_track_obj_id(mprx.remote_player.conn, position); */
1256 }
1257 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
1258
1259 return -EINVAL;
1260 }
1261
media_proxy_ctrl_get_next_track_id(struct media_player * player)1262 int media_proxy_ctrl_get_next_track_id(struct media_player *player)
1263 {
1264 CHECKIF(player == NULL) {
1265 LOG_DBG("player is NULL");
1266 return -EINVAL;
1267 }
1268
1269 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1270 if (mprx.local_player.registered && player == &mprx.local_player) {
1271 if (mprx.local_player.calls->get_next_track_id) {
1272 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->next_track_id_recv) {
1273 const uint64_t id = mprx.local_player.calls->get_next_track_id();
1274
1275 mprx.ctrlr.cbs->next_track_id_recv(player, 0, id);
1276 } else {
1277 LOG_DBG("No callback");
1278 }
1279
1280 return 0;
1281 }
1282
1283 LOG_DBG("No call");
1284 return -EOPNOTSUPP;
1285 }
1286 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1287
1288 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS)
1289 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1290 return bt_mcc_read_next_track_obj_id(mprx.remote_player.conn);
1291 }
1292 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
1293
1294 return -EINVAL;
1295 }
1296
media_proxy_ctrl_set_next_track_id(struct media_player * player,uint64_t id)1297 int media_proxy_ctrl_set_next_track_id(struct media_player *player, uint64_t id)
1298 {
1299 CHECKIF(player == NULL) {
1300 LOG_DBG("player is NULL");
1301 return -EINVAL;
1302 }
1303
1304 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1305 CHECKIF(!BT_MCS_VALID_OBJ_ID(id)) {
1306 LOG_DBG("Object ID 0x%016llx invalid", id);
1307
1308 return -EINVAL;
1309 }
1310
1311 if (mprx.local_player.registered && player == &mprx.local_player) {
1312 if (mprx.local_player.calls->set_next_track_id) {
1313 mprx.local_player.calls->set_next_track_id(id);
1314
1315 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->next_track_id_write) {
1316 mprx.ctrlr.cbs->next_track_id_write(player, 0, id);
1317 } else {
1318 LOG_DBG("No callback");
1319 }
1320
1321 return 0;
1322 }
1323
1324 LOG_DBG("No call");
1325 return -EOPNOTSUPP;
1326 }
1327 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1328
1329 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS)
1330 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1331 /* TODO: Uncomment when function is implemented */
1332 /* return bt_mcc_set_next_track_obj_id(mprx.remote_player.conn, position); */
1333 }
1334 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
1335
1336 return -EINVAL;
1337 }
1338
media_proxy_ctrl_get_parent_group_id(struct media_player * player)1339 int media_proxy_ctrl_get_parent_group_id(struct media_player *player)
1340 {
1341 CHECKIF(player == NULL) {
1342 LOG_DBG("player is NULL");
1343 return -EINVAL;
1344 }
1345
1346 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1347 if (mprx.local_player.registered && player == &mprx.local_player) {
1348 if (mprx.local_player.calls->get_parent_group_id) {
1349 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->parent_group_id_recv) {
1350 const uint64_t id = mprx.local_player.calls->get_parent_group_id();
1351
1352 mprx.ctrlr.cbs->parent_group_id_recv(player, 0, id);
1353 } else {
1354 LOG_DBG("No callback");
1355 }
1356
1357 return 0;
1358 }
1359
1360 LOG_DBG("No call");
1361 return -EOPNOTSUPP;
1362 }
1363 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1364
1365 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS)
1366 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1367 return bt_mcc_read_parent_group_obj_id(mprx.remote_player.conn);
1368 }
1369 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
1370
1371 return -EINVAL;
1372 }
1373
media_proxy_ctrl_get_current_group_id(struct media_player * player)1374 int media_proxy_ctrl_get_current_group_id(struct media_player *player)
1375 {
1376 CHECKIF(player == NULL) {
1377 LOG_DBG("player is NULL");
1378 return -EINVAL;
1379 }
1380
1381 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1382 if (mprx.local_player.registered && player == &mprx.local_player) {
1383 if (mprx.local_player.calls->get_current_group_id) {
1384 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->current_group_id_recv) {
1385 const uint64_t id = mprx.local_player.calls->get_current_group_id();
1386
1387 mprx.ctrlr.cbs->current_group_id_recv(player, 0, id);
1388 } else {
1389 LOG_DBG("No callback");
1390 }
1391
1392 return 0;
1393 }
1394
1395 LOG_DBG("No call");
1396 return -EOPNOTSUPP;
1397 }
1398 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1399
1400 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS)
1401 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1402 return bt_mcc_read_current_group_obj_id(mprx.remote_player.conn);
1403 }
1404 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
1405
1406 return -EINVAL;
1407 }
1408
media_proxy_ctrl_set_current_group_id(struct media_player * player,uint64_t id)1409 int media_proxy_ctrl_set_current_group_id(struct media_player *player, uint64_t id)
1410 {
1411 CHECKIF(player == NULL) {
1412 LOG_DBG("player is NULL");
1413 return -EINVAL;
1414 }
1415
1416 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1417 CHECKIF(!BT_MCS_VALID_OBJ_ID(id)) {
1418 LOG_DBG("Object ID 0x%016llx invalid", id);
1419
1420 return -EINVAL;
1421 }
1422
1423 if (mprx.local_player.registered && player == &mprx.local_player) {
1424 if (mprx.local_player.calls->set_current_group_id) {
1425 mprx.local_player.calls->set_current_group_id(id);
1426
1427 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->current_group_id_write) {
1428 mprx.ctrlr.cbs->current_group_id_write(player, 0, id);
1429 } else {
1430 LOG_DBG("No callback");
1431 }
1432
1433 return 0;
1434 }
1435
1436 LOG_DBG("No call");
1437 return -EOPNOTSUPP;
1438 }
1439 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1440
1441 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS)
1442 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1443 /* TODO: Uncomment when function is implemented */
1444 /* return bt_mcc_set_current_group_obj_id(mprx.remote_player.conn, position); */
1445 }
1446 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
1447
1448 return -EINVAL;
1449 }
1450
media_proxy_ctrl_get_playing_order(struct media_player * player)1451 int media_proxy_ctrl_get_playing_order(struct media_player *player)
1452 {
1453 CHECKIF(player == NULL) {
1454 LOG_DBG("player is NULL");
1455 return -EINVAL;
1456 }
1457
1458 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1459 if (mprx.local_player.registered && player == &mprx.local_player) {
1460 if (mprx.local_player.calls->get_playing_order) {
1461 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->playing_order_recv) {
1462 const uint8_t order = mprx.local_player.calls->get_playing_order();
1463
1464 mprx.ctrlr.cbs->playing_order_recv(player, 0, order);
1465 } else {
1466 LOG_DBG("No callback");
1467 }
1468
1469 return 0;
1470 }
1471
1472 LOG_DBG("No call");
1473 return -EOPNOTSUPP;
1474 }
1475 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1476
1477 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && defined(CONFIG_BT_MCC_READ_PLAYING_ORDER)
1478 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1479 LOG_DBG("Remote player");
1480 return bt_mcc_read_playing_order(mprx.remote_player.conn);
1481 }
1482 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL && CONFIG_BT_MCC_READ_PLAYING_ORDER */
1483
1484 return -EINVAL;
1485 }
1486
media_proxy_ctrl_set_playing_order(struct media_player * player,uint8_t order)1487 int media_proxy_ctrl_set_playing_order(struct media_player *player, uint8_t order)
1488 {
1489 CHECKIF(player == NULL) {
1490 LOG_DBG("player is NULL");
1491 return -EINVAL;
1492 }
1493
1494 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1495 if (mprx.local_player.registered && player == &mprx.local_player) {
1496 if (mprx.local_player.calls->set_playing_order) {
1497 mprx.local_player.calls->set_playing_order(order);
1498
1499 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->playing_order_write) {
1500 mprx.ctrlr.cbs->playing_order_write(player, 0, order);
1501 } else {
1502 LOG_DBG("No callback");
1503 }
1504
1505 return 0;
1506 }
1507
1508 LOG_DBG("No call");
1509 return -EOPNOTSUPP;
1510 }
1511 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1512
1513 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && defined(CONFIG_BT_MCC_SET_PLAYING_ORDER)
1514 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1515 return bt_mcc_set_playing_order(mprx.remote_player.conn, order);
1516 }
1517 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL && CONFIG_BT_MCC_SET_PLAYING_ORDER */
1518
1519 return -EINVAL;
1520 }
1521
media_proxy_ctrl_get_playing_orders_supported(struct media_player * player)1522 int media_proxy_ctrl_get_playing_orders_supported(struct media_player *player)
1523 {
1524 CHECKIF(player == NULL) {
1525 LOG_DBG("player is NULL");
1526 return -EINVAL;
1527 }
1528
1529 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1530 if (mprx.local_player.registered && player == &mprx.local_player) {
1531 if (mprx.local_player.calls->get_playing_orders_supported) {
1532 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->playing_orders_supported_recv) {
1533 const uint16_t orders =
1534 mprx.local_player.calls->get_playing_orders_supported();
1535
1536 mprx.ctrlr.cbs->playing_orders_supported_recv(player, 0, orders);
1537 } else {
1538 LOG_DBG("No callback");
1539 }
1540
1541 return 0;
1542 }
1543
1544 LOG_DBG("No call");
1545 return -EOPNOTSUPP;
1546 }
1547 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1548
1549 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && \
1550 defined(CONFIG_BT_MCC_READ_PLAYING_ORDER_SUPPORTED)
1551 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1552 return bt_mcc_read_playing_orders_supported(mprx.remote_player.conn);
1553 }
1554 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL && CONFIG_BT_MCC_READ_PLAYING_ORDER_SUPPORTED */
1555
1556 return -EINVAL;
1557 }
1558
media_proxy_ctrl_get_media_state(struct media_player * player)1559 int media_proxy_ctrl_get_media_state(struct media_player *player)
1560 {
1561 CHECKIF(player == NULL) {
1562 LOG_DBG("player is NULL");
1563 return -EINVAL;
1564 }
1565
1566 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1567 if (mprx.local_player.registered && player == &mprx.local_player) {
1568 if (mprx.local_player.calls->get_media_state) {
1569 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->media_state_recv) {
1570 const uint8_t state = mprx.local_player.calls->get_media_state();
1571
1572 mprx.ctrlr.cbs->media_state_recv(player, 0, state);
1573 } else {
1574 LOG_DBG("No callback");
1575 }
1576
1577 return 0;
1578 }
1579
1580 LOG_DBG("No call");
1581 return -EOPNOTSUPP;
1582 }
1583 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1584
1585 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && defined(CONFIG_BT_MCC_READ_MEDIA_STATE)
1586 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1587 return bt_mcc_read_media_state(mprx.remote_player.conn);
1588 }
1589 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL && CONFIG_BT_MCC_READ_MEDIA_STATE */
1590
1591 return -EINVAL;
1592 }
1593
media_proxy_ctrl_send_command(struct media_player * player,const struct mpl_cmd * cmd)1594 int media_proxy_ctrl_send_command(struct media_player *player, const struct mpl_cmd *cmd)
1595 {
1596 CHECKIF(player == NULL || cmd == NULL) {
1597 LOG_DBG("NULL pointer");
1598 return -EINVAL;
1599 }
1600
1601 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1602 if (mprx.local_player.registered && player == &mprx.local_player) {
1603 if (mprx.local_player.calls->send_command) {
1604 mprx.local_player.calls->send_command(cmd);
1605
1606 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->command_send) {
1607 mprx.ctrlr.cbs->command_send(player, 0, cmd);
1608 } else {
1609 LOG_DBG("No callback");
1610 }
1611
1612 return 0;
1613 }
1614
1615 LOG_DBG("No call");
1616 return -EOPNOTSUPP;
1617 }
1618 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1619
1620 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && defined(CONFIG_BT_MCC_SET_MEDIA_CONTROL_POINT)
1621 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1622 return bt_mcc_send_cmd(mprx.remote_player.conn, cmd);
1623 }
1624 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL && CONFIG_BT_MCC_SET_MEDIA_CONTROL_POINT */
1625
1626 return -EINVAL;
1627 }
1628
media_proxy_ctrl_get_commands_supported(struct media_player * player)1629 int media_proxy_ctrl_get_commands_supported(struct media_player *player)
1630 {
1631 CHECKIF(player == NULL) {
1632 LOG_DBG("player is NULL");
1633 return -EINVAL;
1634 }
1635
1636 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1637 if (mprx.local_player.registered && player == &mprx.local_player) {
1638 if (mprx.local_player.calls->get_commands_supported) {
1639 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->commands_supported_recv) {
1640 const uint32_t opcodes =
1641 mprx.local_player.calls->get_commands_supported();
1642
1643 mprx.ctrlr.cbs->commands_supported_recv(player, 0, opcodes);
1644 } else {
1645 LOG_DBG("No callback");
1646 }
1647
1648 return 0;
1649 }
1650
1651 LOG_DBG("No call");
1652 return -EOPNOTSUPP;
1653 }
1654 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1655
1656 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && \
1657 defined(CONFIG_BT_MCC_READ_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED)
1658 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1659 return bt_mcc_read_opcodes_supported(mprx.remote_player.conn);
1660 }
1661 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL &&
1662 * CONFIG_BT_MCC_READ_MEDIA_CONTROL_POINT_OPCODES_SUPPORTED
1663 */
1664
1665 return -EINVAL;
1666 }
1667
media_proxy_ctrl_send_search(struct media_player * player,const struct mpl_search * search)1668 int media_proxy_ctrl_send_search(struct media_player *player, const struct mpl_search *search)
1669 {
1670 CHECKIF(player == NULL || search == NULL) {
1671 LOG_DBG("NULL pointer");
1672 return -EINVAL;
1673 }
1674
1675 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1676 if (mprx.local_player.registered && player == &mprx.local_player) {
1677 if (mprx.local_player.calls->send_search) {
1678 mprx.local_player.calls->send_search(search);
1679
1680 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->search_send) {
1681 mprx.ctrlr.cbs->search_send(player, 0, search);
1682 } else {
1683 LOG_DBG("No callback");
1684 }
1685
1686 return 0;
1687 }
1688
1689 LOG_DBG("No call");
1690 return -EOPNOTSUPP;
1691 }
1692 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1693
1694 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS)
1695 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1696 return bt_mcc_send_search(mprx.remote_player.conn, search);
1697 }
1698 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
1699
1700 return -EINVAL;
1701 }
1702
media_proxy_ctrl_get_search_results_id(struct media_player * player)1703 int media_proxy_ctrl_get_search_results_id(struct media_player *player)
1704 {
1705 CHECKIF(player == NULL) {
1706 LOG_DBG("player is NULL");
1707 return -EINVAL;
1708 }
1709
1710 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1711 if (mprx.local_player.registered && player == &mprx.local_player) {
1712 if (mprx.local_player.calls->get_search_results_id) {
1713 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->search_results_id_recv) {
1714 const uint64_t id =
1715 mprx.local_player.calls->get_search_results_id();
1716
1717 mprx.ctrlr.cbs->search_results_id_recv(player, 0, id);
1718 } else {
1719 LOG_DBG("No callback");
1720 }
1721
1722 return 0;
1723 }
1724
1725 LOG_DBG("No call");
1726 return -EOPNOTSUPP;
1727 }
1728 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1729
1730 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS)
1731 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1732 return bt_mcc_read_search_results_obj_id(mprx.remote_player.conn);
1733 }
1734 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL_OBJECTS */
1735
1736 return -EINVAL;
1737 }
1738
media_proxy_ctrl_get_content_ctrl_id(struct media_player * player)1739 uint8_t media_proxy_ctrl_get_content_ctrl_id(struct media_player *player)
1740 {
1741 CHECKIF(player == NULL) {
1742 LOG_DBG("player is NULL");
1743 return -EINVAL;
1744 }
1745
1746 #if defined(CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL)
1747 if (mprx.local_player.registered && player == &mprx.local_player) {
1748 if (mprx.local_player.calls->get_content_ctrl_id) {
1749 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->content_ctrl_id_recv) {
1750 const uint8_t ccid = mprx.local_player.calls->get_content_ctrl_id();
1751
1752 mprx.ctrlr.cbs->content_ctrl_id_recv(player, 0, ccid);
1753 } else {
1754 LOG_DBG("No callback");
1755 }
1756
1757 return 0;
1758 }
1759
1760 LOG_DBG("No call");
1761 return -EOPNOTSUPP;
1762 }
1763 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL */
1764
1765 #if defined(CONFIG_MCTL_REMOTE_PLAYER_CONTROL) && defined(CONFIG_BT_MCC_READ_CONTENT_CONTROL_ID)
1766 if (mprx.remote_player.registered && player == &mprx.remote_player) {
1767 return bt_mcc_read_content_control_id(mprx.remote_player.conn);
1768 }
1769 #endif /* CONFIG_MCTL_REMOTE_PLAYER_CONTROL && CONFIG_BT_MCC_READ_CONTENT_CONTROL_ID */
1770
1771 return -EINVAL;
1772 }
1773 #endif /* CONFIG_MCTL_LOCAL_PLAYER_LOCAL_CONTROL || CONFIG_MCTL_REMOTE_PLAYER_CONTROL */
1774
1775
1776
1777 #if defined(CONFIG_MCTL_LOCAL_PLAYER_CONTROL)
1778 /* Player calls *******************************************/
1779
pl_calls_is_valid(const struct media_proxy_pl_calls * pl_calls)1780 static bool pl_calls_is_valid(const struct media_proxy_pl_calls *pl_calls)
1781 {
1782 if (pl_calls == NULL) {
1783 LOG_DBG("pl_calls is NULL");
1784 return false;
1785 }
1786
1787 if (pl_calls->get_player_name == NULL) {
1788 LOG_DBG("get_player_name is NULL");
1789 return false;
1790 }
1791
1792 #ifdef CONFIG_BT_MPL_OBJECTS
1793 if (pl_calls->get_icon_id == NULL) {
1794 LOG_DBG("get_icon_id is NULL");
1795 return false;
1796 }
1797 #endif /* CONFIG_BT_MPL_OBJECTS */
1798
1799 if (pl_calls->get_icon_url == NULL) {
1800 LOG_DBG("get_icon_url is NULL");
1801 return false;
1802 }
1803
1804 if (pl_calls->get_track_title == NULL) {
1805 LOG_DBG("get_track_title is NULL");
1806 return false;
1807 }
1808
1809 if (pl_calls->get_track_duration == NULL) {
1810 LOG_DBG("get_track_duration is NULL");
1811 return false;
1812 }
1813
1814 if (pl_calls->get_track_position == NULL) {
1815 LOG_DBG("get_track_position is NULL");
1816 return false;
1817 }
1818
1819 if (pl_calls->set_track_position == NULL) {
1820 LOG_DBG("set_track_position is NULL");
1821 return false;
1822 }
1823
1824 if (pl_calls->get_playback_speed == NULL) {
1825 LOG_DBG("get_playback_speed is NULL");
1826 return false;
1827 }
1828
1829 if (pl_calls->set_playback_speed == NULL) {
1830 LOG_DBG("set_playback_speed is NULL");
1831 return false;
1832 }
1833
1834 if (pl_calls->get_seeking_speed == NULL) {
1835 LOG_DBG("get_seeking_speed is NULL");
1836 return false;
1837 }
1838
1839 #ifdef CONFIG_BT_MPL_OBJECTS
1840 if (pl_calls->get_track_segments_id == NULL) {
1841 LOG_DBG("get_track_segments_id is NULL");
1842 return false;
1843 }
1844
1845 if (pl_calls->get_current_track_id == NULL) {
1846 LOG_DBG("get_current_track_id is NULL");
1847 return false;
1848 }
1849
1850 if (pl_calls->set_current_track_id == NULL) {
1851 LOG_DBG("set_current_track_id is NULL");
1852 return false;
1853 }
1854
1855 if (pl_calls->get_next_track_id == NULL) {
1856 LOG_DBG("get_next_track_id is NULL");
1857 return false;
1858 }
1859
1860 if (pl_calls->set_next_track_id == NULL) {
1861 LOG_DBG("set_next_track_id is NULL");
1862 return false;
1863 }
1864
1865 if (pl_calls->get_parent_group_id == NULL) {
1866 LOG_DBG("get_parent_group_id is NULL");
1867 return false;
1868 }
1869
1870 if (pl_calls->get_current_group_id == NULL) {
1871 LOG_DBG("get_current_group_id is NULL");
1872 return false;
1873 }
1874
1875 if (pl_calls->set_current_group_id == NULL) {
1876 LOG_DBG("set_current_group_id is NULL");
1877 return false;
1878 }
1879
1880 #endif /* CONFIG_BT_MPL_OBJECTS */
1881 if (pl_calls->get_playing_order == NULL) {
1882 LOG_DBG("get_playing_order is NULL");
1883 return false;
1884 }
1885
1886 if (pl_calls->set_playing_order == NULL) {
1887 LOG_DBG("set_playing_order is NULL");
1888 return false;
1889 }
1890
1891 if (pl_calls->get_playing_orders_supported == NULL) {
1892 LOG_DBG("get_playing_orders_supported is NULL");
1893 return false;
1894 }
1895
1896 if (pl_calls->get_media_state == NULL) {
1897 LOG_DBG("get_media_state is NULL");
1898 return false;
1899 }
1900
1901 if (pl_calls->send_command == NULL) {
1902 LOG_DBG("send_command is NULL");
1903 return false;
1904 }
1905
1906 if (pl_calls->get_commands_supported == NULL) {
1907 LOG_DBG("get_commands_supported is NULL");
1908 return false;
1909 }
1910
1911 #ifdef CONFIG_BT_MPL_OBJECTS
1912 if (pl_calls->send_search == NULL) {
1913 LOG_DBG("send_search is NULL");
1914 return false;
1915 }
1916
1917 if (pl_calls->get_search_results_id == NULL) {
1918 LOG_DBG("get_search_results_id is NULL");
1919 return false;
1920 }
1921
1922 #endif /* CONFIG_BT_MPL_OBJECTS */
1923 if (pl_calls->get_content_ctrl_id == NULL) {
1924 LOG_DBG("get_content_ctrl_id is NULL");
1925 return false;
1926 }
1927
1928 return true;
1929 }
1930
media_proxy_pl_register(struct media_proxy_pl_calls * pl_calls)1931 int media_proxy_pl_register(struct media_proxy_pl_calls *pl_calls)
1932 {
1933 CHECKIF(!pl_calls_is_valid(pl_calls)) {
1934 return -EINVAL;
1935 }
1936
1937 if (mprx.local_player.registered) {
1938 LOG_DBG("Player already registered");
1939 return -EALREADY;
1940 }
1941
1942 mprx.local_player.calls = pl_calls;
1943 mprx.local_player.registered = true;
1944
1945 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->local_player_instance) {
1946 mprx.ctrlr.cbs->local_player_instance(&mprx.local_player, 0);
1947 }
1948
1949 return 0;
1950 };
1951
1952 /* Player callbacks ********************************/
1953
1954 /* All callbacks here must come from the local player - mprx.local_player */
1955
media_proxy_pl_name_cb(const char * name)1956 void media_proxy_pl_name_cb(const char *name)
1957 {
1958 mprx.sctrlr.cbs->player_name(name);
1959
1960 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->player_name_recv) {
1961 mprx.ctrlr.cbs->player_name_recv(&mprx.local_player, 0, name);
1962 } else {
1963 LOG_DBG("No ctrlr player name callback");
1964 }
1965 }
1966
media_proxy_pl_icon_url_cb(const char * url)1967 void media_proxy_pl_icon_url_cb(const char *url)
1968 {
1969 mprx.sctrlr.cbs->icon_url(url);
1970
1971 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->player_name_recv) {
1972 mprx.ctrlr.cbs->icon_url_recv(&mprx.local_player, 0, url);
1973 } else {
1974 LOG_DBG("No ctrlr player icon URL callback");
1975 }
1976 }
1977
media_proxy_pl_track_changed_cb(void)1978 void media_proxy_pl_track_changed_cb(void)
1979 {
1980 mprx.sctrlr.cbs->track_changed();
1981
1982 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_changed_recv) {
1983 mprx.ctrlr.cbs->track_changed_recv(&mprx.local_player, 0);
1984 } else {
1985 LOG_DBG("No ctrlr track changed callback");
1986 }
1987 }
1988
media_proxy_pl_track_title_cb(char * title)1989 void media_proxy_pl_track_title_cb(char *title)
1990 {
1991 mprx.sctrlr.cbs->track_title(title);
1992
1993 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_title_recv) {
1994 mprx.ctrlr.cbs->track_title_recv(&mprx.local_player, 0, title);
1995 } else {
1996 LOG_DBG("No ctrlr track title callback");
1997 }
1998 }
1999
media_proxy_pl_track_duration_cb(int32_t duration)2000 void media_proxy_pl_track_duration_cb(int32_t duration)
2001 {
2002 mprx.sctrlr.cbs->track_duration(duration);
2003
2004 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_duration_recv) {
2005 mprx.ctrlr.cbs->track_duration_recv(&mprx.local_player, 0, duration);
2006 } else {
2007 LOG_DBG("No ctrlr track duration callback");
2008 }
2009 }
2010
media_proxy_pl_track_position_cb(int32_t position)2011 void media_proxy_pl_track_position_cb(int32_t position)
2012 {
2013 mprx.sctrlr.cbs->track_position(position);
2014
2015 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->track_position_recv) {
2016 mprx.ctrlr.cbs->track_position_recv(&mprx.local_player, 0, position);
2017 } else {
2018 LOG_DBG("No ctrlr track position callback");
2019 }
2020 }
2021
media_proxy_pl_playback_speed_cb(int8_t speed)2022 void media_proxy_pl_playback_speed_cb(int8_t speed)
2023 {
2024 mprx.sctrlr.cbs->playback_speed(speed);
2025
2026 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->playback_speed_recv) {
2027 mprx.ctrlr.cbs->playback_speed_recv(&mprx.local_player, 0, speed);
2028 } else {
2029 LOG_DBG("No ctrlr playback speed callback");
2030 }
2031 }
2032
media_proxy_pl_seeking_speed_cb(int8_t speed)2033 void media_proxy_pl_seeking_speed_cb(int8_t speed)
2034 {
2035 mprx.sctrlr.cbs->seeking_speed(speed);
2036
2037 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->seeking_speed_recv) {
2038 mprx.ctrlr.cbs->seeking_speed_recv(&mprx.local_player, 0, speed);
2039 } else {
2040 LOG_DBG("No ctrlr seeking speed callback");
2041 }
2042 }
2043
2044 #ifdef CONFIG_BT_MPL_OBJECTS
media_proxy_pl_current_track_id_cb(uint64_t id)2045 void media_proxy_pl_current_track_id_cb(uint64_t id)
2046 {
2047 mprx.sctrlr.cbs->current_track_id(id);
2048
2049 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->current_track_id_recv) {
2050 mprx.ctrlr.cbs->current_track_id_recv(&mprx.local_player, 0, id);
2051 } else {
2052 LOG_DBG("No ctrlr current track id callback");
2053 }
2054 }
2055
media_proxy_pl_next_track_id_cb(uint64_t id)2056 void media_proxy_pl_next_track_id_cb(uint64_t id)
2057 {
2058 mprx.sctrlr.cbs->next_track_id(id);
2059
2060 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->next_track_id_recv) {
2061 mprx.ctrlr.cbs->next_track_id_recv(&mprx.local_player, 0, id);
2062 } else {
2063 LOG_DBG("No ctrlr next track id callback");
2064 }
2065 }
2066
media_proxy_pl_parent_group_id_cb(uint64_t id)2067 void media_proxy_pl_parent_group_id_cb(uint64_t id)
2068 {
2069 mprx.sctrlr.cbs->parent_group_id(id);
2070
2071 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->parent_group_id_recv) {
2072 mprx.ctrlr.cbs->parent_group_id_recv(&mprx.local_player, 0, id);
2073 } else {
2074 LOG_DBG("No ctrlr parent group id callback");
2075 }
2076 }
2077
media_proxy_pl_current_group_id_cb(uint64_t id)2078 void media_proxy_pl_current_group_id_cb(uint64_t id)
2079 {
2080 mprx.sctrlr.cbs->current_group_id(id);
2081
2082 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->current_group_id_recv) {
2083 mprx.ctrlr.cbs->current_group_id_recv(&mprx.local_player, 0, id);
2084 } else {
2085 LOG_DBG("No ctrlr current group id callback");
2086 }
2087 }
2088 #endif /* CONFIG_BT_MPL_OBJECTS */
2089
media_proxy_pl_playing_order_cb(uint8_t order)2090 void media_proxy_pl_playing_order_cb(uint8_t order)
2091 {
2092 mprx.sctrlr.cbs->playing_order(order);
2093
2094 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->playing_order_recv) {
2095 mprx.ctrlr.cbs->playing_order_recv(&mprx.local_player, 0, order);
2096 } else {
2097 LOG_DBG("No ctrlr playing order callback");
2098 }
2099 }
2100
media_proxy_pl_media_state_cb(uint8_t state)2101 void media_proxy_pl_media_state_cb(uint8_t state)
2102 {
2103 mprx.sctrlr.cbs->media_state(state);
2104
2105 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->media_state_recv) {
2106 mprx.ctrlr.cbs->media_state_recv(&mprx.local_player, 0, state);
2107 } else {
2108 LOG_DBG("No ctrlr media state callback");
2109 }
2110 }
2111
media_proxy_pl_command_cb(const struct mpl_cmd_ntf * cmd_ntf)2112 void media_proxy_pl_command_cb(const struct mpl_cmd_ntf *cmd_ntf)
2113 {
2114 CHECKIF(cmd_ntf == NULL) {
2115 LOG_WRN("cmd_ntf is NULL");
2116 return;
2117 }
2118
2119 mprx.sctrlr.cbs->command(cmd_ntf);
2120
2121 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->command_recv) {
2122 mprx.ctrlr.cbs->command_recv(&mprx.local_player, 0, cmd_ntf);
2123 } else {
2124 LOG_DBG("No ctrlr command callback");
2125 }
2126 }
2127
media_proxy_pl_commands_supported_cb(uint32_t opcodes)2128 void media_proxy_pl_commands_supported_cb(uint32_t opcodes)
2129 {
2130 mprx.sctrlr.cbs->commands_supported(opcodes);
2131
2132 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->commands_supported_recv) {
2133 mprx.ctrlr.cbs->commands_supported_recv(&mprx.local_player, 0, opcodes);
2134 } else {
2135 LOG_DBG("No ctrlr commands supported callback");
2136 }
2137 }
2138
2139 #ifdef CONFIG_BT_MPL_OBJECTS
media_proxy_pl_search_cb(uint8_t result_code)2140 void media_proxy_pl_search_cb(uint8_t result_code)
2141 {
2142 mprx.sctrlr.cbs->search(result_code);
2143
2144 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->search_recv) {
2145 mprx.ctrlr.cbs->search_recv(&mprx.local_player, 0, result_code);
2146 } else {
2147 LOG_DBG("No ctrlr search callback");
2148 }
2149 }
2150
media_proxy_pl_search_results_id_cb(uint64_t id)2151 void media_proxy_pl_search_results_id_cb(uint64_t id)
2152 {
2153 mprx.sctrlr.cbs->search_results_id(id);
2154
2155 if (mprx.ctrlr.cbs && mprx.ctrlr.cbs->search_results_id_recv) {
2156 mprx.ctrlr.cbs->search_results_id_recv(&mprx.local_player, 0, id);
2157 } else {
2158 LOG_DBG("No ctrlr search results id callback");
2159 }
2160 }
2161 #endif /* CONFIG_BT_MPL_OBJECTS */
2162 #endif /* CONFIG_MCTL_LOCAL_PLAYER_CONTROL */
2163