@christianriedl/media 1.0.1 → 1.0.2
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/playerService.d.ts +15 -5
- package/dist/playerService.js +14 -0
- package/dist/playerService.js.map +1 -1
- package/package.json +1 -1
- package/src/views/MusicPage.vue +98 -21
- package/src/views/PhotosPage.vue +1 -1
package/dist/playerService.d.ts
CHANGED
|
@@ -1,21 +1,30 @@
|
|
|
1
1
|
import { IRest } from '@christianriedl/rest';
|
|
2
2
|
import { ILogger, Dictionary } from '@christianriedl/utils';
|
|
3
|
+
export declare enum EPlayState {
|
|
4
|
+
PowerOff = 0,
|
|
5
|
+
NoMedia = 1,
|
|
6
|
+
Paused = 2,
|
|
7
|
+
Stopped = 3,
|
|
8
|
+
Play = 4,
|
|
9
|
+
PlayAll = 5,
|
|
10
|
+
PlayOnly = 6
|
|
11
|
+
}
|
|
3
12
|
export interface IPlayerState {
|
|
4
13
|
playerName: string;
|
|
5
14
|
albumId: string;
|
|
6
15
|
mediaId: string;
|
|
7
16
|
trackNo: number;
|
|
8
17
|
duration: number;
|
|
9
|
-
state:
|
|
18
|
+
state: EPlayState;
|
|
10
19
|
volume: number;
|
|
11
20
|
mute: boolean;
|
|
12
21
|
}
|
|
13
22
|
export interface IPlayerRequest {
|
|
14
23
|
playerName: string;
|
|
15
|
-
folderId
|
|
16
|
-
mediaId
|
|
17
|
-
trackNo
|
|
18
|
-
withStreamTitle
|
|
24
|
+
folderId?: string;
|
|
25
|
+
mediaId?: string;
|
|
26
|
+
trackNo?: number;
|
|
27
|
+
withStreamTitle?: boolean;
|
|
19
28
|
}
|
|
20
29
|
export declare class PlayerService {
|
|
21
30
|
rest: IRest;
|
|
@@ -28,4 +37,5 @@ export declare class PlayerService {
|
|
|
28
37
|
getPlayerState(playerName: string): Promise<IPlayerState | null>;
|
|
29
38
|
play(playerRequest: IPlayerRequest): Promise<boolean>;
|
|
30
39
|
playStop(playerName: string): Promise<boolean>;
|
|
40
|
+
playPause(playerName: string): Promise<boolean>;
|
|
31
41
|
}
|
package/dist/playerService.js
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
export var EPlayState;
|
|
2
|
+
(function (EPlayState) {
|
|
3
|
+
EPlayState[EPlayState["PowerOff"] = 0] = "PowerOff";
|
|
4
|
+
EPlayState[EPlayState["NoMedia"] = 1] = "NoMedia";
|
|
5
|
+
EPlayState[EPlayState["Paused"] = 2] = "Paused";
|
|
6
|
+
EPlayState[EPlayState["Stopped"] = 3] = "Stopped";
|
|
7
|
+
EPlayState[EPlayState["Play"] = 4] = "Play";
|
|
8
|
+
EPlayState[EPlayState["PlayAll"] = 5] = "PlayAll";
|
|
9
|
+
EPlayState[EPlayState["PlayOnly"] = 6] = "PlayOnly";
|
|
10
|
+
})(EPlayState || (EPlayState = {}));
|
|
1
11
|
export class PlayerService {
|
|
2
12
|
rest;
|
|
3
13
|
mediaUrl;
|
|
@@ -31,5 +41,9 @@ export class PlayerService {
|
|
|
31
41
|
const result = await this.rest.postData('apiplayer/playstop', { playerName: playerName });
|
|
32
42
|
return result.ok;
|
|
33
43
|
}
|
|
44
|
+
async playPause(playerName) {
|
|
45
|
+
const result = await this.rest.postData('apiplayer/playpause', { playerName: playerName });
|
|
46
|
+
return result.ok;
|
|
47
|
+
}
|
|
34
48
|
}
|
|
35
49
|
//# sourceMappingURL=playerService.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"playerService.js","sourceRoot":"","sources":["../src/playerService.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"playerService.js","sourceRoot":"","sources":["../src/playerService.ts"],"names":[],"mappings":"AAOA,MAAM,CAAN,IAAY,UAQX;AARD,WAAY,UAAU;IAClB,mDAAY,CAAA;IACZ,iDAAO,CAAA;IACP,+CAAM,CAAA;IACN,iDAAO,CAAA;IACP,2CAAI,CAAA;IACJ,iDAAO,CAAA;IACP,mDAAQ,CAAA;AACZ,CAAC,EARW,UAAU,KAAV,UAAU,QAQrB;AAqBD,MAAM,OAAO,aAAa;IACtB,IAAI,CAAQ;IACZ,QAAQ,CAAS;IACjB,GAAG,CAAU;IACb,WAAW,GAAa,EAAE,CAAC;IAC3B,YAAY,GAA6B,EAAE,CAAA;IAE3C,YAAY,IAAW,EAAE,GAAY;QACjC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC;IACpC,CAAC;IACD,KAAK,CAAC,UAAU;QACZ,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAW,mBAAmB,CAAC,CAAC;QACvE,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,MAAkB,CAAC;QAC9C,OAAO,IAAI,CAAC,WAAW,CAAC;IAC5B,CAAC;IACD,KAAK,CAAC,cAAc,CAAC,UAAkB;QACnC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAe,qBAAqB,EAAE,EAAE,UAAU,EAAE,UAAU,EAAC,CAAC,CAAC;QACvG,IAAI,MAAM,CAAC,EAAE,EAAE;YACX,MAAM,WAAW,GAAG,MAAM,CAAC,MAAsB,CAAC;YAClD,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,GAAG,WAAW,CAAC;YAC5C,OAAO,WAAW,CAAC;SACtB;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,aAA6B;QACpC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAiB,gBAAgB,EAAE,aAAa,CAAC,CAAC;QACzF,OAAO,MAAM,CAAC,EAAE,CAAC;IACrB,CAAC;IACD,KAAK,CAAC,QAAQ,CAAC,UAAkB;QAC7B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAM,oBAAoB,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAAC;QAC/F,OAAO,MAAM,CAAC,EAAE,CAAC;IACrB,CAAC;IACD,KAAK,CAAC,SAAS,CAAC,UAAkB;QAC9B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAM,qBAAqB,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAAC;QAChG,OAAO,MAAM,CAAC,EAAE,CAAC;IACrB,CAAC;CACJ"}
|
package/package.json
CHANGED
package/src/views/MusicPage.vue
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { inject, ref, reactive, computed, onMounted, onUnmounted, nextTick, watch } from 'vue';
|
|
3
|
-
import { IAppState } from '@christianriedl/utils';
|
|
4
|
-
import { EItemType, EMediaType, IMediaFolder, IMediaItem, IAudioFile, MediaService } from '@christianriedl/media';
|
|
3
|
+
import { IAppState, Helper } from '@christianriedl/utils';
|
|
4
|
+
import { EItemType, EMediaType, IMediaFolder, IMediaItem, IAudioFile, MediaService, EPlayState, PlayerService } from '@christianriedl/media';
|
|
5
5
|
|
|
6
6
|
const appState = inject<IAppState>('appstate')!;
|
|
7
7
|
const getMediaService = inject<() => MediaService>('get-media')!;
|
|
8
8
|
const mediaService = getMediaService();
|
|
9
|
+
const getPlayerService = inject<() => PlayerService>('get-player')!;
|
|
10
|
+
const playerService = getPlayerService();
|
|
9
11
|
const heightStyle = computed(() => { return { height: appState.bodyHeight.value + 'px', overflowY: 'auto' } });
|
|
10
12
|
const isMobile = appState.isMobile;
|
|
11
13
|
|
|
14
|
+
const playerNames = reactive<string[]>(['Local']);
|
|
15
|
+
const currentPlayer = ref('Local');
|
|
12
16
|
const items: IMediaItem[] = reactive([]);
|
|
13
17
|
const selected = ref<IMediaItem>({ Name: 'Root', ItemType: EItemType.Root } as IMediaFolder);
|
|
14
18
|
const playingTrackUrl = ref("");
|
|
@@ -19,7 +23,10 @@
|
|
|
19
23
|
const positionLength = ref(0);
|
|
20
24
|
const listHeight = ref(0);
|
|
21
25
|
const playIndex = ref(-1);
|
|
26
|
+
const volume = ref(0);
|
|
27
|
+
const mute = ref(false);
|
|
22
28
|
|
|
29
|
+
const isLocal = computed(() => currentPlayer == 'Local');
|
|
23
30
|
const backVisible = computed(() => selected.value.ItemType != EItemType.AudioRoot);
|
|
24
31
|
const downloadAlbumVisible = computed(() => selected.value.ItemType == EItemType.AudioAlbum && !playingTrackUrl.value && !isMobile);
|
|
25
32
|
const downloadVisible = computed(() => playingTrackUrl.value && !isMobile);
|
|
@@ -35,6 +42,8 @@
|
|
|
35
42
|
}
|
|
36
43
|
return '';
|
|
37
44
|
});
|
|
45
|
+
let timer = 0;
|
|
46
|
+
|
|
38
47
|
window.addEventListener('popstate', onPopState);
|
|
39
48
|
function onPopState (event: any) {
|
|
40
49
|
if (event.state && event.state.noBackExitsApp && backVisible.value) {
|
|
@@ -59,6 +68,8 @@
|
|
|
59
68
|
selected.value = root;
|
|
60
69
|
items.splice(0, items.length, ...root.Folders);
|
|
61
70
|
computeListHeight();
|
|
71
|
+
const players = await playerService.getPlayers();
|
|
72
|
+
playerNames.splice(playerNames.length, 0, ...players);
|
|
62
73
|
})
|
|
63
74
|
watch(appState.bodyHeight, () => computeListHeight());
|
|
64
75
|
function computeListHeight() {
|
|
@@ -109,12 +120,46 @@
|
|
|
109
120
|
else
|
|
110
121
|
positionLength.value = 0;
|
|
111
122
|
}
|
|
123
|
+
function onPlayerChange() {
|
|
124
|
+
if (timer) {
|
|
125
|
+
window.clearTimeout(timer);
|
|
126
|
+
timer = 0;
|
|
127
|
+
}
|
|
128
|
+
if (currentPlayer != 'Local') {
|
|
129
|
+
timer = window.setTimeout(getPlayerState, 1000);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
async function getPlayerState() {
|
|
133
|
+
const playerState = await playerService.getPlayerState(currentPlayer);
|
|
134
|
+
playerState.state = Helper.stringToEnum(EPlayState, playerState.state);
|
|
135
|
+
paused.value = playerState.state == EPlayState.Paused;
|
|
136
|
+
volume.value = playerState.volume;
|
|
137
|
+
mute.value = playerState.mute;
|
|
138
|
+
if (!selected.value || playerState.folderId != selected.value.DLNAID) {
|
|
139
|
+
const album = mediaService.folders[playerState.folderId];
|
|
140
|
+
if (album) {
|
|
141
|
+
const audios = mediaService.getAudios(selected.Value);
|
|
142
|
+
selected.value = audios;
|
|
143
|
+
items.splice(0, items.length, ...audios.Files);
|
|
144
|
+
playItems.splice(0, items.length, ...audios.Files);
|
|
145
|
+
if (playerState.mediaId) {
|
|
146
|
+
playIndex.value = items.findIndex((it) => it.DLNAID == playerState.mediaId);
|
|
147
|
+
if (playIndex.value >= 0) {
|
|
148
|
+
playingTrack.value = items[playIndex.value];
|
|
149
|
+
position.value = playingTrack.value.duration * playerState.duration / 100;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
computeListHeight();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
timer = window.setTimeout(getPlayerState, 1000);
|
|
156
|
+
}
|
|
112
157
|
function onEnded() {
|
|
113
158
|
mediaService.log.trace(`onEnded ${playIndex} ended`);
|
|
114
159
|
if (playIndex.value < playItems.length - 1)
|
|
115
160
|
play(playIndex.value + 1);
|
|
116
161
|
}
|
|
117
|
-
function play(index: number) {
|
|
162
|
+
async function play(index: number) {
|
|
118
163
|
if (items.length == playItems.length && items[0].DLNAParentID == playItems[0].DLNAParentID)
|
|
119
164
|
itemIndex.value = index;
|
|
120
165
|
playIndex.value = index;
|
|
@@ -122,20 +167,38 @@
|
|
|
122
167
|
paused.value = false;
|
|
123
168
|
playingTrack.value = item;
|
|
124
169
|
playingTrackUrl.value = mediaService.getAudioUrl(item);
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
.
|
|
170
|
+
if (isLocal) {
|
|
171
|
+
audio.value!.src = playingTrackUrl.value;
|
|
172
|
+
audio.value!.load();
|
|
173
|
+
audio.value!.play()
|
|
174
|
+
.then(() => { mediaService.log.trace(`play ${index}ended`) });
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
const rc = await playerService.play({
|
|
178
|
+
playerName: currentPlayer,
|
|
179
|
+
folderId: selected.value.DLNAID,
|
|
180
|
+
mediaId: playingTrack.value.DLNAID,
|
|
181
|
+
trackNo: playingTrack.value.TrackNo
|
|
182
|
+
});
|
|
183
|
+
}
|
|
129
184
|
}
|
|
130
185
|
function playpause() {
|
|
131
|
-
if (
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
.
|
|
186
|
+
if (isLocal) {
|
|
187
|
+
if (audio.value!.paused) {
|
|
188
|
+
paused.value = false;
|
|
189
|
+
audio.value!.play()
|
|
190
|
+
.then(() => { console.log("play ended") });
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
paused.value = true;
|
|
194
|
+
audio.value!.pause();
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
if (paused.value) {
|
|
198
|
+
playerService.play({ playerName: currentPlayer });
|
|
135
199
|
}
|
|
136
200
|
else {
|
|
137
|
-
|
|
138
|
-
audio.value!.pause();
|
|
201
|
+
playerService.pause(currentPlayer);
|
|
139
202
|
}
|
|
140
203
|
}
|
|
141
204
|
function previous() {
|
|
@@ -181,14 +244,28 @@
|
|
|
181
244
|
<audio ref="audio" preload="none" @ended="onEnded" @timeupdate="onTimeUpdate">
|
|
182
245
|
</audio>
|
|
183
246
|
<v-list-item three-line>
|
|
184
|
-
<v-
|
|
185
|
-
<
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
247
|
+
<v-row>
|
|
248
|
+
<v-col cols="4">
|
|
249
|
+
<v-select v-model="currentPlayer"
|
|
250
|
+
:items="playerNames"
|
|
251
|
+
persistent-hint
|
|
252
|
+
@update:modelValue="onPlayerChange"
|
|
253
|
+
dense solo hide-details single-line>
|
|
254
|
+
</v-select>
|
|
255
|
+
</v-col>
|
|
256
|
+
<v-col cols="2">
|
|
257
|
+
<v-list-item-avatar tile rounded="0" size="x-large" v-if="selected.ThumbnailUrl">
|
|
258
|
+
<img width="40" :src="selected.ThumbnailUrl">
|
|
259
|
+
</v-list-item-avatar>
|
|
260
|
+
</v-col>
|
|
261
|
+
<v-col cols="6">
|
|
262
|
+
<v-list-item-content>
|
|
263
|
+
<v-list-item-title>{{selected.title}}</v-list-item-title>
|
|
264
|
+
<v-list-item-subtitle>{{selected.subTitle}}</v-list-item-subtitle>
|
|
265
|
+
<v-list-item-subtitle v-if="playingTrack">{{playingTrack.Name}}</v-list-item-subtitle>
|
|
266
|
+
</v-list-item-content>
|
|
267
|
+
</v-col>
|
|
268
|
+
</v-row>
|
|
192
269
|
</v-list-item>
|
|
193
270
|
<v-card-actions>
|
|
194
271
|
<v-btn v-if="backVisible" @click="listBack">
|
package/src/views/PhotosPage.vue
CHANGED
|
@@ -160,7 +160,7 @@
|
|
|
160
160
|
<v-icon large>{{$vuetify.icons.values.back}}</v-icon>Back
|
|
161
161
|
</v-btn>
|
|
162
162
|
<v-rating clearable length="2" v-model="selected.rating" @update:modelValue="onRating" />
|
|
163
|
-
<v-select v-model="selected.root"
|
|
163
|
+
<v-select v-model="selected.root"
|
|
164
164
|
:items="roots"
|
|
165
165
|
persistent-hint
|
|
166
166
|
@update:modelValue="onRootChange"
|