@christianriedl/media 1.0.300 → 1.0.302

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/iMedia.d.ts CHANGED
@@ -317,3 +317,42 @@ export interface IMediaService {
317
317
  getCloudUrl(folder: string, name: string): Promise<string>;
318
318
  getStatus(): Promise<Dictionary<boolean | number | string> | null>;
319
319
  }
320
+ export interface IRssFeed {
321
+ title: string;
322
+ description: string;
323
+ link: string;
324
+ copyright?: string;
325
+ items?: IRssFeed[];
326
+ mediaType?: string;
327
+ duration?: number;
328
+ }
329
+ export declare const getPlaylistSymbol: InjectionKey<() => IPlaylistService>;
330
+ export declare enum EPlaylistCommand {
331
+ None = 0,
332
+ Play = 1,
333
+ Pause = 2,
334
+ Resume = 3,
335
+ Stop = 4,
336
+ Next = 5,
337
+ Previous = 6
338
+ }
339
+ export interface IPlaylistState {
340
+ state: string;
341
+ device: string;
342
+ title: string;
343
+ url: string;
344
+ position: string;
345
+ }
346
+ export interface IPlaylistService {
347
+ log: ILogger;
348
+ soundbarOn: boolean;
349
+ getTitles(): Promise<string[]>;
350
+ getFeed(title: string): Promise<IRssFeed | null>;
351
+ getFeeds(): Promise<IRssFeed[]>;
352
+ addFeed(url: string, save: boolean): Promise<IRssFeed | null>;
353
+ deleteFeed(title: string): Promise<boolean>;
354
+ play(url: string): Promise<boolean>;
355
+ playList(urls: string[], clear: boolean, index?: number): Promise<boolean>;
356
+ playCommand(cmd: EPlaylistCommand): Promise<boolean>;
357
+ getState(): Promise<IPlaylistState | null>;
358
+ }
package/dist/iMedia.js CHANGED
@@ -121,4 +121,15 @@ export var EPictureFlags;
121
121
  EPictureFlags[EPictureFlags["Mask"] = 240] = "Mask";
122
122
  })(EPictureFlags || (EPictureFlags = {}));
123
123
  export const getMediaSymbol = Symbol("get-media");
124
+ export const getPlaylistSymbol = Symbol("get-playlist");
125
+ export var EPlaylistCommand;
126
+ (function (EPlaylistCommand) {
127
+ EPlaylistCommand[EPlaylistCommand["None"] = 0] = "None";
128
+ EPlaylistCommand[EPlaylistCommand["Play"] = 1] = "Play";
129
+ EPlaylistCommand[EPlaylistCommand["Pause"] = 2] = "Pause";
130
+ EPlaylistCommand[EPlaylistCommand["Resume"] = 3] = "Resume";
131
+ EPlaylistCommand[EPlaylistCommand["Stop"] = 4] = "Stop";
132
+ EPlaylistCommand[EPlaylistCommand["Next"] = 5] = "Next";
133
+ EPlaylistCommand[EPlaylistCommand["Previous"] = 6] = "Previous";
134
+ })(EPlaylistCommand || (EPlaylistCommand = {}));
124
135
  //# sourceMappingURL=iMedia.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"iMedia.js","sourceRoot":"","sources":["../src/iMedia.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"iMedia.js","sourceRoot":"","sources":["../src/iMedia.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -4,6 +4,7 @@ export * from './mediaHelper';
4
4
  export * from './locationHelper';
5
5
  export * from './mediaInstanceService';
6
6
  export * from './playerService';
7
+ export * from './playlistService';
7
8
  export * from './mediaServiceBin';
8
9
  export * from './iBooks';
9
10
  export * from './booksService';
package/dist/index.js CHANGED
@@ -5,6 +5,7 @@ export * from './mediaHelper';
5
5
  export * from './locationHelper';
6
6
  export * from './mediaInstanceService';
7
7
  export * from './playerService';
8
+ export * from './playlistService';
8
9
  export * from './mediaServiceBin';
9
10
  export * from './iBooks';
10
11
  export * from './booksService';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,kBAAkB,CAAC;AACjC,iCAAiC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,kBAAkB,CAAC;AACjC,iCAAiC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { IRest } from '@christianriedl/rest';
2
+ import { ILogger } from '@christianriedl/utils';
3
+ import { IRssFeed, EPlaylistCommand, IPlaylistState, IPlaylistService } from "./iMedia";
4
+ export declare class PlaylistService implements IPlaylistService {
5
+ rest: IRest;
6
+ mediaUrl: string;
7
+ log: ILogger;
8
+ soundbarOn: boolean;
9
+ setSoundbar: (name: string, value: string) => Promise<boolean>;
10
+ getSoundbarValue: (name: string) => string;
11
+ constructor(rest: IRest, log: ILogger, getSoundbarValue: (name: string) => string, setSoundbar: (name: string, value: string) => Promise<boolean>);
12
+ getTitles(): Promise<string[]>;
13
+ getFeed(title: string): Promise<IRssFeed | null>;
14
+ getFeeds(): Promise<IRssFeed[]>;
15
+ addFeed(url: string, save: boolean): Promise<IRssFeed | null>;
16
+ deleteFeed(title: string): Promise<boolean>;
17
+ play(url: string): Promise<boolean>;
18
+ playList(urls: string[], clear: boolean, index?: number): Promise<boolean>;
19
+ playCommand(cmd: EPlaylistCommand): Promise<boolean>;
20
+ getState(): Promise<IPlaylistState | null>;
21
+ ensureOn(): Promise<boolean>;
22
+ }
@@ -0,0 +1,86 @@
1
+ import { Helper } from '@christianriedl/utils';
2
+ import { EPlaylistCommand } from "./iMedia";
3
+ export class PlaylistService {
4
+ rest;
5
+ mediaUrl;
6
+ log;
7
+ soundbarOn;
8
+ setSoundbar;
9
+ getSoundbarValue;
10
+ constructor(rest, log, getSoundbarValue, setSoundbar) {
11
+ this.log = log;
12
+ this.rest = rest;
13
+ this.mediaUrl = rest.serviceUrl;
14
+ this.getSoundbarValue = getSoundbarValue;
15
+ this.setSoundbar = setSoundbar;
16
+ this.soundbarOn = false;
17
+ }
18
+ async getTitles() {
19
+ const res = await this.rest.getData('apiplaylist/title');
20
+ return res.ok ? res.result : [];
21
+ }
22
+ async getFeed(title) {
23
+ const res = await this.rest.getData('apiplaylist/feed', { title: title });
24
+ return res.ok ? res.result : null;
25
+ }
26
+ async getFeeds() {
27
+ const res = await this.rest.getData('apiplaylist/feed');
28
+ return res.ok ? res.result : [];
29
+ }
30
+ async addFeed(url, save) {
31
+ const res = await this.rest.postDataEx(`apiplaylist/feed?url=${encodeURIComponent(url)}&save=${save}`);
32
+ return res.ok ? res.result.result : null;
33
+ }
34
+ async deleteFeed(title) {
35
+ const res = await this.rest.deleteData(`apiplaylist/feed?title=${encodeURIComponent(title)}`);
36
+ return res.ok ? res.result : false;
37
+ }
38
+ async play(url) {
39
+ this.soundbarOn = await this.ensureOn();
40
+ if (!this.soundbarOn)
41
+ return false;
42
+ const res = await this.rest.postData(`apiplaylist/play?url=${encodeURIComponent(url)}`);
43
+ return res.ok ? res.result : false;
44
+ }
45
+ async playList(urls, clear, index) {
46
+ this.soundbarOn = await this.ensureOn();
47
+ if (!this.soundbarOn)
48
+ return false;
49
+ let url = `apiplaylist/play?clear=${clear}`;
50
+ if (index !== undefined)
51
+ url += `&index=${index}`;
52
+ const res = await this.rest.postData(url, urls);
53
+ return res.ok ? res.result : false;
54
+ }
55
+ async playCommand(cmd) {
56
+ this.soundbarOn = await this.ensureOn();
57
+ if (!this.soundbarOn)
58
+ return false;
59
+ let url = `apiplaylist/playcommand?cmd=${EPlaylistCommand[cmd]}`;
60
+ const res = await this.rest.postData(url);
61
+ return res.ok ? res.result : false;
62
+ }
63
+ async getState() {
64
+ const res = await this.rest.getData('apiplaylist/state');
65
+ return res.ok ? res.result : null;
66
+ }
67
+ async ensureOn() {
68
+ let i = 0;
69
+ for (i = 0; i < 5; i++) {
70
+ if (this.getSoundbarValue('ON') === 'ON')
71
+ break;
72
+ const result = await this.setSoundbar('POWER', 'on');
73
+ await Helper.delay(1000);
74
+ }
75
+ if (i >= 5)
76
+ return false;
77
+ for (i = 0; i < 5; i++) {
78
+ if (this.getSoundbarValue('Info') === 'digital')
79
+ return true;
80
+ const result = await this.setSoundbar('SOURCE', 'digital');
81
+ await Helper.delay(1000);
82
+ }
83
+ return false;
84
+ }
85
+ }
86
+ //# sourceMappingURL=playlistService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"playlistService.js","sourceRoot":"","sources":["../src/playlistService.ts"],"names":[],"mappings":"AACA,OAAO,EAAW,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAY,gBAAgB,EAAoC,MAAM,UAAU,CAAC;AAExF,MAAM,OAAO,eAAe;IACxB,IAAI,CAAQ;IACZ,QAAQ,CAAS;IACjB,GAAG,CAAU;IACb,UAAU,CAAU;IACpB,WAAW,CAAoD;IAC/D,gBAAgB,CAA2B;IAC3C,YAAY,IAAW,EAAE,GAAY,EAAE,gBAA0C,EAAE,WAA8D;QAC7I,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC;QAChC,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;QACzC,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QACtC,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;IACrB,CAAC;IACD,KAAK,CAAC,SAAS;QACX,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAW,mBAAmB,CAAC,CAAC;QACnE,OAAO,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,MAAkB,CAAC,CAAC,CAAC,EAAE,CAAC;IAChD,CAAC;IACD,KAAK,CAAC,OAAO,CAAC,KAAa;QACvB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAW,kBAAkB,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QACpF,OAAO,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,MAAkB,CAAC,CAAC,CAAC,IAAI,CAAC;IAClD,CAAC;IACD,KAAK,CAAC,QAAQ;QACV,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAa,kBAAkB,CAAC,CAAC;QACpE,OAAO,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,MAAoB,CAAC,CAAC,CAAC,EAAE,CAAC;IAClD,CAAC;IACD,KAAK,CAAC,OAAO,CAAC,GAAW,EAAE,IAAa;QACpC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,UAAU,CAAmB,wBAAwB,kBAAkB,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;QACzH,OAAO,GAAG,CAAC,EAAE,CAAC,CAAC,CAAE,GAAG,CAAC,MAAiC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;IACzE,CAAC;IACD,KAAK,CAAC,UAAU,CAAC,KAAa;QAC1B,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,UAAU,CAAe,0BAA0B,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC5G,OAAO,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,MAAiB,CAAC,CAAC,CAAC,KAAK,CAAC;IAClD,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,GAAW;QACzB,IAAI,CAAC,UAAU,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QACxC,IAAI,CAAC,IAAI,CAAC,UAAU;YAChB,OAAO,KAAK,CAAC;QACV,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAM,wBAAwB,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC7F,OAAO,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,MAAiB,CAAC,CAAC,CAAC,KAAK,CAAC;IAClD,CAAC;IACD,KAAK,CAAC,QAAQ,CAAC,IAAc,EAAE,KAAc,EAAE,KAAc;QAChE,IAAI,CAAC,UAAU,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QACxC,IAAI,CAAC,IAAI,CAAC,UAAU;YAChB,OAAO,KAAK,CAAC;QACjB,IAAI,GAAG,GAAG,0BAA0B,KAAK,EAAE,CAAC;QAC5C,IAAI,KAAK,KAAK,SAAS;YACnB,GAAG,IAAI,UAAU,KAAK,EAAE,CAAC;QACtB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAW,GAAG,EAAE,IAAI,CAAC,CAAC;QAC1D,OAAO,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,MAAiB,CAAC,CAAC,CAAC,KAAK,CAAC;IAClD,CAAC;IACD,KAAK,CAAC,WAAW,CAAC,GAAqB;QAC1C,IAAI,CAAC,UAAU,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QACxC,IAAI,CAAC,IAAI,CAAC,UAAU;YAChB,OAAO,KAAK,CAAC;QACjB,IAAI,GAAG,GAAG,+BAA+B,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1D,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAM,GAAG,CAAC,CAAC;QAC/C,OAAO,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,MAAiB,CAAC,CAAC,CAAC,KAAK,CAAC;IAClD,CAAC;IACD,KAAK,CAAC,QAAQ;QACV,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAiB,mBAAmB,CAAC,CAAC;QACzE,OAAO,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,MAAwB,CAAC,CAAC,CAAC,IAAI,CAAC;IACxD,CAAC;IACD,KAAK,CAAC,QAAQ;QACjB,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YACrB,IAAI,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,IAAI;gBAC3C,MAAM;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YACrD,MAAM,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7B,CAAC;QACD,IAAI,CAAC,IAAI,CAAC;YACN,OAAO,KAAK,CAAC;QACjB,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YACrB,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,KAAK,SAAS;gBAClD,OAAO,IAAI,CAAC;YACT,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;YAC3D,MAAM,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC7B,CAAC;QACD,OAAO,KAAK,CAAC;IACV,CAAC;CACJ"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@christianriedl/media",
3
- "version": "1.0.300",
3
+ "version": "1.0.302",
4
4
  "description": "RIC media interfaces",
5
5
 
6
6
  "main": "dist/index.js",
@@ -244,6 +244,9 @@
244
244
  function onlineRadio() {
245
245
  router.push({ path: 'onlineradios' });
246
246
  }
247
+ function onlinePodcast() {
248
+ router.push({ path: 'onlinepodcasts' });
249
+ }
247
250
  function download() {
248
251
  window.open(playingTrackUrl.value);
249
252
  }
@@ -319,9 +322,14 @@
319
322
  <v-btn v-if="backVisible" @click="listBack">
320
323
  <v-icon icon="$back" />
321
324
  </v-btn>
322
- <v-btn v-else @click.stop="onlineRadio">
325
+ <template v-else>
326
+ <v-btn @click.stop="onlineRadio">
323
327
  <v-icon size="x-large" icon="$radio" />
324
328
  </v-btn>
329
+ <v-btn @click.stop="onlinePodcast">
330
+ <v-icon size="x-large" icon="$podcast" />
331
+ </v-btn>
332
+ </template>
325
333
  <v-btn v-if="downloadAlbumVisible" @click="downloadAlbum">
326
334
  Album
327
335
  <v-icon icon="$download" />
@@ -0,0 +1,219 @@
1
+ <script setup lang="ts">
2
+ import { inject, ref, reactive, computed, onMounted, onUnmounted, nextTick, watch, StyleValue } from 'vue';
3
+ import type { ComponentPublicInstance } from 'vue';
4
+ import { useRouter } from 'vue-router';
5
+ import { IAppState, EScope, EDevice, appStateSymbol, appConfigSymbol } from '@christianriedl/utils';
6
+ import { getPlaylistSymbol, IPlaylistService, IPlaylistState, IRssFeed, EPlaylistCommand } from '@christianriedl/media';
7
+
8
+ const appState = inject(appStateSymbol)!;
9
+ const getPlaylistService = inject(getPlaylistSymbol)!;
10
+ const playlistService = getPlaylistService() ;
11
+ const heightStyle = computed<StyleValue>(() => { return { height: appState.bodyHeight.value + 'px', overflowY: 'auto' } });
12
+ const isMobile = appState.isMobile && (appState.device != EDevice.iPad);
13
+ const router = useRouter();
14
+ const feeds: IRssFeed[] = reactive([]);
15
+ const selected = ref<IRssFeed|null>(null);
16
+ const status = ref<IPlaylistState|null>(null);
17
+ const audio = ref<HTMLAudioElement | null>(null);
18
+ const listhead = ref<ComponentPublicInstance | null>(null);
19
+ const listHeight = ref(0);
20
+ const playerNames = ['Local', 'Soundbar'];
21
+ const currentPlayer = ref<string>(playerNames[0]);
22
+ const playLocal = computed(() => currentPlayer.value == 'Local');
23
+ const playIndex = ref(-1);
24
+ const itemIndex = ref(0);
25
+ const playingFeed = ref<IRssFeed|null>(null);
26
+ const position = ref(0);
27
+ const positionLength = ref(0);
28
+ const volume = ref(0);
29
+ const paused = ref(false);
30
+ let statusTimer = 0;
31
+
32
+
33
+
34
+ onMounted(async () => {
35
+ playlistService.log.info('OnlineBroadcast created');
36
+ const f = await playlistService.getFeeds();
37
+ feeds.splice(0, feeds.length, ...f);
38
+ computeListHeight();
39
+ });
40
+ onUnmounted(() => {
41
+ if (statusTimer > 0) {
42
+ clearTimeout(statusTimer);
43
+ statusTimer = 0;
44
+ }
45
+ });
46
+
47
+ function computeListHeight() {
48
+ nextTick(() => {
49
+ let height = appState.bodyHeight.value;
50
+ if (listhead.value) {
51
+ height = height - (listhead.value.$el as HTMLElement).clientHeight;
52
+ }
53
+ listHeight.value = height;
54
+ })
55
+ }
56
+ async function play() {
57
+ if (playLocal.value) {
58
+ audio.value!.src = selected.value!.link;
59
+ audio.value!.load();
60
+ audio.value!.play().then(() => {
61
+ playlistService.log.trace(`play local ${selected.value!.title}`)
62
+ });
63
+ }
64
+ else {
65
+ const rc = await playlistService.play(selected.value!.link);
66
+ if (!rc)
67
+ return;
68
+ await getStatus();
69
+ playlistService.log.trace(`play remote ${selected.value!.title}`)
70
+ }
71
+ playingFeed.value = selected.value;
72
+ itemIndex.value = playIndex.value = feeds.findIndex((f) => f.link == selected.value!.link);
73
+ }
74
+ function listItem(item: IRssFeed) {
75
+ selected.value = item;
76
+ computeListHeight();
77
+ }
78
+ function listBack() {
79
+ router.back();
80
+ }
81
+ async function getStatus() {
82
+ const status = await playlistService.getState();
83
+ status.value = status;
84
+ setPosition(status.position.toNumber());
85
+ statusTimer = setTimeout(async () => getStatus(), 1000);
86
+ }
87
+
88
+ function toSubTitle(f: IRssFeed): string {
89
+ if (!f.duration)
90
+ return "";
91
+ let s = f.duration;
92
+ var r = "";
93
+ s = Math.floor(s);
94
+ if (s >= 3600) {
95
+ r += Math.floor(s / 3600).toString() + ":"; s = s % 3600;
96
+ }
97
+ if (!r || s >= 600) {
98
+ r += Math.floor(s / 60).toString() + ":"; s = s % 60;
99
+ }
100
+ else {
101
+ r += "0"; r += Math.floor(s / 60).toString() + ":"; s = s % 60;
102
+ }
103
+ if (s >= 10) {
104
+ r += s.toString(); s = -1;
105
+ }
106
+ else if (s >= 0) {
107
+ r += "0"; r += s.toString();
108
+ s = -1;
109
+ }
110
+ return r;
111
+ }
112
+ function onEnded() {
113
+ }
114
+ function onTimeUpdate() {
115
+ setPosition(audio.value!.currentTime);
116
+ }
117
+ function setPosition(value: number) {
118
+ position.value = value;
119
+ if (playingFeed.value!.duration)
120
+ positionLength.value = position.value * 100 / playingFeed.value!.duration;
121
+ else
122
+ positionLength.value = 0;
123
+ }
124
+ function onPlayerChange() {
125
+ if (statusTimer) {
126
+ clearTimeout(statusTimer);
127
+ statusTimer = 0;
128
+ }
129
+ if (!playLocal.value) {
130
+ statusTimer = setTimeout(() => getStatus(), 1000);
131
+ }
132
+ }
133
+ function playpause() {
134
+ if (playLocal.value) {
135
+ if (audio.value!.paused) {
136
+ paused.value = false;
137
+ audio.value!.play()
138
+ .then(() => { console.log("play ended") });
139
+ }
140
+ else {
141
+ paused.value = true;
142
+ audio.value!.pause();
143
+ }
144
+ }
145
+ else {
146
+ if (paused.value) {
147
+ playlistService.playCommand(EPlaylistCommand.Resume);
148
+ }
149
+ else {
150
+ playlistService.playCommand(EPlaylistCommand.Pause);
151
+ }
152
+ }
153
+ }
154
+ function previous() {
155
+ if (playIndex.value <= 0)
156
+ return;
157
+ selected.value = feeds[playIndex.value - 1];
158
+ play();
159
+ }
160
+ function next() {
161
+ if (playIndex.value >= feeds.length - 1)
162
+ return;
163
+ selected.value = feeds[playIndex.value + 1];
164
+ play();
165
+ }
166
+ function changeVolume() {
167
+ }
168
+
169
+ </script>
170
+
171
+ <template>
172
+ <v-card ref="listhead" class="bg-media_head">
173
+ <audio ref="audio" preload="none" @ended="onEnded" @timeupdate="onTimeUpdate">
174
+ </audio>
175
+ <v-list-item lines="three">
176
+ <v-list-item-content>
177
+ <v-list-item-title text-h6>{{selected!.title}}</v-list-item-title>
178
+ <v-list-item-subtitle>{{toSubTitle(selected!)}}</v-list-item-subtitle>
179
+ </v-list-item-content>
180
+ <template v-slot:append>
181
+ <v-select v-model="currentPlayer"
182
+ :items="playerNames"
183
+ persistent-hint
184
+ @update:modelValue="onPlayerChange"
185
+ hide-details single-line>
186
+ </v-select>!
187
+ </template>
188
+ </v-list-item>
189
+ <v-card-actions>
190
+ <v-btn v-if="backVisible" @click="listBack">
191
+ <v-icon icon="$back" />
192
+ </v-btn>
193
+ <v-btn size="small" v-if="playingFeed" @click="playpause">
194
+ <v-icon v-if="paused" icon="$play" />
195
+ <v-icon v-else icon="$pause" />
196
+ </v-btn>
197
+ <v-btn size="small" v-if="playingFeed" @click="previous">
198
+ <v-icon icon="$prev" />
199
+ </v-btn>
200
+ <v-btn size="small" v-if="playingFeed" @click="next">
201
+ <v-icon icon="$next" />
202
+ </v-btn>
203
+ <v-slider v-if="!playLocal && playingFeed" style="width:30%" color="red" track-color="blue" track-fill-color="red" v-model="volume" hide-details density="compact"
204
+ min="0" max="100" step="5" @update:modelValue="changeVolume">
205
+ </v-slider>
206
+ </v-card-actions>
207
+ <v-progress-linear v-if="playingFeed" v-model="positionLength" color="blue" height="25"><strong>{{positionText}}</strong></v-progress-linear>
208
+ </v-card>
209
+ <v-card :height="listHeight" density="compact" class="overflow-y-auto bg-media">
210
+ <v-list lines="two" class="bg-media">
211
+ <v-list-item-group v-model="itemIndex">
212
+ <v-list-item v-for="(item,index) in items" :key="item.title" density="compact" :title="item.title" :subtitle="toSubTitle(item)"
213
+ active-color="blue" :active="index == playIndex" @click="listItem(item)">
214
+ </v-list-item>
215
+ </v-list-item-group>
216
+ </v-list>
217
+ </v-card>
218
+ </template>
219
+
@@ -67,11 +67,12 @@
67
67
  mimeType = 'image/png';
68
68
  else if (url.includes('.jpg') || url.includes('.jpeg'))
69
69
  mimeType = 'image/jpeg';
70
+ if (mimeType)
71
+ return `${mediaService.mediaUrl}apiimage/cachedimage?url=${encodeURIComponent(url)}&mimeType=${encodeURIComponent(mimeType)}`;
72
+ else
73
+ return `${mediaService.mediaUrl}apiimage/cachedimage?url=${encodeURIComponent(url)}`;
70
74
  }
71
- if (mimeType)
72
- return `${mediaService.mediaUrl}apiimage/cachedimage?url=${encodeURIComponent(url)}&mimeType=${encodeURIComponent(mimeType)}`;
73
- else
74
- return `${mediaService.mediaUrl}apistream/stream?url=${encodeURIComponent(url)}`;
75
+ return `${mediaService.mediaUrl}apistream/stream?url=${encodeURIComponent(url)}&mimeType=${encodeURIComponent(mimeType)}`;
75
76
  }
76
77
  function listItem(item: IMediaItem) {
77
78
  if (item.itemType == EItemType.AudioTrack || item.itemType == EItemType.AudioBroadcast) {
@@ -91,11 +91,12 @@
91
91
  mimeType = 'image/png';
92
92
  else if (url.includes('.jpg') || url.includes('.jpeg'))
93
93
  mimeType = 'image/jpeg';
94
+ if (mimeType)
95
+ return `${mediaService.mediaUrl}apiimage/cachedimage?url=${encodeURIComponent(url)}&mimeType=${encodeURIComponent(mimeType)}`;
96
+ else
97
+ return `${mediaService.mediaUrl}apiimage/cachedimage?url=${encodeURIComponent(url)}`;
94
98
  }
95
- if (mimeType)
96
- return `${mediaService.mediaUrl}apiimage/cachedimage?url=${encodeURIComponent(url)}&mimeType=${encodeURIComponent(mimeType)}`;
97
- else
98
- return `${mediaService.mediaUrl}apistream/stream?url=${encodeURIComponent(url)}`;
99
+ return `${mediaService.mediaUrl}apistream/stream?url=${encodeURIComponent(url)}&mimeType=${encodeURIComponent(mimeType)}`;
99
100
  }
100
101
  async function listItem(item: IMediaItem) {
101
102
  if (item.itemType == EItemType.VideoItem || item.itemType == EItemType.VideoBroadcast) {