add radio support

This commit is contained in:
Thomas Amland 2020-09-07 18:43:22 +02:00
parent 4fca9f417b
commit c3a5136f0f
5 changed files with 127 additions and 0 deletions

View File

@ -38,6 +38,10 @@
<Icon icon="star" /> Starred <Icon icon="star" /> Starred
</router-link> </router-link>
<router-link class="nav-link" :to="{name: 'radio'}">
<Icon icon="broadcast" /> Radio
</router-link>
<PlaylistNav /> <PlaylistNav />
</nav> </nav>
</div> </div>

View File

@ -0,0 +1,66 @@
<template>
<div v-if="items">
<h1>Radio</h1>
<table class="table table-hover table-borderless">
<thead>
<tr>
<th class="text-left">
Title
</th>
<th class="text-right">
Actions
</th>
</tr>
</thead>
<tbody>
<tr v-for="(item, index) in items" :key="index"
:class="{'active': item.id === playingTrackId}">
<td @click="play(index)">
{{ item.title }}
<div>
<small class="text-muted">
{{ item.description }}
</small>
</div>
</td>
<td class="text-right">
<TrackContextMenu :track="item" />
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
import TrackContextMenu from '@/library/TrackContextMenu.vue'
import { RadioStation } from '@/shared/api'
import { mapGetters } from 'vuex'
export default Vue.extend({
components: {
TrackContextMenu,
},
data() {
return {
items: [] as RadioStation[],
}
},
computed: {
...mapGetters({
playingTrackId: 'player/trackId',
}),
},
async created() {
this.items = await this.$api.getRadioStations()
},
methods: {
play(index: number) {
if (this.items[index].id === this.playingTrackId) {
return this.$store.dispatch('player/playPause')
}
return this.$store.dispatch('player/playQueue', { index, queue: this.items })
},
}
})
</script>

View File

@ -52,6 +52,13 @@ export interface SearchResult {
tracks: Track[] tracks: Track[]
} }
export interface RadioStation {
id: string
title: string
description: string
url: string
}
export class API { export class API {
readonly http: AxiosInstance; readonly http: AxiosInstance;
readonly get: (path: string, params?: any) => Promise<any>; readonly get: (path: string, params?: any) => Promise<any>;
@ -274,6 +281,48 @@ export class API {
} }
} }
async getRadioStations(): Promise<RadioStation[]> {
const response = await this.get('rest/getInternetRadioStations')
return (response?.internetRadioStations?.internetRadioStation || [])
.map(this.normalizeRadioStation, this)
}
async addRadioStation(title: string, url: string): Promise<RadioStation> {
const params = {
name: title,
streamUrl: url,
}
return this
.get('rest/createInternetRadioStation', params)
.then(this.normalizeRadioStation)
}
async updateRadioStation(item: RadioStation): Promise<RadioStation> {
const params = {
id: item.id,
name: item.title,
streamUrl: item.url,
}
return this
.get('rest/updateInternetRadioStation', params)
.then(this.normalizeRadioStation)
}
async deleteRadioStation(id: string): Promise<void> {
return this.get('rest/deleteInternetRadioStation', { id })
}
private normalizeRadioStation(item: any): Track & RadioStation {
return {
id: `radio-${item.id}`,
title: item.name,
description: item.homePageUrl,
url: item.streamUrl,
duration: 0,
starred: false,
}
}
private normalizeTrack(item: any): Track { private normalizeTrack(item: any): Track {
return { return {
id: item.id, id: item.id,

View File

@ -5,6 +5,7 @@
import Vue from 'vue' import Vue from 'vue'
import { import {
BIcon, BIcon,
BIconBroadcast,
BIconCardText, BIconCardText,
BIconChevronCompactRight, BIconChevronCompactRight,
BIconMusicNoteList, BIconMusicNoteList,
@ -28,6 +29,7 @@
export default Vue.extend({ export default Vue.extend({
components: { components: {
BIcon, BIcon,
BIconBroadcast,
BIconCardText, BIconCardText,
BIconChevronCompactRight, BIconChevronCompactRight,
BIconMusicNoteList, BIconMusicNoteList,

View File

@ -10,6 +10,7 @@ import RandomSongs from '@/playlist/RandomSongs.vue'
import GenreDetails from '@/library/genre/GenreDetails.vue' import GenreDetails from '@/library/genre/GenreDetails.vue'
import GenreLibrary from '@/library/genre/GenreLibrary.vue' import GenreLibrary from '@/library/genre/GenreLibrary.vue'
import Starred from '@/library/starred/Starred.vue' import Starred from '@/library/starred/Starred.vue'
import RadioStations from '@/library/radio/RadioStations.vue'
import Playlist from '@/playlist/Playlist.vue' import Playlist from '@/playlist/Playlist.vue'
import PlaylistList from '@/playlist/PlaylistList.vue' import PlaylistList from '@/playlist/PlaylistList.vue'
import SearchResult from '@/search/SearchResult.vue' import SearchResult from '@/search/SearchResult.vue'
@ -78,6 +79,11 @@ export function setupRouter(auth: AuthService) {
path: '/starred', path: '/starred',
component: Starred, component: Starred,
}, },
{
name: 'radio',
path: '/radio',
component: RadioStations,
},
{ {
name: 'playlists', name: 'playlists',
path: '/playlists', path: '/playlists',