1Bluetooth: Media Control Profile Shell 2###################################### 3 4This document describes how to run the media control functionality, 5using the shell, both as a client and as a server. 6 7The media control server consists of to parts. There is a media 8player (mpl) that contains the logic to handle media, and there is a 9media control service (mcs) that serves as a GATT-based interface to 10the player. The media control client consists of one part, the GATT 11based client (mcc). 12 13The media control server may include an object transfer service (ots) 14and the media control client may include an object transfer client 15(otc). When these are included, a richer set of functionality is 16available. 17 18The media control server and client both implement the Generic Media 19Control Service (only), and do not use any underlying Media Control 20Services. 21 22Note that in the examples below, in many cases the debug output has 23been removed and long outputs may have been shortened to make the 24examples shorter and clearer. 25 26Also note that this documentation does not list all shell commands, it 27just shows examples of some of them. The set of commands is 28explorable from the mcc shell and the mpl shell, by typing :code:`mcc` 29or :code:`mpl` and pressing TAB. A help text for each command can be 30found by doing :samp:`mcc {<command>} help` or :samp:`mpl {<command>} help`. 31 32Overview 33******** 34 35A media player has a *name* and an *icon* that allows identification 36of the player for the user. 37 38The content of the media player is structured into tracks and groups. 39A media player has a number of groups. A group contains tracks and 40other groups. (In this implementation, a group only contains tracks, 41not other groups.) Tracks can be divided into segments. 42 43An active player will have a *current track*. This is the track that 44is playing now (if the player is playing). The current track has a 45*title*, a *duration* (given in hundredths of a second) and a 46*position* - the current position of the player within the track. 47 48There is also a *current group* (the group of the current track), a 49*parent group* (the parent group of the current group) and a *next 50track*. 51 52The media player is in a *state*, which will be one of playing, 53paused, seeking or inactive. When playing, playback happens at a 54given *playback speed*, and the tracks are played according to the 55*playing order*, which is one of the *playing orders supported*. 56Track changes are signalled as notifications of the *track changed* 57characteristic. When seeking (fast forward or fast rewind), the track 58position is moved according to the *seeking speed*. 59 60The *opcodes supported* tells which operations are supported by the 61player by writing to the *media control point*. There is also a 62*search control point* that allows to search for groups and tracks 63according to various criteria, with the result returned in the *search 64results*. 65 66Finally, the *content control ID* is used to associate the media 67player with an audio stream. 68 69 70Media Control Client (MCP) 71************************** 72 73The media control client is used to control, and to get information 74from, a media control server. Control is done by writing to one of 75the two control points, or by writing to other writable 76characteristics. Getting information is done by reading 77characteristics, or by configuring the server to send notifications. 78 79Using the media control client 80============================== 81 82Before use, the media control client must be initialized by the 83command :code:`mcc init`. 84 85To achieve a connection to the peer, the :code:`bt` commands must be 86used - :code:`bt init` followed by :code:`bt advertise on` (or 87:code:`bt connect` if the server is advertising). 88 89When the media control client is connected to a media control server, 90the client can discover the server's Generic Media Control Service, by 91giving the command :code:`mcc discover_mcs`. This will store the 92handles of the service, and (optionally, but default) subscribe to all 93notifications. 94 95After discovery, the media control client can read and write 96characteristics, including the media control point and the search 97control point. 98 99 100Example usage 101============= 102 103Setup 104----- 105 106.. code-block:: console 107 108 uart:~$ bt init 109 Bluetooth initialized 110 111 uart:~$ mcc init 112 MCC init complete 113 114 uart:~$ bt advertise on 115 Advertising started 116 Connected: F6:58:DC:27:F3:57 (random) 117 118 119When connected 120-------------- 121 122Service discovery (GMCS and included OTS): 123 124.. code-block:: console 125 126 uart:~$ mcc discover_mcs 127 <dbg> bt_mcc.bt_mcc_discover_mcs: start discovery of MCS primary service 128 <dbg> bt_mcc.discover_primary_func: [ATTRIBUTE] handle 0x00ae 129 <dbg> bt_mcc.discover_primary_func: Primary discovery complete 130 <dbg> bt_mcc.discover_primary_func: UUID: 2800 131 <dbg> bt_mcc.discover_primary_func: UUID: 8fd7 132 <dbg> bt_mcc.discover_primary_func: Start discovery of MCS characteristics 133 <dbg> bt_mcc.discover_mcs_char_func: [ATTRIBUTE] handle 0x00b0 134 <dbg> bt_mcc.discover_mcs_char_func: Player name, UUID: 8fa0 135 <dbg> bt_mcc.discover_mcs_char_func: [ATTRIBUTE] handle 0x00b2 136 <dbg> bt_mcc.discover_mcs_char_func: Icon Object, UUID: 8fa1 137 <dbg> bt_mcc.discover_mcs_char_func: [ATTRIBUTE] handle 0x00b4 138 <dbg> bt_mcc.discover_mcs_char_func: Icon URI, UUID: 8fa2 139 <dbg> bt_mcc.discover_mcs_char_func: [ATTRIBUTE] handle 0x00b6 140 <dbg> bt_mcc.discover_mcs_char_func: Track Changed, UUID: 8fa3 141 <dbg> bt_mcc.discover_mcs_char_func: Subscribing - handle: 0x00b6 142 [...] 143 <dbg> bt_mcc.discover_mcs_char_func: [ATTRIBUTE] handle 0x00ea 144 <dbg> bt_mcc.discover_mcs_char_func: Content Control ID, UUID: 8fb5 145 <dbg> bt_mcc.discover_mcs_char_func: Setup complete for MCS 146 <dbg> bt_mcc.discover_mcs_char_func: Start discovery of included services 147 <dbg> bt_mcc.discover_include_func: [ATTRIBUTE] handle 0x00af 148 <dbg> bt_mcc.discover_include_func: Include UUID 1825 149 <dbg> bt_mcc.discover_include_func: Discover include complete for MCS: OTS 150 <dbg> bt_mcc.discover_include_func: Start discovery of OTS characteristics 151 <dbg> bt_mcc.discover_otc_char_func: [ATTRIBUTE] handle 0x009c 152 <dbg> bt_mcc.discover_otc_char_func: OTS Features 153 [...] 154 <dbg> bt_mcc.discover_otc_char_func: [ATTRIBUTE] handle 0x00ac 155 <dbg> bt_mcc.discover_otc_char_func: Object Size 156 Discovery complete 157 <dbg> bt_otc.bt_otc_register: 0 158 <dbg> bt_otc.bt_otc_register: L2CAP psm 0x 25 sec_level 1 registered 159 <dbg> bt_mcc.discover_otc_char_func: Setup complete for OTS 1 / 1 160 uart:~$ 161 162 163Reading characteristics - the player name and the track duration as 164examples: 165 166.. code-block:: console 167 168 uart:~$ mcc read_player_name 169 Player name: My media player 170 4d 79 20 6d 65 64 69 61 20 70 6c 61 79 65 72 |My media player 171 172 uart:~$ mcc read_track_duration 173 Track duration: 6300 174 175Note that the value of some characteristics may be truncated due to 176being too long to fit in the ATT packet. Increasing the ATT MTU may 177help: 178 179.. code-block:: console 180 181 uart:~$ mcc read_track_title 182 Track title: Interlude #1 (Song for 183 184 uart:~$ gatt exchange-mtu 185 Exchange pending 186 Exchange successful 187 188 uart:~$ mcc read_track_title 189 Track title: Interlude #1 (Song for Alison) 190 191Writing characteristics - track position as an example: 192 193The track position is where the player "is" in the current track. 194Read the track position, change it by writing to it, confirm by 195reading it again. 196 197.. code-block:: console 198 199 uart:~$ mcc read_track_position 200 Track Position: 0 201 202 uart:~$ mcc set_track_position 500 203 Track Position: 500 204 205 uart:~$ mcc read_track_position 206 Track Position: 500 207 208 209Controlling the player via the control point: 210 211Writing to the control point allows the client to request the server 212to do operations like play, pause, fast forward, change track, change 213group and so on. Some operations (e.g. goto track) take an argument. 214Currently, raw opcode values are used as input to the control point 215shell command. These opcode values can be found in the mpl.h header 216file. 217 218Send the play command (opcode "1"), the command to go to track (opcode 219"52") number three, and the pause command (opcode "2"): 220 221.. code-block:: console 222 223 uart:~$ mcc set_cp 1 224 Media State: 1 225 Operation: 1, result: 1 226 Operation: 1, param: 0 227 228 uart:~$ mcc set_cp 52 3 229 Track changed 230 Track title: Interlude #3 (Levanto Seventy) 231 Track duration: 7800 232 Track Position: 0 233 Current Track Object ID: 0x000000000104 234 Next Track Object ID: 0x000000000105 235 Operation: 52, result: 1 236 Operation: 52, param: 3 237 238 uart:~$ mcc set_cp 2 239 Media State: 2 240 Operation: 2, result: 1 241 Operation: 2, param: 0 242 243 244 245Using the included object transfer client 246----------------------------------------- 247 248When object transfer is supported by both the client and the server, a 249larger set of characteristics is available. These include object IDs 250for the various track and group objects. These IDs can be used to 251select and download the corresponding objects from the server's object 252transfer service. 253 254 255Read the object ID of the current group object: 256 257.. code-block:: console 258 259 uart:~$ mcc read_current_group_obj_id 260 Current Group Object ID: 0x000000000107 261 262 263Select the object with that ID: 264 265.. code-block:: console 266 267 uart:~$ mcc ots_select 0x107 268 Selecting object succeeded 269 270 271Read the object's metadata: 272 273.. code-block:: console 274 275 uart:~$ mcc ots_read_metadata 276 Reading object metadata succeeded 277 <inf> bt_mcc: Object's meta data: 278 <inf> bt_mcc: Current size :35 279 <inf> bt_otc: --- Displaying 1 metadata records --- 280 <inf> bt_otc: Object ID: 0x000000000107 281 <inf> bt_otc: Object name: Joe Pass - Guitar Inte 282 <inf> bt_otc: Object Current Size: 35 283 <inf> bt_otc: Object Allocate Size: 35 284 <inf> bt_otc: Type: Group Obj Type 285 <inf> bt_otc: Properties:0x4 286 <inf> bt_otc: - read permitted 287 288 289Read the object itself: 290 291The object received is a group object. It consists of a series of 292records consisting of a type (track or group) and an object ID. 293 294.. code-block:: console 295 296 uart:~$ mcc ots_read_current_group_object 297 <dbg> bt_mcc.on_group_content: Object type: 0, object ID: 0x000000000102 298 <dbg> bt_mcc.on_group_content: Object type: 0, object ID: 0x000000000103 299 <dbg> bt_mcc.on_group_content: Object type: 0, object ID: 0x000000000104 300 <dbg> bt_mcc.on_group_content: Object type: 0, object ID: 0x000000000105 301 <dbg> bt_mcc.on_group_content: Object type: 0, object ID: 0x000000000106 302 303 304Search 305------ 306 307The search control point takes as its input a sequence of search 308control items, each consisting of length, type (e.g. track name or 309artist name) and parameter (the track name or artist name to search 310for). If the result is successful, the search results are stored in 311an object in the object transfer service. The ID of the search 312results ID object can be read from the search results object ID 313characteristic. The search result object can then be downloaded as 314for the current group object above. (Note that the search results 315object ID is empty until a search has been done.) 316 317This implementation has a working implementation of the search 318functionality interface and the server-side search control point 319parameter parsing. But the **actual searching is faked**, the same 320results are returned no matter what is searched for. 321 322There are two commands for search, one (:code:`mcc set_scp_raw`) 323allows to input the search control point parameter (the sequence of 324search control items) as a string. The other (:code:`mcc 325set_scp_ioptest`) does preset IOP test searches and takes the round 326number of the IOP search control point test as a parameter. 327 328Before the search, the search results object ID is empty 329 330.. code-block:: console 331 332 uart:~$ mcc read_search_results_obj_id 333 Search Results Object ID: 0x000000000000 334 <dbg> bt_mcc.mcc_read_search_results_obj_id_cb: Zero-length Search Results Object ID 335 336Run the search corresponding to the fourth round of the IOP test: 337 338The search control point parameter generated by this command and 339parameter has one search control item. The length field (first octet) 340is 16 (0x10). (The length of the length field itself is not 341included.) The type field (second octet) is 0x04 (search for a group 342name). The parameter (the group name to search for) is 343"TSPX_Group_Name". 344 345.. code-block:: console 346 347 uart:~$ mcc set_scp_ioptest 4 348 Search string: 349 00000000: 10 04 54 53 50 58 5f 47 72 6f 75 70 5f 4e 61 6d |..TSPX_G roup_Nam| 350 00000010: 65 |e | 351 Search control point notification result code: 1 352 Search Results Object ID: 0x000000000107 353 Search Control Point set 354 355After the successful search, the search results object ID has a value: 356 357.. code-block:: console 358 359 uart:~$ mcc read_search_results_obj_id 360 Search Results Object ID: 0x000000000107 361 362 363Media Control Service (MCS) 364*************************** 365 366The media control service (mcs) and the associated media player (mpl) 367typically reside on devices that can provide access to, and serve, 368media content, like PCs and smartphones. 369 370As mentioned above, the media player (mpl) has the player logic, while 371the media control service (mcs) has the GATT-based interface. This 372separation is done so that the media player can also be used without 373the GATT-based interface. 374 375 376Using the media control service and the media player 377==================================================== 378 379The media control service and the media player are in general 380controlled remotely, from the media control client. 381 382Before use, the media control client must be initialized by the 383command :code:`mpl init`. 384 385As for the client, the :code:`bt` commands are used for connecting - 386:code:`bt init` followed by :code:`bt connect <address> <address 387type>` (or :code:`bt advertise on` if the server is advertising). 388 389 390Example Usage 391============= 392 393Setup 394----- 395 396.. code-block:: console 397 398 uart:~$ bt init 399 Bluetooth initialized 400 401 uart:~$ mpl init 402 [Large amounts of debug output] 403 404 uart:~$ bt connect F9:33:3B:67:D2:A7 (random) 405 Connection pending 406 Connected: F9:33:3B:67:D2:A7 (random) 407 408 409When connected 410-------------- 411 412Control is done from the client. 413 414The server will give debug output related to the various operations 415performed by the client. 416 417Example: Debug output by the server when the client gives the "next 418track" command: 419 420.. code-block:: console 421 422 [00:13:29.932,373] <dbg> bt_mcs.control_point_write: Opcode: 49 423 [00:13:29.932,403] <dbg> bt_mpl.mpl_operation_set: opcode: 49, param: 536880068 424 [00:13:29.932,403] <dbg> bt_mpl.paused_state_operation_handler: Operation opcode: 49 425 [00:13:29.932,495] <dbg> bt_mpl.do_next_track: Track ID before: 0x000000000104 426 [00:13:29.932,586] <dbg> bt_mpl.do_next_track: Track ID after: 0x000000000105 427 [00:13:29.932,617] <dbg> bt_mcs.mpl_track_changed_cb: Notifying track change 428 [00:13:29.932,708] <dbg> bt_mcs.mpl_track_title_cb: Notifying track title: Interlude #4 (Vesper Dreams) 429 [00:13:29.932,800] <dbg> bt_mcs.mpl_track_duration_cb: Notifying track duration: 13500 430 [00:13:29.932,861] <dbg> bt_mcs.mpl_track_position_cb: Notifying track position: 0 431 [00:13:29.933,044] <dbg> bt_mcs.mpl_current_track_id_cb: Notifying current track ID: 0x000000000105 432 [00:13:29.933,258] <dbg> bt_mcs.mpl_next_track_id_cb: Notifying next track ID: 0x000000000106 433 [00:13:29.933,380] <dbg> bt_mcs.mpl_operation_cb: Notifying control point - opcode: 49, result: 1 434 435 436Some server commands are available. These commands force 437notifications of the various characteristics, for testing that the 438client receives notifications. The values sent in the notifications 439caused by these testing commands are independent of the media player, 440so they do not correspond the actual values of the characteristics nor 441to the actual state of the media player. 442 443Example: Force (fake value) notification of the track duration: 444 445.. code-block:: console 446 447 uart:~$ mpl duration_changed_cb 448 [00:15:17.491,058] <dbg> bt_mcs.mpl_track_duration_cb: Notifying track duration: 12000 449