mirror of
https://github.com/owntone/owntone-server.git
synced 2024-12-26 23:25:56 -05:00
Merge pull request #703 from chme/json_web
Small JSON API fixes + small web interface updates (v0.5.1)
This commit is contained in:
commit
fb98eb68ca
@ -600,6 +600,7 @@ POST /api/queue/items/add
|
||||
| expression | A smart playlist query expression identifying the tracks that will be added to the queue. |
|
||||
| position | *(Optional)* If a position is given, new items are inserted starting from this position into the queue. |
|
||||
| playback | *(Optional)* If the `playback` parameter is set to `start`, playback will be started after adding the new items. |
|
||||
| playback_from_position | *(Optional)* If the `playback` parameter is set to `start`, playback will be started with the queue item at the position given in `playback_from_position`. |
|
||||
| clear | *(Optional)* If the `clear` parameter is set to `true`, the queue will be cleared before adding the new items. |
|
||||
| shuffle | *(Optional)* If the `shuffle` parameter is set to `true`, the shuffle mode is activated. If it is set to something else, the shuffle mode is deactivated. To leave the shuffle mode untouched the parameter should be ommited. |
|
||||
|
||||
@ -2048,7 +2049,7 @@ curl --include \
|
||||
| date_released | string | Date in the format `yyyy-mm-dd` |
|
||||
| seek_ms | integer | Resume point in milliseconds (available only for podcasts and audiobooks) |
|
||||
| media_kind | string | Media type of this track: `music`, `movie`, `podcast`, `audiobook`, `musicvideo`, `tvshow` |
|
||||
| data_kind | string | Data type of this track: `file`, `stream`, `spotify`, `pipe` |
|
||||
| data_kind | string | Data type of this track: `file`, `url`, `spotify`, `pipe` |
|
||||
| path | string | Path |
|
||||
| uri | string | Resource identifier |
|
||||
| artwork_url | string | *(optional)* [Artwork url](#artwork-urls) |
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1893,7 +1893,7 @@ queue_tracks_add_byexpression(const char *param, int pos, int *total_count)
|
||||
memset(&query_params, 0, sizeof(struct query_params));
|
||||
|
||||
query_params.type = Q_ITEMS;
|
||||
query_params.sort = S_ALBUM;
|
||||
query_params.sort = S_NAME;
|
||||
query_params.idx_type = I_NONE;
|
||||
|
||||
memset(&smartpl_expression, 0, sizeof(struct smartpl));
|
||||
@ -1905,13 +1905,14 @@ queue_tracks_add_byexpression(const char *param, int pos, int *total_count)
|
||||
return -1;
|
||||
|
||||
query_params.filter = strdup(smartpl_expression.query_where);
|
||||
query_params.order = safe_strdup(smartpl_expression.order);
|
||||
free_smartpl(&smartpl_expression, 1);
|
||||
|
||||
player_get_status(&status);
|
||||
|
||||
ret = db_queue_add_by_query(&query_params, status.shuffle, status.item_id, pos, total_count, NULL);
|
||||
|
||||
free(query_params.filter);
|
||||
free_query_params(&query_params, 1);
|
||||
|
||||
return ret;
|
||||
|
||||
@ -1995,7 +1996,10 @@ jsonapi_reply_queue_tracks_add(struct httpd_request *hreq)
|
||||
param = evhttp_find_header(hreq->query, "playback");
|
||||
if (param && strcmp(param, "start") == 0)
|
||||
{
|
||||
player_playback_start();
|
||||
if ((param = evhttp_find_header(hreq->query, "playback_from_position")))
|
||||
play_item_at_position(param);
|
||||
else
|
||||
player_playback_start();
|
||||
}
|
||||
|
||||
return HTTP_OK;
|
||||
|
999
web-src/package-lock.json
generated
999
web-src/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "forked-daapd-web",
|
||||
"version": "0.5.0",
|
||||
"version": "0.5.1",
|
||||
"description": "forked-daapd web interface",
|
||||
"author": "chme <christian.meffert@googlemail.com>",
|
||||
"license": "GPL-2.0",
|
||||
@ -20,7 +20,7 @@
|
||||
"npm": "^6.8.0",
|
||||
"reconnectingwebsocket": "^1.0.0",
|
||||
"spotify-web-api-js": "^1.2.0",
|
||||
"vue": "^2.6.6",
|
||||
"vue": "^2.6.7",
|
||||
"vue-infinite-loading": "^2.4.3",
|
||||
"vue-progressbar": "^0.7.4",
|
||||
"vue-range-slider": "^0.6.0",
|
||||
@ -29,10 +29,10 @@
|
||||
"vuex": "^3.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "^3.4.0",
|
||||
"@vue/cli-plugin-eslint": "^3.4.0",
|
||||
"@vue/cli-service": "^3.4.0",
|
||||
"@vue/cli-plugin-babel": "^3.4.1",
|
||||
"@vue/cli-plugin-eslint": "^3.4.1",
|
||||
"@vue/cli-service": "^3.4.1",
|
||||
"@vue/eslint-config-standard": "^3.0.5",
|
||||
"vue-template-compiler": "^2.6.6"
|
||||
"vue-template-compiler": "^2.6.7"
|
||||
}
|
||||
}
|
||||
|
@ -39,23 +39,17 @@ export default {
|
||||
methods: {
|
||||
play: function () {
|
||||
this.$emit('close')
|
||||
webapi.search({ 'type': 'tracks', 'expression': 'path starts with "' + this.directory.path + '" order by path asc' }).then(({ data }) => {
|
||||
webapi.player_play_uri(data.tracks.items.map(a => a.uri).join(','), false)
|
||||
})
|
||||
webapi.player_play_expression('path starts with "' + this.directory.path + '" order by path asc', false)
|
||||
},
|
||||
|
||||
queue_add: function () {
|
||||
this.$emit('close')
|
||||
webapi.search({ 'type': 'tracks', 'expression': 'path starts with "' + this.directory.path + '" order by path asc' }).then(({ data }) => {
|
||||
webapi.queue_add(data.tracks.items.map(a => a.uri).join(','))
|
||||
})
|
||||
webapi.queue_expression_add('path starts with "' + this.directory.path + '" order by path asc')
|
||||
},
|
||||
|
||||
queue_add_next: function () {
|
||||
this.$emit('close')
|
||||
webapi.search({ 'type': 'tracks', 'expression': 'path starts with "' + this.directory.path + '" order by path asc' }).then(({ data }) => {
|
||||
webapi.queue_add_next(data.tracks.items.map(a => a.uri).join(','))
|
||||
})
|
||||
webapi.queue_expression_add_next('path starts with "' + this.directory.path + '" order by path asc')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,23 +39,17 @@ export default {
|
||||
methods: {
|
||||
play: function () {
|
||||
this.$emit('close')
|
||||
webapi.library_genre_tracks(this.genre.name).then(({ data }) =>
|
||||
webapi.player_play_uri(data.tracks.items.map(a => a.uri).join(','), false)
|
||||
)
|
||||
webapi.player_play_expression('genre is "' + this.genre.name + '" and media_kind is music', false)
|
||||
},
|
||||
|
||||
queue_add: function () {
|
||||
this.$emit('close')
|
||||
webapi.library_genre_tracks(this.genre.name).then(({ data }) =>
|
||||
webapi.queue_add(data.tracks.items.map(a => a.uri).join(','))
|
||||
)
|
||||
webapi.queue_expression_add('genre is "' + this.genre.name + '" and media_kind is music')
|
||||
},
|
||||
|
||||
queue_add_next: function () {
|
||||
this.$emit('close')
|
||||
webapi.library_genre_tracks(this.genre.name).then(({ data }) =>
|
||||
webapi.queue_add_next(data.tracks.items.map(a => a.uri).join(','))
|
||||
)
|
||||
webapi.queue_expression_add_next('genre is "' + this.genre.name + '" and media_kind is music')
|
||||
},
|
||||
|
||||
open_genre: function () {
|
||||
|
@ -47,6 +47,10 @@
|
||||
<span class="heading">Path</span>
|
||||
<span class="title is-6">{{ item.path }}</span>
|
||||
</p>
|
||||
<p>
|
||||
<span class="heading">Type</span>
|
||||
<span class="title is-6">{{ item.media_kind }} - {{ item.data_kind }} <span class="has-text-weight-normal" v-if="item.data_kind === 'spotify'">(<a @click="open_spotify_artist">artist</a>, <a @click="open_spotify_album">album</a>)</span></span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<footer class="card-footer">
|
||||
@ -67,11 +71,18 @@
|
||||
|
||||
<script>
|
||||
import webapi from '@/webapi'
|
||||
import SpotifyWebApi from 'spotify-web-api-js'
|
||||
|
||||
export default {
|
||||
name: 'ModalDialogQueueItem',
|
||||
props: [ 'show', 'item' ],
|
||||
|
||||
data () {
|
||||
return {
|
||||
spotify_track: {}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
remove: function () {
|
||||
this.$emit('close')
|
||||
@ -99,6 +110,30 @@ export default {
|
||||
|
||||
open_genre: function () {
|
||||
this.$router.push({ name: 'Genre', params: { genre: this.item.genre } })
|
||||
},
|
||||
|
||||
open_spotify_artist: function () {
|
||||
this.$emit('close')
|
||||
this.$router.push({ path: '/music/spotify/artists/' + this.spotify_track.artists[0].id })
|
||||
},
|
||||
|
||||
open_spotify_album: function () {
|
||||
this.$emit('close')
|
||||
this.$router.push({ path: '/music/spotify/albums/' + this.spotify_track.album.id })
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
'item' () {
|
||||
if (this.item && this.item.data_kind === 'spotify') {
|
||||
const spotifyApi = new SpotifyWebApi()
|
||||
spotifyApi.setAccessToken(this.$store.state.spotify.webapi_token)
|
||||
spotifyApi.getTrack(this.item.path.slice(this.item.path.lastIndexOf(':') + 1)).then((response) => {
|
||||
this.spotify_track = response
|
||||
})
|
||||
} else {
|
||||
this.spotify_track = {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
<div>
|
||||
<p class="is-size-7 fd-is-text-clipped">
|
||||
<strong>{{ now_playing.title }}</strong><br>
|
||||
{{ now_playing.artist }}
|
||||
{{ now_playing.artist }}<span v-if="now_playing.data_kind === 'url'"> - {{ now_playing.album }}</span>
|
||||
</p>
|
||||
</div>
|
||||
</router-link>
|
||||
|
@ -153,9 +153,7 @@ export default {
|
||||
},
|
||||
|
||||
play: function () {
|
||||
webapi.search({ 'type': 'tracks', 'expression': 'path starts with "' + this.current_directory + '" order by path asc' }).then(({ data }) => {
|
||||
webapi.player_play_uri(data.tracks.items.map(a => a.uri).join(','), false)
|
||||
})
|
||||
webapi.player_play_expression('path starts with "' + this.current_directory + '" order by path asc', false)
|
||||
},
|
||||
|
||||
play_track: function (position) {
|
||||
|
@ -85,9 +85,7 @@ export default {
|
||||
},
|
||||
|
||||
play: function () {
|
||||
webapi.library_genre_tracks(this.name).then(({ data }) =>
|
||||
webapi.player_play_uri(data.tracks.items.map(a => a.uri).join(','), true)
|
||||
)
|
||||
webapi.player_play_expression('genre is "' + this.name + '" and media_kind is music', true)
|
||||
},
|
||||
|
||||
open_album: function (album) {
|
||||
|
@ -84,11 +84,11 @@ export default {
|
||||
},
|
||||
|
||||
play: function () {
|
||||
webapi.player_play_uri(this.tracks.items.map(a => a.uri).join(','), true)
|
||||
webapi.player_play_expression('genre is "' + this.genre + '" and media_kind is music', true)
|
||||
},
|
||||
|
||||
play_track: function (position) {
|
||||
webapi.player_play_uri(this.tracks.items.map(a => a.uri).join(','), false, position)
|
||||
webapi.player_play_expression('genre is "' + this.genre + '" and media_kind is music', false, position)
|
||||
},
|
||||
|
||||
open_dialog: function (track) {
|
||||
|
@ -41,11 +41,9 @@ export default {
|
||||
return axios.put('/api/queue/items/' + itemId + '?new_position=' + newPosition)
|
||||
},
|
||||
|
||||
queue_add (uri, showNotification = true) {
|
||||
queue_add (uri) {
|
||||
return axios.post('/api/queue/items/add?uris=' + uri).then((response) => {
|
||||
if (showNotification) {
|
||||
store.dispatch('add_notification', { text: response.data.count + ' tracks appended to queue', type: 'info', timeout: 2000 })
|
||||
}
|
||||
store.dispatch('add_notification', { text: response.data.count + ' tracks appended to queue', type: 'info', timeout: 2000 })
|
||||
return Promise.resolve(response)
|
||||
})
|
||||
},
|
||||
@ -61,18 +59,54 @@ export default {
|
||||
})
|
||||
},
|
||||
|
||||
queue_expression_add (expression) {
|
||||
var options = {}
|
||||
options.expression = expression
|
||||
|
||||
return axios.post('/api/queue/items/add', undefined, { params: options }).then((response) => {
|
||||
store.dispatch('add_notification', { text: response.data.count + ' tracks appended to queue', type: 'info', timeout: 2000 })
|
||||
return Promise.resolve(response)
|
||||
})
|
||||
},
|
||||
|
||||
queue_expression_add_next (expression) {
|
||||
var options = {}
|
||||
options.expression = expression
|
||||
options.position = 0
|
||||
if (store.getters.now_playing && store.getters.now_playing.id) {
|
||||
options.position = store.getters.now_playing.position + 1
|
||||
}
|
||||
|
||||
return axios.post('/api/queue/items/add', undefined, { params: options }).then((response) => {
|
||||
store.dispatch('add_notification', { text: response.data.count + ' tracks appended to queue', type: 'info', timeout: 2000 })
|
||||
return Promise.resolve(response)
|
||||
})
|
||||
},
|
||||
|
||||
player_status () {
|
||||
return axios.get('/api/player')
|
||||
},
|
||||
|
||||
player_play_uri (uris, shuffle, position = undefined) {
|
||||
return this.queue_clear().then(() =>
|
||||
this.player_shuffle(shuffle).then(() =>
|
||||
this.queue_add(uris, false).then(() =>
|
||||
this.player_play({ 'position': position })
|
||||
)
|
||||
)
|
||||
)
|
||||
var options = {}
|
||||
options.uris = uris
|
||||
options.shuffle = shuffle ? 'true' : 'false'
|
||||
options.clear = 'true'
|
||||
options.playback = 'start'
|
||||
options.playback_from_position = position
|
||||
|
||||
return axios.post('/api/queue/items/add', undefined, { params: options })
|
||||
},
|
||||
|
||||
player_play_expression (expression, shuffle, position = undefined) {
|
||||
var options = {}
|
||||
options.expression = expression
|
||||
options.shuffle = shuffle ? 'true' : 'false'
|
||||
options.clear = 'true'
|
||||
options.playback = 'start'
|
||||
options.playback_from_position = position
|
||||
|
||||
return axios.post('/api/queue/items/add', undefined, { params: options })
|
||||
},
|
||||
|
||||
player_play (options = {}) {
|
||||
|
Loading…
Reference in New Issue
Block a user