Browse Source

image-source: Add "manual (hotkey)" mode to image slideshow

Allows traversing/stopping the slideshow via hotkeys.

Split from jp9000/obs-studio#976
cg2121 8 years ago
parent
commit
7549b3a092
2 changed files with 187 additions and 1 deletions
  1. 8 0
      plugins/image-source/data/locale/en-US.ini
  2. 179 1
      plugins/image-source/obs-slideshow.c

+ 8 - 0
plugins/image-source/data/locale/en-US.ini

@@ -19,6 +19,14 @@ SlideShow.PlaybackBehavior="Visibility Behavior"
 SlideShow.PlaybackBehavior.StopRestart="Stop when not visible, restart when visible"
 SlideShow.PlaybackBehavior.PauseUnpause="Pause when not visible, unpause when visible"
 SlideShow.PlaybackBehavior.AlwaysPlay="Always play even when not visible"
+SlideShow.SlideMode="Slide Mode"
+SlideShow.SlideMode.Auto="Automatic"
+SlideShow.SlideMode.Manual="Manual (Use hotkeys to control slideshow)"
+SlideShow.PlayPause="Play/Pause"
+SlideShow.Restart="Restart"
+SlideShow.Stop="Stop"
+SlideShow.NextSlide="Next Slide"
+SlideShow.PreviousSlide="Previous Slide"
 SlideShow.HideWhenDone="Hide when slideshow is done"
 
 ColorSource="Color Source"

+ 179 - 1
plugins/image-source/obs-slideshow.c

@@ -22,6 +22,9 @@
 #define S_BEHAVIOR_STOP_RESTART        "stop_restart"
 #define S_BEHAVIOR_PAUSE_UNPAUSE       "pause_unpause"
 #define S_BEHAVIOR_ALWAYS_PLAY         "always_play"
+#define S_MODE                         "slide_mode"
+#define S_MODE_AUTO                    "mode_auto"
+#define S_MODE_MANUAL                  "mode_manual"
 
 #define TR_CUT                         "cut"
 #define TR_FADE                        "fade"
@@ -42,6 +45,9 @@
 #define T_BEHAVIOR_STOP_RESTART        T_("PlaybackBehavior.StopRestart")
 #define T_BEHAVIOR_PAUSE_UNPAUSE       T_("PlaybackBehavior.PauseUnpause")
 #define T_BEHAVIOR_ALWAYS_PLAY         T_("PlaybackBehavior.AlwaysPlay")
+#define T_MODE                         T_("SlideMode")
+#define T_MODE_AUTO                    T_("SlideMode.Auto")
+#define T_MODE_MANUAL                  T_("SlideMode.Manual")
 
 #define T_TR_(text) obs_module_text("SlideShow.Transition." text)
 #define T_TR_CUT                       T_TR_("Cut")
@@ -70,6 +76,7 @@ struct slideshow {
 	bool restart_on_activate;
 	bool pause_on_deactivate;
 	bool restart;
+	bool manual;
 	bool hide;
 	bool use_cut;
 	bool paused;
@@ -89,6 +96,12 @@ struct slideshow {
 	DARRAY(struct image_file_data) files;
 
 	enum behavior behavior;
+
+	obs_hotkey_id play_pause_hotkey;
+	obs_hotkey_id restart_hotkey;
+	obs_hotkey_id stop_hotkey;
+	obs_hotkey_id next_hotkey;
+	obs_hotkey_id prev_hotkey;
 };
 
 static obs_source_t *get_transition(struct slideshow *ss)
@@ -241,6 +254,7 @@ static void ss_update(void *data, obs_data_t *settings)
 	uint32_t cy = 0;
 	size_t count;
 	const char *behavior;
+	const char *mode;
 
 	/* ------------------------------------- */
 	/* get settings data */
@@ -256,6 +270,10 @@ static void ss_update(void *data, obs_data_t *settings)
 	else /* S_BEHAVIOR_STOP_RESTART */
 		ss->behavior = BEHAVIOR_STOP_RESTART;
 
+	mode = obs_data_get_string(settings, S_MODE);
+
+	ss->manual = (astrcmpi(mode, S_MODE_MANUAL) == 0);
+
 	tr_name = obs_data_get_string(settings, S_TRANSITION);
 	if (astrcmpi(tr_name, TR_CUT) == 0)
 		tr_name = "cut_transition";
@@ -411,6 +429,134 @@ static void ss_update(void *data, obs_data_t *settings)
 	obs_data_array_release(array);
 }
 
+static void ss_play_pause(void *data)
+{
+	struct slideshow *ss = data;
+
+	ss->paused = !ss->paused;
+	ss->manual = ss->paused;
+}
+
+static void ss_restart(void *data)
+{
+	struct slideshow *ss = data;
+
+	ss->elapsed = 0.0f;
+	ss->cur_item = 0;
+
+	obs_transition_set(ss->transition,
+			ss->files.array[ss->cur_item].source);
+
+	ss->stop = false;
+	ss->paused = false;
+}
+
+static void ss_stop(void *data)
+{
+	struct slideshow *ss = data;
+
+	ss->elapsed = 0.0f;
+	ss->cur_item = 0;
+
+	do_transition(ss, true);
+	ss->stop = true;
+	ss->paused = false;
+}
+
+static void ss_next_slide(void *data)
+{
+	struct slideshow *ss = data;
+
+	if (!ss->files.num)
+		return;
+
+	if (++ss->cur_item >= ss->files.num)
+		ss->cur_item = 0;
+
+	do_transition(ss, false);
+}
+
+static void ss_previous_slide(void *data)
+{
+	struct slideshow *ss = data;
+
+	if (!ss->files.num)
+		return;
+
+	if (ss->cur_item == 0)
+		ss->cur_item = ss->files.num - 1;
+	else
+		--ss->cur_item;
+
+	do_transition(ss, false);
+}
+
+static void play_pause_hotkey(void *data, obs_hotkey_id id,
+		obs_hotkey_t *hotkey, bool pressed)
+{
+	UNUSED_PARAMETER(id);
+	UNUSED_PARAMETER(hotkey);
+
+	struct slideshow *ss = data;
+
+	if (pressed && obs_source_active(ss->source))
+		ss_play_pause(ss);
+}
+
+static void restart_hotkey(void *data, obs_hotkey_id id,
+		obs_hotkey_t *hotkey, bool pressed)
+{
+	UNUSED_PARAMETER(id);
+	UNUSED_PARAMETER(hotkey);
+
+	struct slideshow *ss = data;
+
+	if (pressed && obs_source_active(ss->source))
+		ss_restart(ss);
+}
+
+static void stop_hotkey(void *data, obs_hotkey_id id,
+		obs_hotkey_t *hotkey, bool pressed)
+{
+	UNUSED_PARAMETER(id);
+	UNUSED_PARAMETER(hotkey);
+
+	struct slideshow *ss = data;
+
+	if (pressed && obs_source_active(ss->source))
+		ss_stop(ss);
+}
+
+static void next_slide_hotkey(void *data, obs_hotkey_id id,
+		obs_hotkey_t *hotkey, bool pressed)
+{
+	UNUSED_PARAMETER(id);
+	UNUSED_PARAMETER(hotkey);
+
+	struct slideshow *ss = data;
+
+	if (!ss->manual)
+		return;
+
+	if (pressed && obs_source_active(ss->source))
+		ss_next_slide(ss);
+}
+
+static void previous_slide_hotkey(void *data, obs_hotkey_id id,
+		obs_hotkey_t *hotkey, bool pressed)
+{
+	UNUSED_PARAMETER(id);
+	UNUSED_PARAMETER(hotkey);
+
+	struct slideshow *ss = data;
+
+	if (!ss->manual)
+		return;
+
+	if (pressed && obs_source_active(ss->source))
+		ss_previous_slide(ss);
+}
+
 static void ss_destroy(void *data)
 {
 	struct slideshow *ss = data;
@@ -427,9 +573,35 @@ static void *ss_create(obs_data_t *settings, obs_source_t *source)
 
 	ss->source = source;
 
+	ss->manual = false;
 	ss->paused = false;
 	ss->stop = false;
 
+	ss->play_pause_hotkey = obs_hotkey_register_source(source,
+			"SlideShow.PlayPause",
+			obs_module_text("SlideShow.PlayPause"),
+			play_pause_hotkey, ss);
+
+	ss->restart_hotkey = obs_hotkey_register_source(source,
+			"SlideShow.Restart",
+			obs_module_text("SlideShow.Restart"),
+			restart_hotkey, ss);
+
+	ss->stop_hotkey = obs_hotkey_register_source(source,
+			"SlideShow.Stop",
+			obs_module_text("SlideShow.Stop"),
+			stop_hotkey, ss);
+
+	ss->prev_hotkey = obs_hotkey_register_source(source,
+			"SlideShow.NextSlide",
+			obs_module_text("SlideShow.NextSlide"),
+			next_slide_hotkey, ss);
+
+	ss->prev_hotkey = obs_hotkey_register_source(source,
+			"SlideShow.PreviousSlide",
+			obs_module_text("SlideShow.PreviousSlide"),
+			previous_slide_hotkey, ss);
+
 	pthread_mutex_init_value(&ss->mutex);
 	if (pthread_mutex_init(&ss->mutex, NULL) != 0)
 		goto error;
@@ -474,7 +646,7 @@ static void ss_video_tick(void *data, float seconds)
 		return;
 	}
 
-	if (ss->pause_on_deactivate || ss->stop || ss->paused)
+	if (ss->pause_on_deactivate || ss->manual || ss->stop || ss->paused)
 		return;
 
 	ss->elapsed += seconds;
@@ -590,6 +762,7 @@ static void ss_defaults(obs_data_t *settings)
 	obs_data_set_default_string(settings, S_CUSTOM_SIZE, T_CUSTOM_SIZE_AUTO);
 	obs_data_set_default_string(settings, S_BEHAVIOR,
 			S_BEHAVIOR_ALWAYS_PLAY);
+	obs_data_set_default_string(settings, S_MODE, S_MODE_AUTO);
 	obs_data_set_default_bool(settings, S_LOOP, true);
 }
 
@@ -632,6 +805,11 @@ static obs_properties_t *ss_properties(void *data)
 	obs_property_list_add_string(p, T_BEHAVIOR_PAUSE_UNPAUSE,
 			S_BEHAVIOR_PAUSE_UNPAUSE);
 
+	p = obs_properties_add_list(ppts, S_MODE, T_MODE,
+			OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
+	obs_property_list_add_string(p, T_MODE_AUTO, S_MODE_AUTO);
+	obs_property_list_add_string(p, T_MODE_MANUAL, S_MODE_MANUAL);
+
 	p = obs_properties_add_list(ppts, S_TRANSITION, T_TRANSITION,
 			OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
 	obs_property_list_add_string(p, T_TR_CUT, TR_CUT);