diff options
author | Luis de Bethencourt <luis@debethencourt.com> | 2011-03-29 17:26:38 +0200 |
---|---|---|
committer | Luis de Bethencourt <luis@debethencourt.com> | 2011-03-29 17:26:38 +0200 |
commit | b5f5cf1de62b0a37172db12505373fbdabc3b6d4 (patch) | |
tree | 703b03714669069c2f3430db33fcb9f7550ed75b | |
parent | a8adf3a0d65ed56c4d3d925b56f3755277bd8ef3 (diff) |
engine: continue playback where file was closed
save position of playback if snappy is closed and the file is longer
than 5 minutes, position is >5% || <95% of the stream and
~/.config/snappy/config file exists.
-rw-r--r-- | src/gst_engine.c | 204 | ||||
-rw-r--r-- | src/gst_engine.h | 7 | ||||
-rw-r--r-- | src/snappy.c | 6 |
3 files changed, 188 insertions, 29 deletions
diff --git a/src/gst_engine.c b/src/gst_engine.c index 815418a..ebc943e 100644 --- a/src/gst_engine.c +++ b/src/gst_engine.c @@ -25,10 +25,148 @@ #include "user_interface.h" #include "gst_engine.h" +#define SAVE_POSITION_MIN_DURATION 300 * 1000 // don't save >5 minute files +#define SAVE_POSITION_THRESHOLD 0.05 // percentage threshold + +/* -------------------- static functions --------------------- */ + +gint64 +uri_is_unfinished_playback (GstEngine * engine, gchar * uri) +{ + guint hash_key; + gint64 position = -1; + const gchar *config_dir; + gchar *path, *key; + GKeyFile *keyfile; + GKeyFileFlags flags; + + keyfile = g_key_file_new (); + flags = G_KEY_FILE_KEEP_COMMENTS; + hash_key = g_str_hash (uri); + asprintf (&key, "%d", hash_key); + + // config file path + config_dir = g_get_user_config_dir (); + asprintf (&path, "%s/snappy/config", config_dir); + + if (g_key_file_load_from_file (keyfile, path, flags, NULL)) + if (g_key_file_has_group (keyfile, "unfinished")) + if (g_key_file_has_key (keyfile, "unfinished", key, NULL)) + position = g_key_file_get_int64 (keyfile, "unfinished", key, NULL); + + g_key_file_free (keyfile); + g_free (path); + + return position; +} + +gboolean +add_uri_unfinished_playback (GstEngine * engine, gchar * uri, gint64 position) +{ + guint hash_key; + gint64 duration; + const gchar *config_dir; + gchar *path, *data, *key; + FILE *file; + GKeyFile *keyfile; + GKeyFileFlags flags; + + duration = engine->media_duration; + if (duration < SAVE_POSITION_MIN_DURATION || + (duration - position) < (duration * SAVE_POSITION_THRESHOLD) || + (position < duration * SAVE_POSITION_THRESHOLD)) { + // remove in case position is already stored and close + remove_uri_unfinished_playback (engine, uri); + return FALSE; + } + + keyfile = g_key_file_new (); + flags = G_KEY_FILE_KEEP_COMMENTS; + hash_key = g_str_hash (uri); + asprintf (&key, "%d", hash_key); + + // config file path + config_dir = g_get_user_config_dir (); + asprintf (&path, "%s/snappy/config", config_dir); + + g_key_file_load_from_file (keyfile, path, flags, NULL); + // if file doesn't exist it uses the newly created one + g_key_file_set_int64 (keyfile, "unfinished", key, position); + + // save gkeyfile to a file + data = g_key_file_to_data (keyfile, NULL, NULL); + file = fopen (path, "w"); + fputs (data, file); + fclose (file); + + g_free (data); + g_free (path); + + return TRUE; +} + +gboolean +remove_uri_unfinished_playback (GstEngine * engine, gchar * uri) +{ + guint hash_key; + const gchar *config_dir; + gchar *path, *data, *key; + FILE *file; + GKeyFile *keyfile; + GKeyFileFlags flags; + + keyfile = g_key_file_new (); + flags = G_KEY_FILE_KEEP_COMMENTS; + hash_key = g_str_hash (uri); + asprintf (&key, "%d", hash_key); + + // config file path + config_dir = g_get_user_config_dir (); + asprintf (&path, "%s/snappy/config", config_dir); + + // remove key if gkeyfile exists + if (g_key_file_load_from_file (keyfile, path, flags, NULL)) + g_key_file_remove_key (keyfile, "unfinished", key, NULL); + + // save gkeyfile to a file + data = g_key_file_to_data (keyfile, NULL, NULL); + file = fopen (path, "w"); + fputs (data, file); + fclose (file); + + g_free (data); + g_free (path); + + return TRUE; +} /* -------------------- non-static functions --------------------- */ gboolean +add_uri_unfinished (GstEngine * engine) +{ + gint64 position; + + position = query_position (engine); + add_uri_unfinished_playback (engine, engine->uri, position); + + return TRUE; +} + +gboolean +at_the_eos (GstEngine * engine) +{ + gboolean ret = TRUE; + gint64 position; + + position = query_position (engine); + if (position < engine->media_duration) + ret = FALSE; + + return ret; +} + +gboolean bus_call (GstBus * bus, GstMessage * msg, gpointer data) { UserInterface *ui = (UserInterface *) data; @@ -37,6 +175,7 @@ bus_call (GstBus * bus, GstMessage * msg, gpointer data) switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_EOS: g_debug ("End-of-stream\n"); + remove_uri_unfinished_playback (engine, engine->uri); break; case GST_MESSAGE_ERROR: { @@ -75,6 +214,7 @@ bus_call (GstBus * bus, GstMessage * msg, gpointer data) heightval = gst_structure_get_value (s, "height"); if (G_VALUE_HOLDS (widthval, G_TYPE_INT)) { gint width, height; + gint64 position; width = g_value_get_int (widthval); height = g_value_get_int (heightval); @@ -82,6 +222,10 @@ bus_call (GstBus * bus, GstMessage * msg, gpointer data) engine->media_height = height; update_media_duration (ui->engine); load_user_interface (ui); + + position = uri_is_unfinished_playback (engine, engine->uri); + if (position != -1) + seek (engine, position); } } } @@ -100,7 +244,8 @@ bus_call (GstBus * bus, GstMessage * msg, gpointer data) return TRUE; } -gboolean engine_load (GstEngine * engine, GstElement * sink) +gboolean +engine_load (GstEngine * engine, GstElement * sink) { engine->player = gst_element_factory_make ("playbin2", "playbin2"); if (engine->player == NULL) { @@ -115,8 +260,11 @@ gboolean engine_load (GstEngine * engine, GstElement * sink) return TRUE; } -gboolean engine_load_uri (GstEngine * engine, gchar * uri) +gboolean +engine_load_uri (GstEngine * engine, gchar * uri) { + gint64 position; + engine->uri = uri; g_object_set (G_OBJECT (engine->player), "uri", uri, NULL); g_print ("Loading: %s\n", uri); @@ -124,19 +272,18 @@ gboolean engine_load_uri (GstEngine * engine, gchar * uri) return TRUE; } -gboolean frame_stepping (GstEngine * engine, gboolean foward) +gboolean +frame_stepping (GstEngine * engine, gboolean foward) { gboolean ok; gint64 pos; gdouble rate; GstFormat fmt; - if (engine->prev_done) - { + if (engine->prev_done) { engine->prev_done = FALSE; - if (foward != engine->direction_foward) - { + if (foward != engine->direction_foward) { engine->direction_foward = foward; fmt = GST_FORMAT_TIME; @@ -144,20 +291,18 @@ gboolean frame_stepping (GstEngine * engine, gboolean foward) gst_element_get_state (engine->player, NULL, NULL, GST_SECOND); if (foward) - rate = 1.0; + rate = 1.0; else - rate = -1.0; + rate = -1.0; if (rate >= 0.0) { - ok = gst_element_seek (engine->player, rate, fmt, - GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, - GST_SEEK_TYPE_SET, pos, - GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE); + ok = gst_element_seek (engine->player, rate, fmt, + GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, + GST_SEEK_TYPE_SET, pos, GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE); } else { - ok = gst_element_seek (engine->player, rate, fmt, + ok = gst_element_seek (engine->player, rate, fmt, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, - GST_SEEK_TYPE_SET, G_GINT64_CONSTANT (0), - GST_SEEK_TYPE_SET, pos); + GST_SEEK_TYPE_SET, G_GINT64_CONSTANT (0), GST_SEEK_TYPE_SET, pos); } gst_element_get_state (engine->player, NULL, NULL, GST_SECOND); } @@ -170,7 +315,17 @@ gboolean frame_stepping (GstEngine * engine, gboolean foward) return FALSE; } -gint64 query_position (GstEngine *engine) +GstState +get_state (GstEngine * engine) +{ + GstState state; + gst_element_get_state (engine->player, &state, NULL, GST_SECOND); + + return state; +} + +gint64 +query_position (GstEngine * engine) { gint64 position; GstFormat fmt = GST_FORMAT_TIME; @@ -179,7 +334,8 @@ gint64 query_position (GstEngine *engine) return position; } -gboolean seek (GstEngine * engine, gint64 position) +gboolean +seek (GstEngine * engine, gint64 position) { GstFormat fmt = GST_FORMAT_TIME; @@ -188,23 +344,21 @@ gboolean seek (GstEngine * engine, gint64 position) return TRUE; } -gboolean change_state (GstEngine * engine, gchar * state) +gboolean +change_state (GstEngine * engine, gchar * state) { if (state == "Playing") { gst_element_set_state (engine->player, GST_STATE_PLAYING); engine->playing = TRUE; - } - else if (state == "Paused") { + } else if (state == "Paused") { gst_element_set_state (engine->player, GST_STATE_PAUSED); engine->playing = FALSE; engine->media_duration = -1; - } - else if (state == "Ready") { + } else if (state == "Ready") { gst_element_set_state (engine->player, GST_STATE_READY); engine->playing = FALSE; engine->media_duration = -1; - } - else if (state == "Null") { + } else if (state == "Null") { gst_element_set_state (engine->player, GST_STATE_NULL); engine->playing = FALSE; engine->media_duration = -1; diff --git a/src/gst_engine.h b/src/gst_engine.h index 4a407f5..22d2791 100644 --- a/src/gst_engine.h +++ b/src/gst_engine.h @@ -23,9 +23,7 @@ #ifndef __GST_ENGINE_H__ #define __GST_ENGINE_H__ -G_BEGIN_DECLS - -typedef struct _GstEngine GstEngine; +G_BEGIN_DECLS typedef struct _GstEngine GstEngine; struct _GstEngine { @@ -44,10 +42,13 @@ struct _GstEngine }; // Declaration of non-static functions +gboolean add_uri_unfinished (GstEngine * engine); +gboolean at_the_eos (GstEngine * engine); gboolean bus_call (GstBus * bus, GstMessage * msg, gpointer data); gboolean engine_load (GstEngine * engine, GstElement * sink); gboolean engine_load_uri (GstEngine * engine, gchar * uri); gboolean frame_stepping (GstEngine * engine, gboolean foward); +GstState get_state (GstEngine * engine); gint64 query_position (GstEngine * engine); gboolean seek (GstEngine * engine, gint64 position); gboolean change_state (GstEngine * engine, gchar * state); diff --git a/src/snappy.c b/src/snappy.c index cae2980..a729211 100644 --- a/src/snappy.c +++ b/src/snappy.c @@ -113,7 +113,6 @@ main (int argc, char *argv[]) fileuri = clean_uri (file_list[0]); asprintf (&uri, "file://%s", fileuri); - g_print ("Loading: %s\n", uri); engine_load_uri (engine, uri); interface_load_uri (ui, uri); @@ -122,6 +121,11 @@ main (int argc, char *argv[]) clutter_main (); + g_print ("closing snappy\n"); + + // save position if file isn't finished playing + add_uri_unfinished (engine); + change_state (engine, "Null"); gst_object_unref (engine->player); |