@christianriedl/media 1.0.302 → 1.0.304

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,15 +317,33 @@ 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 {
320
+ export interface IRssItem {
321
321
  title: string;
322
- description: string;
322
+ description?: string;
323
323
  link: string;
324
- copyright?: string;
325
- items?: IRssFeed[];
326
324
  mediaType?: string;
327
325
  duration?: number;
328
326
  }
327
+ export declare enum EFeedType {
328
+ Unknown = 0,
329
+ Movie = 1,
330
+ Podcast = 2,
331
+ Music = 3,
332
+ MusicVideo = 4,
333
+ Audiobook = 5,
334
+ ShortFilm = 6,
335
+ TvShow = 7,
336
+ Ebook = 8
337
+ }
338
+ export interface IRssFeed extends IRssItem {
339
+ rssUrl: string;
340
+ genre?: string;
341
+ country?: string;
342
+ copyright?: string;
343
+ owner?: string;
344
+ imageUrl?: string;
345
+ items?: IRssItem[];
346
+ }
329
347
  export declare const getPlaylistSymbol: InjectionKey<() => IPlaylistService>;
330
348
  export declare enum EPlaylistCommand {
331
349
  None = 0,
@@ -346,13 +364,12 @@ export interface IPlaylistState {
346
364
  export interface IPlaylistService {
347
365
  log: ILogger;
348
366
  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>;
367
+ soundbarVolume: number;
368
+ searchFeeds(query: Dictionary<any>, limit?: number): Promise<IRssFeed[]>;
369
+ getFeed(rssUrl: string): Promise<IRssFeed | null>;
354
370
  play(url: string): Promise<boolean>;
355
371
  playList(urls: string[], clear: boolean, index?: number): Promise<boolean>;
356
372
  playCommand(cmd: EPlaylistCommand): Promise<boolean>;
373
+ setSoundbarVolume(value: number): Promise<boolean>;
357
374
  getState(): Promise<IPlaylistState | null>;
358
375
  }
package/dist/iMedia.js CHANGED
@@ -121,6 +121,18 @@ export var EPictureFlags;
121
121
  EPictureFlags[EPictureFlags["Mask"] = 240] = "Mask";
122
122
  })(EPictureFlags || (EPictureFlags = {}));
123
123
  export const getMediaSymbol = Symbol("get-media");
124
+ export var EFeedType;
125
+ (function (EFeedType) {
126
+ EFeedType[EFeedType["Unknown"] = 0] = "Unknown";
127
+ EFeedType[EFeedType["Movie"] = 1] = "Movie";
128
+ EFeedType[EFeedType["Podcast"] = 2] = "Podcast";
129
+ EFeedType[EFeedType["Music"] = 3] = "Music";
130
+ EFeedType[EFeedType["MusicVideo"] = 4] = "MusicVideo";
131
+ EFeedType[EFeedType["Audiobook"] = 5] = "Audiobook";
132
+ EFeedType[EFeedType["ShortFilm"] = 6] = "ShortFilm";
133
+ EFeedType[EFeedType["TvShow"] = 7] = "TvShow";
134
+ EFeedType[EFeedType["Ebook"] = 8] = "Ebook";
135
+ })(EFeedType || (EFeedType = {}));
124
136
  export const getPlaylistSymbol = Symbol("get-playlist");
125
137
  export var EPlaylistCommand;
126
138
  (function (EPlaylistCommand) {
@@ -1 +1 @@
1
- {"version":3,"file":"iMedia.js","sourceRoot":"","sources":["../src/iMedia.ts"],"names":[],"mappings":"AAGA,MAAM,CAAN,IAAY,UASX;AATD,WAAY,UAAU;IAClB,6CAAS,CAAA;IACT,6CAAS,CAAA;IACT,iDAAW,CAAA;IACX,4CAAS,CAAA;IACT,0DAAgB,CAAA;IAChB,iDAAa,CAAA;IACb,6CAAW,CAAA;IACX,mDAAc,CAAA;AAClB,CAAC,EATW,UAAU,KAAV,UAAU,QASrB;AACD,MAAM,CAAN,IAAY,eAeX;AAfD,WAAY,eAAe;IACvB,qDAAiB,CAAA;IACjB,gEAAoB,CAAA;IACpB,gEAAoB,CAAA;IACpB,gEAAoB,CAAA;IACpB,gEAAoB,CAAA;IACpB,kEAAoB,CAAA;IACpB,gEAAoB,CAAA;IACpB,gEAAoB,CAAA;IACpB,gEAAoB,CAAA;IACpB,kEAAoB,CAAA;IACpB,4DAAoB,CAAA;IACpB,4DAAoB,CAAA;IACpB,4DAAoB,CAAA;IACpB,8DAAoB,CAAA;AACxB,CAAC,EAfW,eAAe,KAAf,eAAe,QAe1B;AAaD,MAAM,CAAN,IAAY,SAoDX;AApDD,WAAY,SAAS;IACjB,yCAAQ,CAAA;IACR,mDAAa,CAAA;IACb,uDAAe,CAAA;IACf,uDAAe,CAAA;IACf,6DAAkB,CAAA;IAClB,iEAAoB,CAAA;IACpB,iEAAoB,CAAA;IACpB,iEAAoB,CAAA;IACpB,iEAAoB,CAAA;IACpB,mDAAgB,CAAA;IAChB,6CAAa,CAAA;IACb,4CAAY,CAAA;IACZ,4CAAY,CAAA;IACZ,gDAAc,CAAA;IACd,6DAAoB,CAAA;IACpB,qDAAgB,CAAA;IAChB,yCAAa,CAAA;IACb,mDAA6C,CAAA;IAC7C,oDAA0B,CAAA;IAC1B,wDAAkC,CAAA;IAClC,wDAAkC,CAAA;IAClC,8DAAqC,CAAA;IACrC,sDAAiC,CAAA;IACjC,wDAAkC,CAAA;IAClC,sDAAiC,CAAA;IACjC,0DAAmC,CAAA;IACnC,uEAA0C,CAAA;IAC1C,2EAA8C,CAAA;IAC9C,sDAAkB,CAAA;IAClB,+DAAkC,CAAA;IAClC,oDAA0B,CAAA;IAC1B,wDAAkC,CAAA;IAClC,wDAAkC,CAAA;IAClC,8DAAqC,CAAA;IACrC,4DAAoC,CAAA;IACpC,uEAA0C,CAAA;IAC1C,2EAA8C,CAAA;IAC9C,yEAA+C,CAAA;IAC/C,oDAAiB,CAAA;IACjB,+DAAkC,CAAA;IAClC,wDAA8B,CAAA;IAC9B,4DAAsC,CAAA;IACtC,4DAAsC,CAAA;IACtC,kEAAyC,CAAA;IACzC,gEAAwC,CAAA;IACxC,wDAAoC,CAAA;IACpC,0DAAqC,CAAA;IACrC,wDAAqB,CAAA;IACrB,uDAA+C,CAAA;IAC/C,qDAAgB,CAAA;IAChB,yCAAU,CAAA;AACd,CAAC,EApDW,SAAS,KAAT,SAAS,QAoDpB;AACD,MAAM,CAAN,IAAY,MAUX;AAVD,WAAY,MAAM;IACd,mCAAQ,CAAA;IACR,yDAAsB,CAAA;IACtB,2CAAe,CAAA;IACf,+CAAiB,CAAA;IACjB,qDAAoB,CAAA;IACpB,kDAAkB,CAAA;IAClB,sDAAoB,CAAA;IACpB,0DAAsB,CAAA;IACtB,+DAAwB,CAAA;AAC5B,CAAC,EAVW,MAAM,KAAN,MAAM,QAUjB;AAkDD,MAAM,CAAN,IAAY,YAaX;AAbD,WAAY,YAAY;IAEpB,+CAAY,CAAA;IACZ,qDAAmB,CAAA;IACnB,yDAAmB,CAAA;IACnB,6DAAmB,CAAA;IACnB,2DAAmB,CAAA;IACnB,qEAAmB,CAAA;IACnB,uDAAmB,CAAA;IACnB,mEAAmB,CAAA;IACnB,2DAAmB,CAAA;IACnB,yDAAiB,CAAA;IACjB,gDAAe,CAAA;AACnB,CAAC,EAbW,YAAY,KAAZ,YAAY,QAavB;AACD,MAAM,CAAN,IAAY,aAaX;AAbD,WAAY,aAAa;IAErB,iDAAe,CAAA;IACf,yDAAkB,CAAA;IAClB,gDAAkB,CAAA;IAClB,sDAAkB,CAAA;IAClB,oDAAkB,CAAA;IAClB,kDAAkB,CAAA;IAClB,sDAAkB,CAAA;IAClB,oDAAkB,CAAA;IAClB,qDAAkB,CAAA;IAClB,6DAAkB,CAAA;IAClB,mDAAkB,CAAA;AACtB,CAAC,EAbW,aAAa,KAAb,aAAa,QAaxB;AA6FD,MAAM,CAAC,MAAM,cAAc,GAAsC,MAAM,CAAC,WAAW,CAAC,CAAC;AA6ErF,MAAM,CAAC,MAAM,iBAAiB,GAAyC,MAAM,CAAC,cAAc,CAAC,CAAC;AAC9F,MAAM,CAAN,IAAY,gBAEX;AAFD,WAAY,gBAAgB;IACxB,uDAAQ,CAAA;IAAE,uDAAI,CAAA;IAAE,yDAAK,CAAA;IAAE,2DAAM,CAAA;IAAE,uDAAI,CAAA;IAAE,uDAAI,CAAA;IAAE,+DAAQ,CAAA;AACvD,CAAC,EAFW,gBAAgB,KAAhB,gBAAgB,QAE3B"}
1
+ {"version":3,"file":"iMedia.js","sourceRoot":"","sources":["../src/iMedia.ts"],"names":[],"mappings":"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"}
@@ -1,22 +1,21 @@
1
1
  import { IRest } from '@christianriedl/rest';
2
- import { ILogger } from '@christianriedl/utils';
2
+ import { ILogger, Dictionary } from '@christianriedl/utils';
3
3
  import { IRssFeed, EPlaylistCommand, IPlaylistState, IPlaylistService } from "./iMedia";
4
4
  export declare class PlaylistService implements IPlaylistService {
5
5
  rest: IRest;
6
6
  mediaUrl: string;
7
7
  log: ILogger;
8
8
  soundbarOn: boolean;
9
+ soundbarVolume: number;
9
10
  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>;
11
+ getSoundbarValue: (name: string) => any;
12
+ constructor(rest: IRest, log: ILogger, getSoundbarValue: (name: string) => any, setSoundbar: (name: string, value: string) => Promise<boolean>);
13
+ searchFeeds(query: Dictionary<any>, limit?: number): Promise<IRssFeed[]>;
14
+ getFeed(rssUrl: string): Promise<IRssFeed | null>;
17
15
  play(url: string): Promise<boolean>;
18
16
  playList(urls: string[], clear: boolean, index?: number): Promise<boolean>;
19
17
  playCommand(cmd: EPlaylistCommand): Promise<boolean>;
20
18
  getState(): Promise<IPlaylistState | null>;
21
- ensureOn(): Promise<boolean>;
19
+ ensureSoundbarOn(): Promise<boolean>;
20
+ setSoundbarVolume(value: number): Promise<boolean>;
22
21
  }
@@ -5,6 +5,7 @@ export class PlaylistService {
5
5
  mediaUrl;
6
6
  log;
7
7
  soundbarOn;
8
+ soundbarVolume;
8
9
  setSoundbar;
9
10
  getSoundbarValue;
10
11
  constructor(rest, log, getSoundbarValue, setSoundbar) {
@@ -15,35 +16,46 @@ export class PlaylistService {
15
16
  this.setSoundbar = setSoundbar;
16
17
  this.soundbarOn = false;
17
18
  }
18
- async getTitles() {
19
- const res = await this.rest.getData('apiplaylist/title');
19
+ async searchFeeds(query, limit) {
20
+ query['limit'] = limit ?? 50;
21
+ const res = await this.rest.getData('apiplaylist/feed/search', query);
20
22
  return res.ok ? res.result : [];
21
23
  }
22
- async getFeed(title) {
23
- const res = await this.rest.getData('apiplaylist/feed', { title: title });
24
+ async getFeed(rssUrl) {
25
+ const res = await this.rest.getData('apiplaylist/feed', { rssUrl: rssUrl });
24
26
  return res.ok ? res.result : null;
25
27
  }
26
- async getFeeds() {
27
- const res = await this.rest.getData('apiplaylist/feed');
28
- return res.ok ? res.result : [];
28
+ /*
29
+ async getTitles(): Promise<string[]> {
30
+ const res = await this.rest.getData<string[]>('apiplaylist/title');
31
+ return res.ok ? res.result as string[] : [];
29
32
  }
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
+ async getFeed(title: string): Promise<IRssFeed|null> {
34
+ const res = await this.rest.getData<IRssFeed>('apiplaylist/feed', { title: title });
35
+ return res.ok ? res.result as IRssFeed : null;
33
36
  }
34
- async deleteFeed(title) {
35
- const res = await this.rest.deleteData(`apiplaylist/feed?title=${encodeURIComponent(title)}`);
36
- return res.ok ? res.result : false;
37
+ async getFeeds(): Promise<IRssFeed[]> {
38
+ const res = await this.rest.getData<IRssFeed[]>('apiplaylist/feed');
39
+ return res.ok ? res.result as IRssFeed[] : [];
40
+ }
41
+ async addFeed(url: string, save: boolean): Promise<IRssFeed|null> {
42
+ const res = await this.rest.postDataEx<boolean,IRssFeed>(`apiplaylist/feed?url=${encodeURIComponent(url)}&save=${save}`);
43
+ return res.ok ? (res.result as IValueResult<IRssFeed>).result : null;
37
44
  }
45
+ async deleteFeed(title: string): Promise<boolean> {
46
+ const res = await this.rest.deleteData<any, boolean>(`apiplaylist/feed?title=${encodeURIComponent(title)}`);
47
+ return res.ok ? res.result as boolean : false;
48
+ }
49
+ */
38
50
  async play(url) {
39
- this.soundbarOn = await this.ensureOn();
51
+ this.soundbarOn = await this.ensureSoundbarOn();
40
52
  if (!this.soundbarOn)
41
53
  return false;
42
54
  const res = await this.rest.postData(`apiplaylist/play?url=${encodeURIComponent(url)}`);
43
55
  return res.ok ? res.result : false;
44
56
  }
45
57
  async playList(urls, clear, index) {
46
- this.soundbarOn = await this.ensureOn();
58
+ this.soundbarOn = await this.ensureSoundbarOn();
47
59
  if (!this.soundbarOn)
48
60
  return false;
49
61
  let url = `apiplaylist/play?clear=${clear}`;
@@ -53,7 +65,7 @@ export class PlaylistService {
53
65
  return res.ok ? res.result : false;
54
66
  }
55
67
  async playCommand(cmd) {
56
- this.soundbarOn = await this.ensureOn();
68
+ this.soundbarOn = await this.ensureSoundbarOn();
57
69
  if (!this.soundbarOn)
58
70
  return false;
59
71
  let url = `apiplaylist/playcommand?cmd=${EPlaylistCommand[cmd]}`;
@@ -61,15 +73,16 @@ export class PlaylistService {
61
73
  return res.ok ? res.result : false;
62
74
  }
63
75
  async getState() {
76
+ this.soundbarVolume = Number(this.getSoundbarValue('Volume'));
64
77
  const res = await this.rest.getData('apiplaylist/state');
65
78
  return res.ok ? res.result : null;
66
79
  }
67
- async ensureOn() {
80
+ async ensureSoundbarOn() {
68
81
  let i = 0;
69
82
  for (i = 0; i < 5; i++) {
70
- if (this.getSoundbarValue('ON') === 'ON')
83
+ if (this.getSoundbarValue('On') === true)
71
84
  break;
72
- const result = await this.setSoundbar('POWER', 'on');
85
+ const result = await this.setSoundbar('POWERON', '1');
73
86
  await Helper.delay(1000);
74
87
  }
75
88
  if (i >= 5)
@@ -82,5 +95,9 @@ export class PlaylistService {
82
95
  }
83
96
  return false;
84
97
  }
98
+ async setSoundbarVolume(value) {
99
+ const result = await this.setSoundbar('VOLUME', value.toString());
100
+ return result;
101
+ }
85
102
  }
86
103
  //# sourceMappingURL=playlistService.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"playlistService.js","sourceRoot":"","sources":["../src/playlistService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"playlistService.js","sourceRoot":"","sources":["../src/playlistService.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@christianriedl/media",
3
- "version": "1.0.302",
3
+ "version": "1.0.304",
4
4
  "description": "RIC media interfaces",
5
5
 
6
6
  "main": "dist/index.js",
@@ -1,9 +1,9 @@
1
1
  <script setup lang="ts">
2
2
  import { inject, ref, reactive, computed, onMounted, onUnmounted, nextTick, watch, StyleValue } from 'vue';
3
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';
4
+ import { useRouter, useRoute } from 'vue-router';
5
+ import { IAppState, EScope, EDevice, Helper, appStateSymbol, appConfigSymbol, Dictionary } from '@christianriedl/utils';
6
+ import { getPlaylistSymbol, IPlaylistService, IPlaylistState, IRssFeed, IRssItem, EPlaylistCommand, EFeedType } from '@christianriedl/media';
7
7
 
8
8
  const appState = inject(appStateSymbol)!;
9
9
  const getPlaylistService = inject(getPlaylistSymbol)!;
@@ -11,8 +11,11 @@
11
11
  const heightStyle = computed<StyleValue>(() => { return { height: appState.bodyHeight.value + 'px', overflowY: 'auto' } });
12
12
  const isMobile = appState.isMobile && (appState.device != EDevice.iPad);
13
13
  const router = useRouter();
14
+ const route = useRoute();
14
15
  const feeds: IRssFeed[] = reactive([]);
15
- const selected = ref<IRssFeed|null>(null);
16
+ const items: IRssItem[] = reactive([]);
17
+ const selectedItem = ref<IRssItem|null>(null);
18
+ const selectedFeed = ref<IRssFeed|null>(null);
16
19
  const status = ref<IPlaylistState|null>(null);
17
20
  const audio = ref<HTMLAudioElement | null>(null);
18
21
  const listhead = ref<ComponentPublicInstance | null>(null);
@@ -22,27 +25,57 @@
22
25
  const playLocal = computed(() => currentPlayer.value == 'Local');
23
26
  const playIndex = ref(-1);
24
27
  const itemIndex = ref(0);
25
- const playingFeed = ref<IRssFeed|null>(null);
28
+ const playingItem = ref<IRssItem|null>(null);
26
29
  const position = ref(0);
27
30
  const positionLength = ref(0);
28
31
  const volume = ref(0);
29
32
  const paused = ref(false);
33
+ const search = ref(true);
30
34
  let statusTimer = 0;
35
+ let volumeTimer = 0;
36
+ let volumeCount = 0;
31
37
 
38
+ const positionText = computed(() => {
39
+ if (playingItem.value?.duration)
40
+ return toTime(position.value) + '/' + toTime(playingItem.value.duration);
41
+ else
42
+ return toTime(position.value);
43
+ });
32
44
 
45
+ const feedTypes = Helper.getEnumOptions(EFeedType);
46
+ const feedType = ref<EFeedType>(0);
47
+ const countries = ["", "AT", "DE", "US"];
48
+ const country = ref("");
49
+ const query = ref("");
50
+ const limit = ref(50);
33
51
 
34
52
  onMounted(async () => {
35
- playlistService.log.info('OnlineBroadcast created');
36
- const f = await playlistService.getFeeds();
37
- feeds.splice(0, feeds.length, ...f);
38
- computeListHeight();
53
+ playlistService.log.info('OnlinePodcastsPage created');
54
+ await start();
39
55
  });
40
56
  onUnmounted(() => {
41
57
  if (statusTimer > 0) {
42
- clearTimeout(statusTimer);
58
+ window.clearTimeout(statusTimer);
43
59
  statusTimer = 0;
44
60
  }
45
61
  });
62
+ async function start() {
63
+ if (route.query?.rssUrl) {
64
+ const rssUrl = decodeURIComponent(route.query.rssUrl.toString());
65
+ const f = await playlistService.getFeed(rssUrl);
66
+ if (f && f.items) {
67
+ selectedFeed.value = f;
68
+ items.splice(0, items.length, ...f.items);
69
+ search.value = false;
70
+ }
71
+ }
72
+ else {
73
+ search.value = true;
74
+ }
75
+ computeListHeight();
76
+ }
77
+ watch(appState.bodyHeight, () => computeListHeight());
78
+ watch(() => route.query, () => start());
46
79
 
47
80
  function computeListHeight() {
48
81
  nextTick(() => {
@@ -53,43 +86,69 @@
53
86
  listHeight.value = height;
54
87
  })
55
88
  }
89
+ async function onSearch() {
90
+ const dict: Dictionary<any> = {};
91
+ if (feedType.value != EFeedType.Unknown)
92
+ dict["media"] = EFeedType[feedType.value];
93
+ if (country.value != "")
94
+ dict["country"] = country.value;;
95
+ dict["query"] = query.value;
96
+ const fds = await playlistService.searchFeeds(dict, limit.value);
97
+ feeds.splice (0, feeds.length, ...fds);
98
+ }
56
99
  async function play() {
57
100
  if (playLocal.value) {
58
- audio.value!.src = selected.value!.link;
101
+ audio.value!.src = selectedItem.value!.link;
59
102
  audio.value!.load();
60
103
  audio.value!.play().then(() => {
61
- playlistService.log.trace(`play local ${selected.value!.title}`)
104
+ playlistService.log.trace(`play local ${selectedItem.value!.title}`)
62
105
  });
106
+ playingItem.value = selectedItem.value;
63
107
  }
64
108
  else {
65
- const rc = await playlistService.play(selected.value!.link);
109
+ const rc = await playlistService.play(selectedItem.value!.link);
66
110
  if (!rc)
67
111
  return;
112
+ playingItem.value = selectedItem.value;
68
113
  await getStatus();
69
- playlistService.log.trace(`play remote ${selected.value!.title}`)
114
+ playlistService.log.trace(`play remote ${selectedItem.value!.title}`);
70
115
  }
71
- playingFeed.value = selected.value;
72
- itemIndex.value = playIndex.value = feeds.findIndex((f) => f.link == selected.value!.link);
116
+ itemIndex.value = playIndex.value = items.findIndex((f) => f.link == selectedItem.value!.link);
73
117
  }
74
- function listItem(item: IRssFeed) {
75
- selected.value = item;
76
- computeListHeight();
118
+ function listFeed(feed: IRssFeed) {
119
+ router.push ({path: 'onlinePodcasts', query: { rssUrl: feed.rssUrl }});
120
+ }
121
+
122
+ function listItem(item: IRssItem) {
123
+ selectedItem.value = item;
124
+ play();
125
+ computeListHeight();
77
126
  }
78
127
  function listBack() {
79
128
  router.back();
80
129
  }
81
130
  async function getStatus() {
82
- const status = await playlistService.getState();
83
- status.value = status;
84
- setPosition(status.position.toNumber());
85
- statusTimer = setTimeout(async () => getStatus(), 1000);
131
+ const state = await playlistService.getState();
132
+ status.value = state;
133
+ if (state)
134
+ setPosition(Number(state.position));
135
+ if (volumeCount > 0)
136
+ volumeCount--;
137
+ else
138
+ volume.value = playlistService.soundbarVolume;
139
+ statusTimer = window.setTimeout(async () => getStatus(), 1000);
86
140
  }
87
141
 
88
142
  function toSubTitle(f: IRssFeed): string {
89
- if (!f.duration)
143
+ if (!f || !f.duration)
90
144
  return "";
91
- let s = f.duration;
92
- var r = "";
145
+ return toTime(f.duration);
146
+ }
147
+
148
+ function toTime(s?: number): string {
149
+ if (!s)
150
+ return "";
151
+ let r = "";
93
152
  s = Math.floor(s);
94
153
  if (s >= 3600) {
95
154
  r += Math.floor(s / 3600).toString() + ":"; s = s % 3600;
@@ -116,8 +175,8 @@
116
175
  }
117
176
  function setPosition(value: number) {
118
177
  position.value = value;
119
- if (playingFeed.value!.duration)
120
- positionLength.value = position.value * 100 / playingFeed.value!.duration;
178
+ if (playingItem.value?.duration)
179
+ positionLength.value = position.value * 100 / playingItem.value!.duration;
121
180
  else
122
181
  positionLength.value = 0;
123
182
  }
@@ -127,7 +186,7 @@
127
186
  statusTimer = 0;
128
187
  }
129
188
  if (!playLocal.value) {
130
- statusTimer = setTimeout(() => getStatus(), 1000);
189
+ statusTimer = window.setTimeout(() => getStatus(), 1000);
131
190
  }
132
191
  }
133
192
  function playpause() {
@@ -154,36 +213,143 @@
154
213
  function previous() {
155
214
  if (playIndex.value <= 0)
156
215
  return;
157
- selected.value = feeds[playIndex.value - 1];
216
+ selectedItem.value = items[playIndex.value - 1];
158
217
  play();
159
218
  }
160
219
  function next() {
161
- if (playIndex.value >= feeds.length - 1)
220
+ if (playIndex.value >= items.length - 1)
162
221
  return;
163
- selected.value = feeds[playIndex.value + 1];
222
+ selectedItem.value = items[playIndex.value + 1];
164
223
  play();
165
224
  }
166
- function changeVolume() {
225
+ async function stop() {
226
+ await playlistService.playCommand(EPlaylistCommand.Stop);
227
+ }
228
+ async function changeVolume() {
229
+ if (volumeTimer)
230
+ window.clearTimeout(volumeTimer);
231
+
232
+ volumeCount = 3;
233
+ volumeTimer = window.setTimeout(async () => {
234
+ await playlistService.setSoundbarVolume(volume.value);
235
+ volumeTimer = 0;
236
+ }, 500);
167
237
  }
168
238
 
169
239
  </script>
170
240
 
171
241
  <template>
172
242
  <v-card ref="listhead" class="bg-media_head">
243
+ <audio ref="audio" preload="none" @ended="onEnded" @timeupdate="onTimeUpdate">
244
+ </audio>
245
+ <v-container v-if="search" fluid>
246
+ <v-row class="align-center">
247
+ <v-col cols="1"></v-col>
248
+ <v-col cols="2">Type</v-col>
249
+ <v-col cols="1">Country</v-col>
250
+ <v-col cols="6">Query</v-col>
251
+ <v-col cols="1">Limit</v-col>
252
+ </v-row>
253
+ <v-row class="align-center">
254
+ <v-col cols="1">
255
+ </v-col>
256
+ <v-col cols="2">
257
+ <v-select density="compact" v-model="feedType"
258
+ :items="feedTypes"
259
+ persistent-hint hide-details single-line>
260
+ </v-select>
261
+ </v-col>
262
+ <v-col cols="1">
263
+ <v-combobox density="compact" v-model="country"
264
+ :items="countries"
265
+ persistent-hint hide-details single-line>
266
+ </v-combobox>
267
+ </v-col>
268
+ <v-col cols="6">
269
+ <v-text-field v-model="query" hide-details density="compact"></v-text-field>
270
+ </v-col>
271
+ <v-col cols="1">
272
+ <v-text-field v-model="limit" hide-details type="number" density="compact"></v-text-field>
273
+ </v-col>
274
+ <v-col cols="1">
275
+ <v-btn icon="$search" class="bg-media_head" variant="tonal" @click="onSearch">
276
+ </v-btn>
277
+ </v-col>
278
+ </v-row>
279
+ </v-container>
280
+ <v-container v-else fluid>
281
+ <v-row class="align-center">
282
+ <v-col cols="1">
283
+ <v-btn icon="$back" class="bg-media_head" variant="tonal" @click="listBack">
284
+ </v-btn>
285
+ </v-col>
286
+ <v-col cols="1">
287
+ <v-img :src="selectedFeed!.imageUrl"></v-img>
288
+ </v-col>
289
+ <v-col cols="1">{{selectedFeed!.country}}</v-col>
290
+ <v-col cols="2">{{selectedFeed!.genre}}</v-col>
291
+ <v-col cols="2">{{selectedFeed!.owner}}</v-col>
292
+ <v-col cols="4">{{selectedFeed!.title}}</v-col>
293
+ <v-col cols="1">
294
+ <v-select v-model="currentPlayer" density="compact" :items="playerNames" persistent-hint
295
+ @update:modelValue="onPlayerChange" hide-details single-line>
296
+ </v-select>
297
+ </v-col>
298
+ </v-row>
299
+ <v-row v-if="playingItem" class="align-center">
300
+ <v-col cols="4">
301
+ <v-btn :icon="paused ? '$play' : '$pause'" class="bg-media_head" variant="tonal" @click="playpause"></v-btn>
302
+ <v-btn v-if="!playLocal" icon="$stop" class="bg-media_head" variant="tonal" @click="stop"></v-btn>
303
+ <v-btn icon="$prev" class="bg-media_head" variant="tonal" @click="previous"></v-btn>
304
+ <v-btn icon="$next" class="bg-media_head" variant="tonal" @click="next"></v-btn>
305
+ </v-col>
306
+ <v-col cols ="8">
307
+ <v-slider v-if="!playLocal" style="width:30%" color="red" track-color="blue" track-fill-color="red" v-model="volume" hide-details density="compact"
308
+ min="0" max="100" step="5" @update:modelValue="changeVolume">
309
+ </v-slider>
310
+ <v-div v-else>{{playingItem.title}}</v-div>
311
+ </v-col>
312
+ </v-row>
313
+ <v-row v-if="playingItem">
314
+ <v-col cols="12">
315
+ <v-progress-linear v-model="positionLength" color="blue" height="25"><strong>{{positionText}}</strong></v-progress-linear>
316
+ </v-col>
317
+ </v-row>
318
+ </v-container>
319
+ </v-card>
320
+ <v-card :height="listHeight" density="compact" class="overflow-y-auto bg-media">
321
+ <v-container v-if="search" fluid>
322
+ <v-row v-for="(feed,index) in feeds" :key="feed.rssUrl" @click="listFeed(feed)">
323
+ <v-col cols="1">{{feed.country}}</v-col>
324
+ <v-col cols="2">{{feed.genre}}</v-col>
325
+ <v-col cols="2">{{feed.owner}}</v-col>
326
+ <v-col cols="5">{{feed.title}}</v-col>
327
+ </v-row>
328
+ </v-container>
329
+ <v-container v-else>
330
+ <v-row v-for="(item,index) in items" :key="item.title" :class="{ active: index == playIndex }" @click="listItem(item)">
331
+ <v-col cols="6">{{item.title}}</v-col>
332
+ <v-col cols="6">{{toTime(item.duration)}}</v-col>
333
+ </v-row>
334
+ </v-container>
335
+ </v-card>
336
+
337
+ <!--
338
+ <v-card class="bg-media_head">
173
339
  <audio ref="audio" preload="none" @ended="onEnded" @timeupdate="onTimeUpdate">
174
340
  </audio>
175
341
  <v-list-item lines="three">
176
342
  <v-list-item-content>
177
- <v-list-item-title text-h6>{{selected!.title}}</v-list-item-title>
343
+ <v-list-item-title text-h6>{{selected?.title}}</v-list-item-title>
178
344
  <v-list-item-subtitle>{{toSubTitle(selected!)}}</v-list-item-subtitle>
179
345
  </v-list-item-content>
180
346
  <template v-slot:append>
181
- <v-select v-model="currentPlayer"
347
+ <v-select v-model="currentPlayer" density="compact"
182
348
  :items="playerNames"
183
349
  persistent-hint
184
350
  @update:modelValue="onPlayerChange"
185
351
  hide-details single-line>
186
- </v-select>!
352
+ </v-select>
187
353
  </template>
188
354
  </v-list-item>
189
355
  <v-card-actions>
@@ -209,11 +375,18 @@
209
375
  <v-card :height="listHeight" density="compact" class="overflow-y-auto bg-media">
210
376
  <v-list lines="two" class="bg-media">
211
377
  <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)">
378
+ <v-list-item v-for="(feed,index) in feeds" :key="feed.title" density="compact" :title="feed.title" :subtitle="toSubTitle(feed)"
379
+ active-color="blue" :active="index == playIndex" @click="listItem(feed)">
214
380
  </v-list-item>
215
381
  </v-list-item-group>
216
382
  </v-list>
217
383
  </v-card>
384
+ -->
218
385
  </template>
219
386
 
387
+ <style scoped>
388
+ .active {
389
+ background-color: aliceblue;
390
+ }
391
+
392
+ </style>