Johannes Weißl
2011-04-05 03:17:29 UTC
If resume=true, cmus will start playing right from the position it had
when exiting. Information is saved to $CMUS_HOME/resume.
---
Doc/cmus.txt | 3 +
TODO | 1 -
command_mode.c | 2 +-
lib.c | 8 ++--
lib.h | 3 +
misc.c | 26 +++++++++++
misc.h | 1 +
options.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
options.h | 6 +++
player.c | 11 ++++-
player.h | 6 ++-
server.c | 3 +-
ui_curses.c | 5 ++
13 files changed, 193 insertions(+), 11 deletions(-)
diff --git a/Doc/cmus.txt b/Doc/cmus.txt
index 83a0b78..38409b3 100644
--- a/Doc/cmus.txt
+++ b/Doc/cmus.txt
@@ -886,6 +886,9 @@ replaygain_limit (true)
replaygain_preamp (6.0)
Replay gain preamplification in decibels.
+resume (false)
+ Resume playback on startup.
+
show_hidden (false)
Display hidden files in browser.
diff --git a/TODO b/TODO
index be4186a..572d5d3 100644
--- a/TODO
+++ b/TODO
@@ -3,6 +3,5 @@
- cuesheet (.flac + .cue) support
- CDDA support
- Last.FM support
-- option to resume playback on startup
- different random modes (albums/artist/etc.)
- playlist tracks grouping (a la foobar2000)
diff --git a/command_mode.c b/command_mode.c
index 62a1a0a..f6d93fb 100644
--- a/command_mode.c
+++ b/command_mode.c
@@ -575,7 +575,7 @@ inside:
}
if (!*arg) {
- player_seek(seek, relative);
+ player_seek(seek, relative, 1);
return;
}
err:
diff --git a/lib.c b/lib.c
index 1367731..28ae6d8 100644
--- a/lib.c
+++ b/lib.c
@@ -329,7 +329,7 @@ void lib_init(void)
srand(time(NULL));
}
-static struct track_info *lib_set_track(struct tree_track *track)
+struct track_info *lib_set_track(struct tree_track *track)
{
struct track_info *ti = NULL;
@@ -415,7 +415,7 @@ static void hash_add_to_views(void)
}
}
-static struct tree_track *find_tree_track(struct track_info *ti)
+struct tree_track *lib_find_track(struct track_info *ti)
{
struct simple_track *track;
@@ -430,7 +430,7 @@ static struct tree_track *find_tree_track(struct track_info *ti)
static void restore_cur_track(struct track_info *ti)
{
- struct tree_track *tt = find_tree_track(ti);
+ struct tree_track *tt = lib_find_track(ti);
if (tt)
lib_cur_track = tt;
}
@@ -527,7 +527,7 @@ static void store_sel_track(void)
static void restore_sel_track(void)
{
if (sel_track_ti) {
- struct tree_track *tt = find_tree_track(sel_track_ti);
+ struct tree_track *tt = lib_find_track(sel_track_ti);
if (tt) {
set_sel_track(tt);
track_info_unref(sel_track_ti);
diff --git a/lib.h b/lib.h
index 1a6d38b..3d6fe16 100644
--- a/lib.h
+++ b/lib.h
@@ -104,6 +104,9 @@ void lib_set_view(int view);
int lib_for_each(int (*cb)(void *data, struct track_info *ti), void *data);
int lib_for_each_filtered(int (*cb)(void *data, struct track_info *ti), void *data);
+struct tree_track *lib_find_track(struct track_info *ti);
+struct track_info *lib_set_track(struct tree_track *track);
+
struct tree_track *tree_get_selected(void);
struct track_info *tree_set_selected(void);
void tree_sort_artists(void);
diff --git a/misc.c b/misc.c
index 6e77fd5..1bf64a6 100644
--- a/misc.c
+++ b/misc.c
@@ -109,6 +109,32 @@ const char *escape(const char *str)
return buf;
}
+const char *unescape(const char *str)
+{
+ static char *buf = NULL;
+ static size_t alloc = 0;
+ size_t need = strlen(str) + 1;
+ int do_escape = 0;
+ int s, d;
+
+ if (need > alloc) {
+ alloc = (need + 16) & ~(16 - 1);
+ buf = xrealloc(buf, alloc);
+ }
+
+ d = 0;
+ for (s = 0; str[s]; s++) {
+ if (!do_escape && str[s] == '\\')
+ do_escape = 1;
+ else {
+ buf[d++] = (do_escape && str[s] == 'n') ? '\n' : str[s];
+ do_escape = 0;
+ }
+ }
+ buf[d] = 0;
+ return buf;
+}
+
static int dir_exists(const char *dirname)
{
DIR *dir;
diff --git a/misc.h b/misc.h
index f12d857..0e0a80b 100644
--- a/misc.h
+++ b/misc.h
@@ -28,5 +28,6 @@ char **get_words(const char *text);
int strptrcmp(const void *a, const void *b);
int misc_init(void);
const char *escape(const char *str);
+const char *unescape(const char *str);
#endif
diff --git a/options.c b/options.c
index 75eca52..80b13bf 100644
--- a/options.c
+++ b/options.c
@@ -23,6 +23,8 @@
#include "output.h"
#include "config/datadir.h"
#include "track_info.h"
+#include "cache.h"
+#include "debug.h"
#include <stdio.h>
#include <errno.h>
@@ -41,6 +43,7 @@ char *status_display_program = NULL;
char *server_password;
int auto_reshuffle = 1;
int confirm_run = 1;
+int resume_cmus = 0;
int show_hidden = 0;
int show_remaining_time = 0;
int set_term_title = 1;
@@ -677,6 +680,21 @@ static void toggle_replaygain_limit(unsigned int id)
player_set_rg_limit(replaygain_limit ^ 1);
}
+static void get_resume(unsigned int id, char *buf)
+{
+ strcpy(buf, bool_names[resume_cmus]);
+}
+
+static void set_resume(unsigned int id, const char *buf)
+{
+ parse_bool(buf, &resume_cmus);
+}
+
+static void toggle_resume(unsigned int id)
+{
+ resume_cmus ^= 1;
+}
+
static void get_show_hidden(unsigned int id, char *buf)
{
strcpy(buf, bool_names[show_hidden]);
@@ -890,6 +908,7 @@ static const struct {
DT(replaygain)
DT(replaygain_limit)
DN(replaygain_preamp)
+ DT(resume)
DT(show_hidden)
DT(show_remaining_time)
DT(set_term_title)
@@ -1107,3 +1126,113 @@ void options_exit(void)
fclose(f);
}
+
+struct resume {
+ enum player_status status;
+ char *filename;
+ long int position;
+ char *lib_filename;
+ int view;
+};
+
+static int handle_resume_line(void *data, const char *line)
+{
+ struct resume *resume = data;
+ char *cmd, *arg;
+
+ if (!parse_command(line, &cmd, &arg))
+ return 0;
+ if (!arg)
+ goto out;
+
+ if (strcmp(cmd, "status") == 0) {
+ parse_enum(arg, 0, NR_PLAYER_STATUS, player_status_names, (int *) &resume->status);
+ } else if (strcmp(cmd, "file") == 0) {
+ resume->filename = xstrdup(unescape(arg));
+ } else if (strcmp(cmd, "position") == 0) {
+ str_to_int(arg, &resume->position);
+ } else if (strcmp(cmd, "lib_file") == 0) {
+ resume->lib_filename = xstrdup(unescape(arg));
+ } else if (strcmp(cmd, "view") == 0) {
+ parse_enum(arg, 0, NR_VIEWS, view_names, &resume->view);
+ }
+
+ free(arg);
+out:
+ free(cmd);
+ return 0;
+}
+
+void resume_load(void)
+{
+ char filename[512];
+ struct track_info *ti, *old;
+ struct resume resume = { .status = PLAYER_STATUS_STOPPED, .view = -1 };
+
+ snprintf(filename, sizeof(filename), "%s/resume", cmus_config_dir);
+ if (file_for_each_line(filename, handle_resume_line, &resume) == -1) {
+ if (errno != ENOENT)
+ error_msg("loading %s: %s", filename, strerror(errno));
+ return;
+ }
+ if (resume.view >= 0 && resume.view != cur_view)
+ set_view(resume.view);
+ if (resume.lib_filename) {
+ cache_lock();
+ ti = old = cache_get_ti(resume.lib_filename);
+ cache_unlock();
+ if (ti) {
+ editable_lock();
+ lib_add_track(ti);
+ track_info_unref(ti);
+ ti = lib_set_track(lib_find_track(ti));
+ BUG_ON(ti != old);
+ track_info_unref(ti);
+ tree_sel_current();
+ sorted_sel_current();
+ editable_unlock();
+ }
+ free(resume.lib_filename);
+ }
+ if (resume.filename) {
+ cache_lock();
+ ti = cache_get_ti(resume.filename);
+ cache_unlock();
+ if (ti) {
+ player_set_file(ti);
+ if (resume.status != PLAYER_STATUS_STOPPED)
+ player_seek(resume.position, 0, resume.status == PLAYER_STATUS_PLAYING);
+ }
+ free(resume.filename);
+ }
+}
+
+void resume_exit(void)
+{
+ char filename[512];
+ struct track_info *ti;
+ FILE *f;
+
+ snprintf(filename, sizeof(filename), "%s/resume", cmus_config_dir);
+ f = fopen(filename, "w");
+ if (!f) {
+ warn_errno("creating %s", filename);
+ return;
+ }
+
+ player_info_lock();
+ fprintf(f, "status %s\n", player_status_names[player_info.status]);
+ ti = player_info.ti;
+ if (ti) {
+ fprintf(f, "file %s\n", escape(ti->filename));
+ fprintf(f, "position %d\n", player_info.pos);
+ }
+ player_info_unlock();
+ if (lib_cur_track) {
+ ti = tree_track_info(lib_cur_track);
+ fprintf(f, "lib_file %s\n", escape(ti->filename));
+ }
+ fprintf(f, "view %s\n", view_names[cur_view]);
+
+ fclose(f);
+}
diff --git a/options.h b/options.h
index 53e3dbb..49125d7 100644
--- a/options.h
+++ b/options.h
@@ -86,6 +86,7 @@ extern char *status_display_program;
extern char *server_password;
extern int auto_reshuffle;
extern int confirm_run;
+extern int resume_cmus;
extern int show_hidden;
extern int show_remaining_time;
extern int set_term_title;
@@ -131,6 +132,11 @@ int source_file(const char *filename);
/* save options */
void options_exit(void);
+/* load resume file */
+void resume_load(void);
+/* save resume file */
+void resume_exit(void);
+
void option_add(const char *name, unsigned int id, opt_get_cb get,
opt_set_cb set, opt_toggle_cb toggle);
struct cmus_opt *option_find(const char *name);
diff --git a/player.c b/player.c
index 573a49a..2d73f91 100644
--- a/player.c
+++ b/player.c
@@ -36,6 +36,8 @@
#include <stdarg.h>
#include <math.h>
+const char * const player_status_names[] = { "stopped", "playing", "paused", NULL };
+
enum producer_status {
PS_UNLOADED,
PS_STOPPED,
@@ -1172,10 +1174,12 @@ out:
player_unlock();
}
-void player_seek(double offset, int relative)
+void player_seek(double offset, int relative, int start_playing)
{
+ int stopped = 0;
player_lock();
if (consumer_status == CS_STOPPED) {
+ stopped = 1;
__producer_play();
if (producer_status == PS_PLAYING) {
__consumer_play();
@@ -1238,6 +1242,11 @@ void player_seek(double offset, int relative)
consumer_pos = new_pos * buffer_second_size();
scale_pos = consumer_pos;
__consumer_position_update();
+ if (stopped && !start_playing) {
+ __producer_pause();
+ __consumer_pause();
+ __player_status_changed();
+ }
} else {
d_print("error: ip_seek returned %d\n", rc);
}
diff --git a/player.h b/player.h
index ca57a5e..ef12e7b 100644
--- a/player.h
+++ b/player.h
@@ -35,10 +35,12 @@ enum {
PLAYER_ERROR_NOT_SUPPORTED
};
+extern const char * const player_status_names[];
enum player_status {
PLAYER_STATUS_STOPPED,
PLAYER_STATUS_PLAYING,
- PLAYER_STATUS_PAUSED
+ PLAYER_STATUS_PAUSED,
+ NR_PLAYER_STATUS
};
enum replaygain {
@@ -101,7 +103,7 @@ void player_play_file(struct track_info *ti);
void player_play(void);
void player_stop(void);
void player_pause(void);
-void player_seek(double offset, int relative);
+void player_seek(double offset, int relative, int start_playing);
void player_set_op(const char *name);
void player_set_buffer_chunks(unsigned int nr_chunks);
int player_get_buffer_chunks(void);
diff --git a/server.c b/server.c
index 797086b..d65fb82 100644
--- a/server.c
+++ b/server.c
@@ -61,7 +61,6 @@ static union {
static int cmd_status(struct client *client)
{
- const char *status[] = { "stopped", "playing", "paused" };
const char *export_options[] = {
"aaa_mode",
"continue",
@@ -84,7 +83,7 @@ static int cmd_status(struct client *client)
int i, ret;
player_info_lock();
- gbuf_addf(&buf, "status %s\n", status[player_info.status]);
+ gbuf_addf(&buf, "status %s\n", player_status_names[player_info.status]);
ti = player_info.ti;
if (ti) {
gbuf_addf(&buf, "file %s\n", escape(ti->filename));
diff --git a/ui_curses.c b/ui_curses.c
index 50a0df5..f0efd9f 100644
--- a/ui_curses.c
+++ b/ui_curses.c
@@ -2205,6 +2205,9 @@ static void init_all(void)
if (!soft_vol)
mixer_open();
+ if (resume_cmus)
+ resume_load();
+
lib_autosave_filename = xstrjoin(cmus_config_dir, "/lib.pl");
pl_autosave_filename = xstrjoin(cmus_config_dir, "/playlist.pl");
pl_filename = xstrdup(pl_autosave_filename);
@@ -2231,6 +2234,8 @@ static void exit_all(void)
{
endwin();
+ if (resume_cmus)
+ resume_exit();
options_exit();
server_exit();
when exiting. Information is saved to $CMUS_HOME/resume.
---
Doc/cmus.txt | 3 +
TODO | 1 -
command_mode.c | 2 +-
lib.c | 8 ++--
lib.h | 3 +
misc.c | 26 +++++++++++
misc.h | 1 +
options.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
options.h | 6 +++
player.c | 11 ++++-
player.h | 6 ++-
server.c | 3 +-
ui_curses.c | 5 ++
13 files changed, 193 insertions(+), 11 deletions(-)
diff --git a/Doc/cmus.txt b/Doc/cmus.txt
index 83a0b78..38409b3 100644
--- a/Doc/cmus.txt
+++ b/Doc/cmus.txt
@@ -886,6 +886,9 @@ replaygain_limit (true)
replaygain_preamp (6.0)
Replay gain preamplification in decibels.
+resume (false)
+ Resume playback on startup.
+
show_hidden (false)
Display hidden files in browser.
diff --git a/TODO b/TODO
index be4186a..572d5d3 100644
--- a/TODO
+++ b/TODO
@@ -3,6 +3,5 @@
- cuesheet (.flac + .cue) support
- CDDA support
- Last.FM support
-- option to resume playback on startup
- different random modes (albums/artist/etc.)
- playlist tracks grouping (a la foobar2000)
diff --git a/command_mode.c b/command_mode.c
index 62a1a0a..f6d93fb 100644
--- a/command_mode.c
+++ b/command_mode.c
@@ -575,7 +575,7 @@ inside:
}
if (!*arg) {
- player_seek(seek, relative);
+ player_seek(seek, relative, 1);
return;
}
err:
diff --git a/lib.c b/lib.c
index 1367731..28ae6d8 100644
--- a/lib.c
+++ b/lib.c
@@ -329,7 +329,7 @@ void lib_init(void)
srand(time(NULL));
}
-static struct track_info *lib_set_track(struct tree_track *track)
+struct track_info *lib_set_track(struct tree_track *track)
{
struct track_info *ti = NULL;
@@ -415,7 +415,7 @@ static void hash_add_to_views(void)
}
}
-static struct tree_track *find_tree_track(struct track_info *ti)
+struct tree_track *lib_find_track(struct track_info *ti)
{
struct simple_track *track;
@@ -430,7 +430,7 @@ static struct tree_track *find_tree_track(struct track_info *ti)
static void restore_cur_track(struct track_info *ti)
{
- struct tree_track *tt = find_tree_track(ti);
+ struct tree_track *tt = lib_find_track(ti);
if (tt)
lib_cur_track = tt;
}
@@ -527,7 +527,7 @@ static void store_sel_track(void)
static void restore_sel_track(void)
{
if (sel_track_ti) {
- struct tree_track *tt = find_tree_track(sel_track_ti);
+ struct tree_track *tt = lib_find_track(sel_track_ti);
if (tt) {
set_sel_track(tt);
track_info_unref(sel_track_ti);
diff --git a/lib.h b/lib.h
index 1a6d38b..3d6fe16 100644
--- a/lib.h
+++ b/lib.h
@@ -104,6 +104,9 @@ void lib_set_view(int view);
int lib_for_each(int (*cb)(void *data, struct track_info *ti), void *data);
int lib_for_each_filtered(int (*cb)(void *data, struct track_info *ti), void *data);
+struct tree_track *lib_find_track(struct track_info *ti);
+struct track_info *lib_set_track(struct tree_track *track);
+
struct tree_track *tree_get_selected(void);
struct track_info *tree_set_selected(void);
void tree_sort_artists(void);
diff --git a/misc.c b/misc.c
index 6e77fd5..1bf64a6 100644
--- a/misc.c
+++ b/misc.c
@@ -109,6 +109,32 @@ const char *escape(const char *str)
return buf;
}
+const char *unescape(const char *str)
+{
+ static char *buf = NULL;
+ static size_t alloc = 0;
+ size_t need = strlen(str) + 1;
+ int do_escape = 0;
+ int s, d;
+
+ if (need > alloc) {
+ alloc = (need + 16) & ~(16 - 1);
+ buf = xrealloc(buf, alloc);
+ }
+
+ d = 0;
+ for (s = 0; str[s]; s++) {
+ if (!do_escape && str[s] == '\\')
+ do_escape = 1;
+ else {
+ buf[d++] = (do_escape && str[s] == 'n') ? '\n' : str[s];
+ do_escape = 0;
+ }
+ }
+ buf[d] = 0;
+ return buf;
+}
+
static int dir_exists(const char *dirname)
{
DIR *dir;
diff --git a/misc.h b/misc.h
index f12d857..0e0a80b 100644
--- a/misc.h
+++ b/misc.h
@@ -28,5 +28,6 @@ char **get_words(const char *text);
int strptrcmp(const void *a, const void *b);
int misc_init(void);
const char *escape(const char *str);
+const char *unescape(const char *str);
#endif
diff --git a/options.c b/options.c
index 75eca52..80b13bf 100644
--- a/options.c
+++ b/options.c
@@ -23,6 +23,8 @@
#include "output.h"
#include "config/datadir.h"
#include "track_info.h"
+#include "cache.h"
+#include "debug.h"
#include <stdio.h>
#include <errno.h>
@@ -41,6 +43,7 @@ char *status_display_program = NULL;
char *server_password;
int auto_reshuffle = 1;
int confirm_run = 1;
+int resume_cmus = 0;
int show_hidden = 0;
int show_remaining_time = 0;
int set_term_title = 1;
@@ -677,6 +680,21 @@ static void toggle_replaygain_limit(unsigned int id)
player_set_rg_limit(replaygain_limit ^ 1);
}
+static void get_resume(unsigned int id, char *buf)
+{
+ strcpy(buf, bool_names[resume_cmus]);
+}
+
+static void set_resume(unsigned int id, const char *buf)
+{
+ parse_bool(buf, &resume_cmus);
+}
+
+static void toggle_resume(unsigned int id)
+{
+ resume_cmus ^= 1;
+}
+
static void get_show_hidden(unsigned int id, char *buf)
{
strcpy(buf, bool_names[show_hidden]);
@@ -890,6 +908,7 @@ static const struct {
DT(replaygain)
DT(replaygain_limit)
DN(replaygain_preamp)
+ DT(resume)
DT(show_hidden)
DT(show_remaining_time)
DT(set_term_title)
@@ -1107,3 +1126,113 @@ void options_exit(void)
fclose(f);
}
+
+struct resume {
+ enum player_status status;
+ char *filename;
+ long int position;
+ char *lib_filename;
+ int view;
+};
+
+static int handle_resume_line(void *data, const char *line)
+{
+ struct resume *resume = data;
+ char *cmd, *arg;
+
+ if (!parse_command(line, &cmd, &arg))
+ return 0;
+ if (!arg)
+ goto out;
+
+ if (strcmp(cmd, "status") == 0) {
+ parse_enum(arg, 0, NR_PLAYER_STATUS, player_status_names, (int *) &resume->status);
+ } else if (strcmp(cmd, "file") == 0) {
+ resume->filename = xstrdup(unescape(arg));
+ } else if (strcmp(cmd, "position") == 0) {
+ str_to_int(arg, &resume->position);
+ } else if (strcmp(cmd, "lib_file") == 0) {
+ resume->lib_filename = xstrdup(unescape(arg));
+ } else if (strcmp(cmd, "view") == 0) {
+ parse_enum(arg, 0, NR_VIEWS, view_names, &resume->view);
+ }
+
+ free(arg);
+out:
+ free(cmd);
+ return 0;
+}
+
+void resume_load(void)
+{
+ char filename[512];
+ struct track_info *ti, *old;
+ struct resume resume = { .status = PLAYER_STATUS_STOPPED, .view = -1 };
+
+ snprintf(filename, sizeof(filename), "%s/resume", cmus_config_dir);
+ if (file_for_each_line(filename, handle_resume_line, &resume) == -1) {
+ if (errno != ENOENT)
+ error_msg("loading %s: %s", filename, strerror(errno));
+ return;
+ }
+ if (resume.view >= 0 && resume.view != cur_view)
+ set_view(resume.view);
+ if (resume.lib_filename) {
+ cache_lock();
+ ti = old = cache_get_ti(resume.lib_filename);
+ cache_unlock();
+ if (ti) {
+ editable_lock();
+ lib_add_track(ti);
+ track_info_unref(ti);
+ ti = lib_set_track(lib_find_track(ti));
+ BUG_ON(ti != old);
+ track_info_unref(ti);
+ tree_sel_current();
+ sorted_sel_current();
+ editable_unlock();
+ }
+ free(resume.lib_filename);
+ }
+ if (resume.filename) {
+ cache_lock();
+ ti = cache_get_ti(resume.filename);
+ cache_unlock();
+ if (ti) {
+ player_set_file(ti);
+ if (resume.status != PLAYER_STATUS_STOPPED)
+ player_seek(resume.position, 0, resume.status == PLAYER_STATUS_PLAYING);
+ }
+ free(resume.filename);
+ }
+}
+
+void resume_exit(void)
+{
+ char filename[512];
+ struct track_info *ti;
+ FILE *f;
+
+ snprintf(filename, sizeof(filename), "%s/resume", cmus_config_dir);
+ f = fopen(filename, "w");
+ if (!f) {
+ warn_errno("creating %s", filename);
+ return;
+ }
+
+ player_info_lock();
+ fprintf(f, "status %s\n", player_status_names[player_info.status]);
+ ti = player_info.ti;
+ if (ti) {
+ fprintf(f, "file %s\n", escape(ti->filename));
+ fprintf(f, "position %d\n", player_info.pos);
+ }
+ player_info_unlock();
+ if (lib_cur_track) {
+ ti = tree_track_info(lib_cur_track);
+ fprintf(f, "lib_file %s\n", escape(ti->filename));
+ }
+ fprintf(f, "view %s\n", view_names[cur_view]);
+
+ fclose(f);
+}
diff --git a/options.h b/options.h
index 53e3dbb..49125d7 100644
--- a/options.h
+++ b/options.h
@@ -86,6 +86,7 @@ extern char *status_display_program;
extern char *server_password;
extern int auto_reshuffle;
extern int confirm_run;
+extern int resume_cmus;
extern int show_hidden;
extern int show_remaining_time;
extern int set_term_title;
@@ -131,6 +132,11 @@ int source_file(const char *filename);
/* save options */
void options_exit(void);
+/* load resume file */
+void resume_load(void);
+/* save resume file */
+void resume_exit(void);
+
void option_add(const char *name, unsigned int id, opt_get_cb get,
opt_set_cb set, opt_toggle_cb toggle);
struct cmus_opt *option_find(const char *name);
diff --git a/player.c b/player.c
index 573a49a..2d73f91 100644
--- a/player.c
+++ b/player.c
@@ -36,6 +36,8 @@
#include <stdarg.h>
#include <math.h>
+const char * const player_status_names[] = { "stopped", "playing", "paused", NULL };
+
enum producer_status {
PS_UNLOADED,
PS_STOPPED,
@@ -1172,10 +1174,12 @@ out:
player_unlock();
}
-void player_seek(double offset, int relative)
+void player_seek(double offset, int relative, int start_playing)
{
+ int stopped = 0;
player_lock();
if (consumer_status == CS_STOPPED) {
+ stopped = 1;
__producer_play();
if (producer_status == PS_PLAYING) {
__consumer_play();
@@ -1238,6 +1242,11 @@ void player_seek(double offset, int relative)
consumer_pos = new_pos * buffer_second_size();
scale_pos = consumer_pos;
__consumer_position_update();
+ if (stopped && !start_playing) {
+ __producer_pause();
+ __consumer_pause();
+ __player_status_changed();
+ }
} else {
d_print("error: ip_seek returned %d\n", rc);
}
diff --git a/player.h b/player.h
index ca57a5e..ef12e7b 100644
--- a/player.h
+++ b/player.h
@@ -35,10 +35,12 @@ enum {
PLAYER_ERROR_NOT_SUPPORTED
};
+extern const char * const player_status_names[];
enum player_status {
PLAYER_STATUS_STOPPED,
PLAYER_STATUS_PLAYING,
- PLAYER_STATUS_PAUSED
+ PLAYER_STATUS_PAUSED,
+ NR_PLAYER_STATUS
};
enum replaygain {
@@ -101,7 +103,7 @@ void player_play_file(struct track_info *ti);
void player_play(void);
void player_stop(void);
void player_pause(void);
-void player_seek(double offset, int relative);
+void player_seek(double offset, int relative, int start_playing);
void player_set_op(const char *name);
void player_set_buffer_chunks(unsigned int nr_chunks);
int player_get_buffer_chunks(void);
diff --git a/server.c b/server.c
index 797086b..d65fb82 100644
--- a/server.c
+++ b/server.c
@@ -61,7 +61,6 @@ static union {
static int cmd_status(struct client *client)
{
- const char *status[] = { "stopped", "playing", "paused" };
const char *export_options[] = {
"aaa_mode",
"continue",
@@ -84,7 +83,7 @@ static int cmd_status(struct client *client)
int i, ret;
player_info_lock();
- gbuf_addf(&buf, "status %s\n", status[player_info.status]);
+ gbuf_addf(&buf, "status %s\n", player_status_names[player_info.status]);
ti = player_info.ti;
if (ti) {
gbuf_addf(&buf, "file %s\n", escape(ti->filename));
diff --git a/ui_curses.c b/ui_curses.c
index 50a0df5..f0efd9f 100644
--- a/ui_curses.c
+++ b/ui_curses.c
@@ -2205,6 +2205,9 @@ static void init_all(void)
if (!soft_vol)
mixer_open();
+ if (resume_cmus)
+ resume_load();
+
lib_autosave_filename = xstrjoin(cmus_config_dir, "/lib.pl");
pl_autosave_filename = xstrjoin(cmus_config_dir, "/playlist.pl");
pl_filename = xstrdup(pl_autosave_filename);
@@ -2231,6 +2234,8 @@ static void exit_all(void)
{
endwin();
+ if (resume_cmus)
+ resume_exit();
options_exit();
server_exit();
--
1.7.4.1
1.7.4.1