|
| 1 | +// use integration library in a client project: |
| 2 | +// import * as uc from "@unfoldedcircle/integration-api"; |
| 3 | +// individual classes and enums can also be imported |
| 4 | +import * as uc from "../../dist/cjs/index.js"; |
| 5 | +import { |
| 6 | + BrowseMediaItem, |
| 7 | + BrowseResult, |
| 8 | + KnownMediaClass, |
| 9 | + KnownMediaContentType, |
| 10 | + MediaPlayerAttributes, |
| 11 | + MediaPlayerDeviceClasses, |
| 12 | + MediaPlayerFeatures, |
| 13 | + MediaPlayerStates |
| 14 | +} from "../../dist/cjs/index.js"; |
| 15 | + |
| 16 | +const driver = new uc.IntegrationAPI(); |
| 17 | + |
| 18 | +driver.init("media_player.json"); |
| 19 | + |
| 20 | +driver.on(uc.Events.Connect, async () => { |
| 21 | + await driver.setDeviceState(uc.DeviceStates.Connected); |
| 22 | +}); |
| 23 | + |
| 24 | +driver.on(uc.Events.Disconnect, async () => { |
| 25 | + await driver.setDeviceState(uc.DeviceStates.Disconnected); |
| 26 | +}); |
| 27 | + |
| 28 | +class MediaPlayer extends uc.MediaPlayer { |
| 29 | + constructor() { |
| 30 | + super( |
| 31 | + "test_mediaplayer", |
| 32 | + { en: "Foobar MediaPlayer" }, |
| 33 | + { |
| 34 | + features: [ |
| 35 | + MediaPlayerFeatures.OnOff, |
| 36 | + MediaPlayerFeatures.Dpad, |
| 37 | + MediaPlayerFeatures.Home, |
| 38 | + MediaPlayerFeatures.Menu, |
| 39 | + MediaPlayerFeatures.ChannelSwitcher, |
| 40 | + MediaPlayerFeatures.SelectSource, |
| 41 | + MediaPlayerFeatures.PlayPause, |
| 42 | + MediaPlayerFeatures.PlayMedia, |
| 43 | + MediaPlayerFeatures.PlayMediaAction, |
| 44 | + MediaPlayerFeatures.ClearPlaylist, |
| 45 | + MediaPlayerFeatures.BrowseMedia, |
| 46 | + MediaPlayerFeatures.SearchMedia, |
| 47 | + MediaPlayerFeatures.SearchMediaClasses |
| 48 | + ], |
| 49 | + attributes: { |
| 50 | + [MediaPlayerAttributes.State]: MediaPlayerStates.Off, |
| 51 | + [MediaPlayerAttributes.SourceList]: ["Radio", "Streaming", "Favorite 1", "Favorite 2", "Favorite 3"], |
| 52 | + [MediaPlayerAttributes.SearchMediaClasses]: [ |
| 53 | + KnownMediaClass.Album, |
| 54 | + KnownMediaClass.Artist, |
| 55 | + KnownMediaClass.Music, |
| 56 | + KnownMediaClass.Radio |
| 57 | + ] |
| 58 | + }, |
| 59 | + deviceClass: MediaPlayerDeviceClasses.StreamingBox |
| 60 | + } |
| 61 | + ); |
| 62 | + } |
| 63 | + |
| 64 | + async command(cmdId, params) { |
| 65 | + const parameters = params ? JSON.stringify(params) : ""; |
| 66 | + console.log(`Got media-player command request: ${cmdId} ${parameters}`); |
| 67 | + |
| 68 | + return uc.StatusCodes.Ok; |
| 69 | + } |
| 70 | + |
| 71 | + async browse(options) { |
| 72 | + const paging = options.paging; |
| 73 | + console.log( |
| 74 | + "Media browsing request for %s: media_id=%s, media_type=%s, offset=%d, limit=%d", |
| 75 | + this.id, |
| 76 | + options.media_id, |
| 77 | + options.media_type, |
| 78 | + paging.offset, |
| 79 | + paging.limit |
| 80 | + ); |
| 81 | + |
| 82 | + if (options.media_id === undefined && options.media_type === undefined) { |
| 83 | + if (paging.page > 1) { |
| 84 | + return BrowseResult.empty(); |
| 85 | + } |
| 86 | + |
| 87 | + return this.browseRoot(paging); |
| 88 | + } |
| 89 | + |
| 90 | + switch (options.media_id) { |
| 91 | + case "favorites": |
| 92 | + return this.browseFavorites(paging); |
| 93 | + case "radio": |
| 94 | + return this.browseRadio(paging); |
| 95 | + case "albums": |
| 96 | + return this.browseAlbums(paging); |
| 97 | + default: |
| 98 | + return BrowseResult.empty(); |
| 99 | + } |
| 100 | + } |
| 101 | + |
| 102 | + async search(options) { |
| 103 | + const paging = options.paging; |
| 104 | + console.log( |
| 105 | + "Media searching request for %s: '%s', media_id=%s, media_type=%s, filter=%s, offset=%d, limit=%d", |
| 106 | + this.id, |
| 107 | + options.query, |
| 108 | + options.media_id, |
| 109 | + options.media_type, |
| 110 | + JSON.stringify(options.filter), |
| 111 | + paging.offset, |
| 112 | + paging.limit |
| 113 | + ); |
| 114 | + |
| 115 | + return uc.StatusCodes.NotImplemented; |
| 116 | + } |
| 117 | + |
| 118 | + browseRoot(paging) { |
| 119 | + const root = new BrowseMediaItem("", "Media Directory", { |
| 120 | + media_class: KnownMediaClass.Directory, |
| 121 | + can_browse: true, |
| 122 | + items: [ |
| 123 | + new BrowseMediaItem("favorites", "Favorites", { |
| 124 | + media_class: KnownMediaClass.Directory, |
| 125 | + can_browse: true, |
| 126 | + can_play: true |
| 127 | + }), |
| 128 | + new BrowseMediaItem("radio", "Radio", { |
| 129 | + media_class: KnownMediaClass.Radio, |
| 130 | + can_browse: true |
| 131 | + }), |
| 132 | + new BrowseMediaItem("albums", "Albums", { |
| 133 | + media_class: KnownMediaClass.Directory, |
| 134 | + can_browse: true |
| 135 | + }) |
| 136 | + ] |
| 137 | + }); |
| 138 | + return new BrowseResult(root, new uc.Pagination(1, root.items.length, root.items.length)); |
| 139 | + } |
| 140 | + |
| 141 | + browseFavorites(paging) { |
| 142 | + const maxFavorites = 99; |
| 143 | + const items = []; |
| 144 | + for (let i = paging.offset; i < paging.offset + paging.limit; i++) { |
| 145 | + const favId = i + 1; |
| 146 | + if (favId > maxFavorites) { |
| 147 | + break; |
| 148 | + } |
| 149 | + items.push( |
| 150 | + new BrowseMediaItem(`library://favorite/${favId}`, `Favorite ${favId}`, { |
| 151 | + media_class: KnownMediaClass.Directory, |
| 152 | + media_type: KnownMediaContentType.Music, |
| 153 | + can_play: true |
| 154 | + }) |
| 155 | + ); |
| 156 | + } |
| 157 | + const favorites = new BrowseMediaItem("favorites", "Favorites", { |
| 158 | + media_class: KnownMediaClass.Directory, |
| 159 | + can_browse: true, |
| 160 | + can_play: true, |
| 161 | + items: items |
| 162 | + }); |
| 163 | + return BrowseResult.fromPaging(favorites, paging, maxFavorites); |
| 164 | + } |
| 165 | + |
| 166 | + browseRadio(paging) { |
| 167 | + const radios = [ |
| 168 | + new BrowseMediaItem("library://radio/1", "RTS Couleur 3", { |
| 169 | + media_class: KnownMediaClass.Radio, |
| 170 | + media_type: KnownMediaContentType.Radio, |
| 171 | + can_play: true |
| 172 | + }), |
| 173 | + new BrowseMediaItem("library://radio/3", "Bassdrive", { |
| 174 | + media_class: KnownMediaClass.Radio, |
| 175 | + media_type: KnownMediaContentType.Radio, |
| 176 | + can_play: true |
| 177 | + }), |
| 178 | + new BrowseMediaItem("library://radio/4", "BBC Radio 1", { |
| 179 | + media_class: KnownMediaClass.Radio, |
| 180 | + media_type: KnownMediaContentType.Radio, |
| 181 | + can_play: true |
| 182 | + }) |
| 183 | + ]; |
| 184 | + const items = []; |
| 185 | + for (let i = paging.offset; i < paging.offset + paging.limit; i++) { |
| 186 | + if (i < radios.length) { |
| 187 | + items.push(radios[i]); |
| 188 | + } |
| 189 | + } |
| 190 | + |
| 191 | + const radio = new BrowseMediaItem("radio", "Radio", { |
| 192 | + media_class: KnownMediaClass.Directory, |
| 193 | + can_browse: true, |
| 194 | + items: items |
| 195 | + }); |
| 196 | + return BrowseResult.fromPaging(radio, paging, 3); |
| 197 | + } |
| 198 | + |
| 199 | + browseAlbums(paging) { |
| 200 | + const maxAlbums = 1234; |
| 201 | + const items = []; |
| 202 | + for (let i = paging.offset; i < paging.offset + paging.limit; i++) { |
| 203 | + const albumId = i + 1; |
| 204 | + if (albumId > maxAlbums) { |
| 205 | + break; |
| 206 | + } |
| 207 | + items.push( |
| 208 | + new BrowseMediaItem(`library://album/${albumId}`, `Album ${albumId}`, { |
| 209 | + media_class: KnownMediaClass.Album, |
| 210 | + media_type: KnownMediaContentType.Album, |
| 211 | + can_play: true |
| 212 | + }) |
| 213 | + ); |
| 214 | + } |
| 215 | + const albums = new BrowseMediaItem("albums", "Albums", { |
| 216 | + media_class: KnownMediaClass.Directory, |
| 217 | + can_browse: true, |
| 218 | + items: items |
| 219 | + }); |
| 220 | + return BrowseResult.fromPaging(albums, paging, maxAlbums); |
| 221 | + } |
| 222 | +} |
| 223 | + |
| 224 | +// add a media-player entity |
| 225 | +const mediaPlayerEntity = new MediaPlayer(); |
| 226 | + |
| 227 | +driver.addAvailableEntity(mediaPlayerEntity); |
0 commit comments