mirror of
https://github.com/owntone/owntone-server.git
synced 2025-01-14 16:25:03 -05:00
Enable resuming playback from saved position for certain media kinds (eg audiobooks)
This commit is contained in:
parent
7881df67f6
commit
68912efa1f
@ -187,7 +187,7 @@ expression returns [ pANTLR3_STRING result ]
|
|||||||
}
|
}
|
||||||
else if (strcmp((char *)val, "url") == 0)
|
else if (strcmp((char *)val, "url") == 0)
|
||||||
{
|
{
|
||||||
sprintf(str, "f.data_kind = \%d", DATA_KIND_URL);
|
sprintf(str, "f.data_kind = \%d", DATA_KIND_HTTP);
|
||||||
}
|
}
|
||||||
else if (strcmp((char *)val, "spotify") == 0)
|
else if (strcmp((char *)val, "spotify") == 0)
|
||||||
{
|
{
|
||||||
|
23
src/db.c
23
src/db.c
@ -2050,7 +2050,7 @@ db_files_update_songalbumid(void)
|
|||||||
void
|
void
|
||||||
db_file_inc_playcount(int id)
|
db_file_inc_playcount(int id)
|
||||||
{
|
{
|
||||||
#define Q_TMPL "UPDATE files SET play_count = play_count + 1, time_played = %" PRIi64 " WHERE id = %d;"
|
#define Q_TMPL "UPDATE files SET play_count = play_count + 1, time_played = %" PRIi64 ", seek = 0 WHERE id = %d;"
|
||||||
char *query;
|
char *query;
|
||||||
|
|
||||||
query = sqlite3_mprintf(Q_TMPL, (int64_t)time(NULL), id);
|
query = sqlite3_mprintf(Q_TMPL, (int64_t)time(NULL), id);
|
||||||
@ -2754,6 +2754,27 @@ db_file_update_icy(int id, char *artist, char *album)
|
|||||||
#undef Q_TMPL
|
#undef Q_TMPL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
db_file_save_seek(int id, uint32_t seek)
|
||||||
|
{
|
||||||
|
#define Q_TMPL "UPDATE files SET seek = %d WHERE id = %d;"
|
||||||
|
char *query;
|
||||||
|
|
||||||
|
if (id == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
query = sqlite3_mprintf(Q_TMPL, seek, id);
|
||||||
|
if (!query)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_DB, "Out of memory for query string\n");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
db_query_run(query, 1, 0);
|
||||||
|
#undef Q_TMPL
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
db_file_delete_bypath(char *path)
|
db_file_delete_bypath(char *path)
|
||||||
{
|
{
|
||||||
|
5
src/db.h
5
src/db.h
@ -104,7 +104,7 @@ enum media_kind {
|
|||||||
|
|
||||||
enum data_kind {
|
enum data_kind {
|
||||||
DATA_KIND_FILE = 0, /* normal file */
|
DATA_KIND_FILE = 0, /* normal file */
|
||||||
DATA_KIND_URL = 1, /* url/stream */
|
DATA_KIND_HTTP = 1, /* network stream (radio) */
|
||||||
DATA_KIND_SPOTIFY = 2, /* iTunes has no spotify data kind, but we use 2 */
|
DATA_KIND_SPOTIFY = 2, /* iTunes has no spotify data kind, but we use 2 */
|
||||||
DATA_KIND_PIPE = 3, /* iTunes has no pipe data kind, but we use 3 */
|
DATA_KIND_PIPE = 3, /* iTunes has no pipe data kind, but we use 3 */
|
||||||
};
|
};
|
||||||
@ -473,6 +473,9 @@ db_file_update(struct media_file_info *mfi);
|
|||||||
void
|
void
|
||||||
db_file_update_icy(int id, char *artist, char *album);
|
db_file_update_icy(int id, char *artist, char *album);
|
||||||
|
|
||||||
|
void
|
||||||
|
db_file_save_seek(int id, uint32_t seek);
|
||||||
|
|
||||||
void
|
void
|
||||||
db_file_delete_bypath(char *path);
|
db_file_delete_bypath(char *path);
|
||||||
|
|
||||||
|
@ -706,7 +706,7 @@ filescanner_process_media(char *path, time_t mtime, off_t size, int type, struct
|
|||||||
}
|
}
|
||||||
else if (type & F_SCAN_TYPE_URL)
|
else if (type & F_SCAN_TYPE_URL)
|
||||||
{
|
{
|
||||||
mfi->data_kind = DATA_KIND_URL;
|
mfi->data_kind = DATA_KIND_HTTP;
|
||||||
ret = scan_metadata_ffmpeg(path, mfi);
|
ret = scan_metadata_ffmpeg(path, mfi);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
|
@ -335,14 +335,14 @@ scan_metadata_ffmpeg(char *file, struct media_file_info *mfi)
|
|||||||
#if LIBAVFORMAT_VERSION_MAJOR >= 54 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR >= 3)
|
#if LIBAVFORMAT_VERSION_MAJOR >= 54 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR >= 3)
|
||||||
# ifndef HAVE_FFMPEG
|
# ifndef HAVE_FFMPEG
|
||||||
// Without this, libav is slow to probe some internet streams
|
// Without this, libav is slow to probe some internet streams
|
||||||
if (mfi->data_kind == DATA_KIND_URL)
|
if (mfi->data_kind == DATA_KIND_HTTP)
|
||||||
{
|
{
|
||||||
ctx = avformat_alloc_context();
|
ctx = avformat_alloc_context();
|
||||||
ctx->probesize = 64000;
|
ctx->probesize = 64000;
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
if (mfi->data_kind == DATA_KIND_URL)
|
if (mfi->data_kind == DATA_KIND_HTTP)
|
||||||
{
|
{
|
||||||
free(path);
|
free(path);
|
||||||
ret = http_stream_setup(&path, file);
|
ret = http_stream_setup(&path, file);
|
||||||
@ -481,8 +481,8 @@ scan_metadata_ffmpeg(char *file, struct media_file_info *mfi)
|
|||||||
|
|
||||||
DPRINTF(E_DBG, L_SCAN, "Duration %d ms, bitrate %d kbps\n", mfi->song_length, mfi->bitrate);
|
DPRINTF(E_DBG, L_SCAN, "Duration %d ms, bitrate %d kbps\n", mfi->song_length, mfi->bitrate);
|
||||||
|
|
||||||
/* Try to extract ICY metadata if url/stream */
|
/* Try to extract ICY metadata if http stream */
|
||||||
if (mfi->data_kind == DATA_KIND_URL)
|
if (mfi->data_kind == DATA_KIND_HTTP)
|
||||||
{
|
{
|
||||||
icy_metadata = http_icy_metadata_get(ctx, 0);
|
icy_metadata = http_icy_metadata_get(ctx, 0);
|
||||||
if (icy_metadata && icy_metadata->name)
|
if (icy_metadata && icy_metadata->name)
|
||||||
|
@ -170,7 +170,7 @@ dacp_nowplaying(struct evbuffer *evbuf, struct player_status *status, struct med
|
|||||||
* FIXME: Giving the client invalid ids on purpose is hardly ideal, but the
|
* FIXME: Giving the client invalid ids on purpose is hardly ideal, but the
|
||||||
* clients don't seem to use these ids for anything other than rating.
|
* clients don't seem to use these ids for anything other than rating.
|
||||||
*/
|
*/
|
||||||
if (mfi->data_kind == DATA_KIND_URL)
|
if (mfi->data_kind == DATA_KIND_HTTP)
|
||||||
{
|
{
|
||||||
id = djb_hash(mfi->album, strlen(mfi->album));
|
id = djb_hash(mfi->album, strlen(mfi->album));
|
||||||
songalbumid = (int64_t)id;
|
songalbumid = (int64_t)id;
|
||||||
|
@ -491,7 +491,7 @@ scrobble(int id)
|
|||||||
goto noscrobble;
|
goto noscrobble;
|
||||||
|
|
||||||
// Don't scrobble non-music and radio stations
|
// Don't scrobble non-music and radio stations
|
||||||
if ((mfi->media_kind != MEDIA_KIND_MUSIC) || (mfi->data_kind == DATA_KIND_URL))
|
if ((mfi->media_kind != MEDIA_KIND_MUSIC) || (mfi->data_kind == DATA_KIND_HTTP))
|
||||||
goto noscrobble;
|
goto noscrobble;
|
||||||
|
|
||||||
// Don't scrobble songs with unknown artist
|
// Don't scrobble songs with unknown artist
|
||||||
|
@ -81,7 +81,7 @@ pipe_setup(struct media_file_info *mfi)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
93
src/player.c
93
src/player.c
@ -1173,21 +1173,21 @@ player_queue_make_mpd(char *path, int recursive)
|
|||||||
static void
|
static void
|
||||||
source_free(struct player_source *ps)
|
source_free(struct player_source *ps)
|
||||||
{
|
{
|
||||||
switch (ps->type)
|
switch (ps->data_kind)
|
||||||
{
|
{
|
||||||
case SOURCE_FILE:
|
case DATA_KIND_FILE:
|
||||||
case SOURCE_HTTP:
|
case DATA_KIND_HTTP:
|
||||||
if (ps->ctx)
|
if (ps->ctx)
|
||||||
transcode_cleanup(ps->ctx);
|
transcode_cleanup(ps->ctx);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SOURCE_SPOTIFY:
|
case DATA_KIND_SPOTIFY:
|
||||||
#ifdef HAVE_SPOTIFY_H
|
#ifdef HAVE_SPOTIFY_H
|
||||||
spotify_playback_stop();
|
spotify_playback_stop();
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SOURCE_PIPE:
|
case DATA_KIND_PIPE:
|
||||||
pipe_cleanup();
|
pipe_cleanup();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1202,10 +1202,10 @@ source_stop(struct player_source *ps)
|
|||||||
|
|
||||||
while (ps)
|
while (ps)
|
||||||
{
|
{
|
||||||
switch (ps->type)
|
switch (ps->data_kind)
|
||||||
{
|
{
|
||||||
case SOURCE_FILE:
|
case DATA_KIND_FILE:
|
||||||
case SOURCE_HTTP:
|
case DATA_KIND_HTTP:
|
||||||
if (ps->ctx)
|
if (ps->ctx)
|
||||||
{
|
{
|
||||||
transcode_cleanup(ps->ctx);
|
transcode_cleanup(ps->ctx);
|
||||||
@ -1213,13 +1213,13 @@ source_stop(struct player_source *ps)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SOURCE_SPOTIFY:
|
case DATA_KIND_SPOTIFY:
|
||||||
#ifdef HAVE_SPOTIFY_H
|
#ifdef HAVE_SPOTIFY_H
|
||||||
spotify_playback_stop();
|
spotify_playback_stop();
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SOURCE_PIPE:
|
case DATA_KIND_PIPE:
|
||||||
pipe_cleanup();
|
pipe_cleanup();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1360,7 +1360,7 @@ source_reshuffle(void)
|
|||||||
|
|
||||||
/* Helper */
|
/* Helper */
|
||||||
static int
|
static int
|
||||||
source_open(struct player_source *ps, int no_md)
|
source_open(struct player_source *ps, int no_md, int seek)
|
||||||
{
|
{
|
||||||
struct media_file_info *mfi;
|
struct media_file_info *mfi;
|
||||||
char *url;
|
char *url;
|
||||||
@ -1390,12 +1390,13 @@ source_open(struct player_source *ps, int no_md)
|
|||||||
|
|
||||||
DPRINTF(E_INFO, L_PLAYER, "Opening '%s' (%s)\n", mfi->title, mfi->path);
|
DPRINTF(E_INFO, L_PLAYER, "Opening '%s' (%s)\n", mfi->title, mfi->path);
|
||||||
|
|
||||||
|
ps->data_kind = mfi->data_kind;
|
||||||
|
ps->media_kind = mfi->media_kind;
|
||||||
|
|
||||||
// Setup the source type responsible for getting the audio
|
// Setup the source type responsible for getting the audio
|
||||||
switch (mfi->data_kind)
|
switch (mfi->data_kind)
|
||||||
{
|
{
|
||||||
case DATA_KIND_URL:
|
case DATA_KIND_HTTP:
|
||||||
ps->type = SOURCE_HTTP;
|
|
||||||
|
|
||||||
ret = http_stream_setup(&url, mfi->path);
|
ret = http_stream_setup(&url, mfi->path);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
break;
|
break;
|
||||||
@ -1407,22 +1408,29 @@ source_open(struct player_source *ps, int no_md)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case DATA_KIND_SPOTIFY:
|
case DATA_KIND_SPOTIFY:
|
||||||
ps->type = SOURCE_SPOTIFY;
|
|
||||||
#ifdef HAVE_SPOTIFY_H
|
#ifdef HAVE_SPOTIFY_H
|
||||||
ret = spotify_playback_play(mfi);
|
ret = spotify_playback_play(mfi);
|
||||||
|
if (seek && mfi->seek)
|
||||||
|
{
|
||||||
|
DPRINTF(E_DBG, L_PLAYER, "Source id %d started with seek %d\n", ps->id, mfi->seek);
|
||||||
|
ret = spotify_playback_seek(mfi->seek);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
ret = -1;
|
ret = -1;
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DATA_KIND_PIPE:
|
case DATA_KIND_PIPE:
|
||||||
ps->type = SOURCE_PIPE;
|
|
||||||
ret = pipe_setup(mfi);
|
ret = pipe_setup(mfi);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ps->type = SOURCE_FILE;
|
|
||||||
ret = transcode_setup(&ps->ctx, mfi, NULL, 0);
|
ret = transcode_setup(&ps->ctx, mfi, NULL, 0);
|
||||||
|
if (seek && mfi->seek)
|
||||||
|
{
|
||||||
|
DPRINTF(E_DBG, L_PLAYER, "Source id %d started with seek %d\n", ps->id, mfi->seek);
|
||||||
|
ret = transcode_seek(ps->ctx, mfi->seek);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free_mfi(mfi, 0);
|
free_mfi(mfi, 0);
|
||||||
@ -1439,7 +1447,7 @@ source_open(struct player_source *ps, int no_md)
|
|||||||
|
|
||||||
ps->setup_done = 1;
|
ps->setup_done = 1;
|
||||||
|
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -1479,7 +1487,7 @@ source_next(int force)
|
|||||||
if (!cur_streaming)
|
if (!cur_streaming)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if ((cur_streaming->type == SOURCE_FILE) && cur_streaming->ctx)
|
if ((cur_streaming->data_kind == DATA_KIND_FILE) && cur_streaming->ctx)
|
||||||
{
|
{
|
||||||
ret = transcode_seek(cur_streaming->ctx, 0);
|
ret = transcode_seek(cur_streaming->ctx, 0);
|
||||||
|
|
||||||
@ -1491,7 +1499,7 @@ source_next(int force)
|
|||||||
metadata_trigger(cur_streaming, 0);
|
metadata_trigger(cur_streaming, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ret = source_open(cur_streaming, force);
|
ret = source_open(cur_streaming, force, 0);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
@ -1535,7 +1543,7 @@ source_next(int force)
|
|||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
ret = source_open(ps, force);
|
ret = source_open(ps, force, 0);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
if (shuffle)
|
if (shuffle)
|
||||||
@ -1593,7 +1601,7 @@ source_prev(void)
|
|||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
ret = source_open(ps, 1);
|
ret = source_open(ps, 1, 0);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
if (shuffle)
|
if (shuffle)
|
||||||
@ -1741,7 +1749,7 @@ source_check(void)
|
|||||||
|
|
||||||
if (ps->setup_done)
|
if (ps->setup_done)
|
||||||
{
|
{
|
||||||
if ((ps->type == SOURCE_FILE) && ps->ctx)
|
if ((ps->data_kind == DATA_KIND_FILE) && ps->ctx)
|
||||||
{
|
{
|
||||||
transcode_cleanup(ps->ctx);
|
transcode_cleanup(ps->ctx);
|
||||||
ps->ctx = NULL;
|
ps->ctx = NULL;
|
||||||
@ -1796,7 +1804,7 @@ source_check(void)
|
|||||||
|
|
||||||
if (ps->setup_done)
|
if (ps->setup_done)
|
||||||
{
|
{
|
||||||
if ((ps->type == SOURCE_FILE) && ps->ctx)
|
if ((ps->data_kind == DATA_KIND_FILE) && ps->ctx)
|
||||||
{
|
{
|
||||||
transcode_cleanup(ps->ctx);
|
transcode_cleanup(ps->ctx);
|
||||||
ps->ctx = NULL;
|
ps->ctx = NULL;
|
||||||
@ -1882,26 +1890,26 @@ source_read(uint8_t *buf, int len, uint64_t rtptime)
|
|||||||
|
|
||||||
if (evbuffer_get_length(audio_buf) == 0)
|
if (evbuffer_get_length(audio_buf) == 0)
|
||||||
{
|
{
|
||||||
switch (cur_streaming->type)
|
switch (cur_streaming->data_kind)
|
||||||
{
|
{
|
||||||
case SOURCE_HTTP:
|
case DATA_KIND_HTTP:
|
||||||
ret = transcode(cur_streaming->ctx, audio_buf, len - nbytes, &icy_timer);
|
ret = transcode(cur_streaming->ctx, audio_buf, len - nbytes, &icy_timer);
|
||||||
|
|
||||||
if (icy_timer)
|
if (icy_timer)
|
||||||
metadata_check_icy();
|
metadata_check_icy();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SOURCE_FILE:
|
case DATA_KIND_FILE:
|
||||||
ret = transcode(cur_streaming->ctx, audio_buf, len - nbytes, &icy_timer);
|
ret = transcode(cur_streaming->ctx, audio_buf, len - nbytes, &icy_timer);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef HAVE_SPOTIFY_H
|
#ifdef HAVE_SPOTIFY_H
|
||||||
case SOURCE_SPOTIFY:
|
case DATA_KIND_SPOTIFY:
|
||||||
ret = spotify_audio_get(audio_buf, len - nbytes);
|
ret = spotify_audio_get(audio_buf, len - nbytes);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case SOURCE_PIPE:
|
case DATA_KIND_PIPE:
|
||||||
ret = pipe_audio_get(audio_buf, len - nbytes);
|
ret = pipe_audio_get(audio_buf, len - nbytes);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -2647,7 +2655,7 @@ artwork_url_get(struct player_command *cmd)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Check that we are playing a viable stream, and that it has the requested id */
|
/* Check that we are playing a viable stream, and that it has the requested id */
|
||||||
if (!ps->ctx || ps->type != SOURCE_HTTP || ps->id != cmd->arg.icy.id)
|
if (!ps->ctx || ps->data_kind != DATA_KIND_HTTP || ps->id != cmd->arg.icy.id)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
transcode_metadata_artwork_url(ps->ctx, &cmd->arg.icy.artwork_url);
|
transcode_metadata_artwork_url(ps->ctx, &cmd->arg.icy.artwork_url);
|
||||||
@ -2874,7 +2882,7 @@ playback_start(struct player_command *cmd)
|
|||||||
else
|
else
|
||||||
cur_streaming = ps;
|
cur_streaming = ps;
|
||||||
|
|
||||||
ret = source_open(cur_streaming, 0);
|
ret = source_open(cur_streaming, 0, 1);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_PLAYER, "Couldn't jump to source %d in queue\n", cur_streaming->id);
|
DPRINTF(E_LOG, L_PLAYER, "Couldn't jump to source %d in queue\n", cur_streaming->id);
|
||||||
@ -2886,7 +2894,7 @@ playback_start(struct player_command *cmd)
|
|||||||
if (idx_id)
|
if (idx_id)
|
||||||
*idx_id = cur_streaming->id;
|
*idx_id = cur_streaming->id;
|
||||||
|
|
||||||
cur_streaming->stream_start = last_rtptime + AIRTUNES_V2_PACKET_SAMPLES;
|
cur_streaming->stream_start = last_rtptime + AIRTUNES_V2_PACKET_SAMPLES - ((uint64_t)ret * 44100) / 1000;
|
||||||
cur_streaming->output_start = cur_streaming->stream_start;
|
cur_streaming->output_start = cur_streaming->stream_start;
|
||||||
}
|
}
|
||||||
else if (!cur_streaming)
|
else if (!cur_streaming)
|
||||||
@ -3023,7 +3031,7 @@ playback_prev_bh(struct player_command *cmd)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ret = source_open(cur_streaming, 1);
|
ret = source_open(cur_streaming, 1, 0);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
playback_abort();
|
playback_abort();
|
||||||
@ -3103,18 +3111,18 @@ playback_seek_bh(struct player_command *cmd)
|
|||||||
ps->end = 0;
|
ps->end = 0;
|
||||||
|
|
||||||
/* Seek to commanded position */
|
/* Seek to commanded position */
|
||||||
switch (ps->type)
|
switch (ps->data_kind)
|
||||||
{
|
{
|
||||||
case SOURCE_FILE:
|
case DATA_KIND_FILE:
|
||||||
ret = transcode_seek(ps->ctx, ms);
|
ret = transcode_seek(ps->ctx, ms);
|
||||||
break;
|
break;
|
||||||
#ifdef HAVE_SPOTIFY_H
|
#ifdef HAVE_SPOTIFY_H
|
||||||
case SOURCE_SPOTIFY:
|
case DATA_KIND_SPOTIFY:
|
||||||
ret = spotify_playback_seek(ms);
|
ret = spotify_playback_seek(ms);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case SOURCE_PIPE:
|
case DATA_KIND_PIPE:
|
||||||
case SOURCE_HTTP:
|
case DATA_KIND_HTTP:
|
||||||
ret = 1;
|
ret = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -3162,13 +3170,13 @@ playback_pause_bh(struct player_command *cmd)
|
|||||||
pos -= ps->stream_start;
|
pos -= ps->stream_start;
|
||||||
ms = (int)((pos * 1000) / 44100);
|
ms = (int)((pos * 1000) / 44100);
|
||||||
|
|
||||||
switch (ps->type)
|
switch (ps->data_kind)
|
||||||
{
|
{
|
||||||
case SOURCE_FILE:
|
case DATA_KIND_FILE:
|
||||||
ret = transcode_seek(ps->ctx, ms);
|
ret = transcode_seek(ps->ctx, ms);
|
||||||
break;
|
break;
|
||||||
#ifdef HAVE_SPOTIFY_H
|
#ifdef HAVE_SPOTIFY_H
|
||||||
case SOURCE_SPOTIFY:
|
case DATA_KIND_SPOTIFY:
|
||||||
ret = spotify_playback_seek(ms);
|
ret = spotify_playback_seek(ms);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
@ -3192,6 +3200,9 @@ playback_pause_bh(struct player_command *cmd)
|
|||||||
|
|
||||||
status_update(PLAY_PAUSED);
|
status_update(PLAY_PAUSED);
|
||||||
|
|
||||||
|
if (ps->media_kind & (MEDIA_KIND_MOVIE | MEDIA_KIND_PODCAST | MEDIA_KIND_AUDIOBOOK | MEDIA_KIND_TVSHOW))
|
||||||
|
db_file_save_seek(ps->id, ret);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
src/player.h
10
src/player.h
@ -33,13 +33,6 @@ enum repeat_mode {
|
|||||||
REPEAT_ALL = 2,
|
REPEAT_ALL = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum source_type {
|
|
||||||
SOURCE_FILE = 0,
|
|
||||||
SOURCE_SPOTIFY,
|
|
||||||
SOURCE_PIPE,
|
|
||||||
SOURCE_HTTP,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct spk_flags {
|
struct spk_flags {
|
||||||
unsigned selected:1;
|
unsigned selected:1;
|
||||||
unsigned has_password:1;
|
unsigned has_password:1;
|
||||||
@ -84,7 +77,8 @@ struct player_source
|
|||||||
uint32_t id;
|
uint32_t id;
|
||||||
uint32_t len_ms;
|
uint32_t len_ms;
|
||||||
|
|
||||||
enum source_type type;
|
enum data_kind data_kind;
|
||||||
|
enum media_kind media_kind;
|
||||||
int setup_done;
|
int setup_done;
|
||||||
|
|
||||||
uint64_t stream_start;
|
uint64_t stream_start;
|
||||||
|
@ -507,13 +507,13 @@ transcode_setup(struct transcode_ctx **nctx, struct media_file_info *mfi, off_t
|
|||||||
#if LIBAVFORMAT_VERSION_MAJOR >= 54 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR >= 3)
|
#if LIBAVFORMAT_VERSION_MAJOR >= 54 || (LIBAVFORMAT_VERSION_MAJOR == 53 && LIBAVFORMAT_VERSION_MINOR >= 3)
|
||||||
# ifndef HAVE_FFMPEG
|
# ifndef HAVE_FFMPEG
|
||||||
// Without this, libav is slow to probe some internet streams, which leads to RAOP timeouts
|
// Without this, libav is slow to probe some internet streams, which leads to RAOP timeouts
|
||||||
if (mfi->data_kind == DATA_KIND_URL)
|
if (mfi->data_kind == DATA_KIND_HTTP)
|
||||||
{
|
{
|
||||||
ctx->fmtctx = avformat_alloc_context();
|
ctx->fmtctx = avformat_alloc_context();
|
||||||
ctx->fmtctx->probesize = 64000;
|
ctx->fmtctx->probesize = 64000;
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
if (mfi->data_kind == DATA_KIND_URL)
|
if (mfi->data_kind == DATA_KIND_HTTP)
|
||||||
av_dict_set(&options, "icy", "1", 0);
|
av_dict_set(&options, "icy", "1", 0);
|
||||||
|
|
||||||
ret = avformat_open_input(&ctx->fmtctx, mfi->path, NULL, &options);
|
ret = avformat_open_input(&ctx->fmtctx, mfi->path, NULL, &options);
|
||||||
|
Loading…
Reference in New Issue
Block a user