* Boston, MA 02111-1307, USA.
*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <gtk/gtk.h>
#include <glib.h>
#include <ges/ges.h>
+#include <regex.h>
typedef struct App
{
GtkComboBox *halign;
GtkComboBox *valign;
GtkEntry *text;
+ GtkEntry *seconds;
+ GtkWidget *generic_duration;
GstState state;
GType selected_type;
} App;
void disconnect_from_title_source (GESTimelineObject * object, App * app);
+void seconds_notify_text_changed_cb (GtkEntry * widget, GParamSpec * unused,
+ App * app);
+
/* UI state functions *******************************************************/
static void
gtk_widget_set_visible (app->text_properties,
app->selected_type == GES_TYPE_TIMELINE_TITLE_SOURCE);
+
+ gtk_widget_set_visible (app->generic_duration,
+ app->selected_type == GES_TYPE_TIMELINE_TITLE_SOURCE);
}
gboolean
}
}
+static gboolean
+check_time (const gchar * time)
+{
+ static regex_t re;
+ static gboolean compiled = FALSE;
+
+ if (!compiled) {
+ compiled = TRUE;
+ regcomp (&re, "^[0-9][0-9]:[0-5][0-9]:[0-5][0-9](.[0-9]+)?$",
+ REG_EXTENDED | REG_NOSUB);
+ }
+
+ if (!regexec (&re, time, (size_t) 0, NULL, 0))
+ return TRUE;
+ return FALSE;
+}
+
+static guint64
+str_to_time (const gchar * str)
+{
+ guint64 ret;
+ guint64 h, m;
+ gdouble s;
+ gchar buf[15];
+
+ buf[0] = str[0];
+ buf[1] = str[1];
+ buf[2] = '\0';
+
+ h = strtoull (buf, NULL, 10);
+
+ buf[0] = str[3];
+ buf[1] = str[4];
+ buf[2] = '\0';
+
+ m = strtoull (buf, NULL, 10);
+
+ strncpy (buf, &str[6], sizeof (buf));
+ s = strtod (buf, NULL);
+
+ ret = (h * 3600 * GST_SECOND) +
+ (m * 60 * GST_SECOND) + ((guint64) (s * GST_SECOND));
+
+ return ret;
+}
+
+void
+seconds_notify_text_changed_cb (GtkEntry * widget, GParamSpec * unused,
+ App * app)
+{
+ GList *tmp;
+ const gchar *text;
+
+ text = gtk_entry_get_text (app->seconds);
+
+ if (!check_time (text)) {
+ gtk_entry_set_icon_from_stock (app->seconds,
+ GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_DIALOG_WARNING);
+ } else {
+ gtk_entry_set_icon_from_stock (app->seconds,
+ GTK_ENTRY_ICON_SECONDARY, NULL);
+ for (tmp = app->selected_objects; tmp; tmp = tmp->next) {
+ g_object_set (GES_TIMELINE_OBJECT (tmp->data), "duration",
+ (guint64) str_to_time (text), NULL);
+ }
+ }
+}
+
/* application methods ******************************************************/
static void selection_foreach (GtkTreeModel * model, GtkTreePath * path,
void
connect_to_title_source (GESTimelineObject * object, App * app)
{
+ gdouble s;
+ guint64 duration;
+ gchar buf[30];
+
GESTimelineTitleSource *obj;
obj = GES_TIMELINE_TITLE_SOURCE (object);
gtk_combo_box_set_active (app->halign, obj->halign);
gtk_combo_box_set_active (app->valign, obj->valign);
gtk_entry_set_text (app->text, obj->text);
+
+ duration = GES_TIMELINE_OBJECT_DURATION (object);
+
+ s = (duration / (float) GST_SECOND);
+
+ g_snprintf (buf, sizeof (buf), "%02u:%02u:%02u.%09u",
+ GST_TIME_ARGS (duration));
+ gtk_entry_set_text (app->seconds, buf);
}
void
GET_WIDGET (app->add_file, "add_file", GTK_ACTION);
GET_WIDGET (app->delete, "delete", GTK_ACTION);
GET_WIDGET (app->play, "play", GTK_ACTION);
+ GET_WIDGET (app->seconds, "seconds", GTK_ENTRY);
+ GET_WIDGET (app->generic_duration, "generic_duration", GTK_WIDGET);
/* get text notifications */
g_signal_connect (app->text, "notify::text",
G_CALLBACK (text_notify_text_changed_cb), app);
+ g_signal_connect (app->seconds, "notify::text",
+ G_CALLBACK (seconds_notify_text_changed_cb), app);
+
/* we care when the tree selection changes */
if (!(app->selection = gtk_tree_view_get_selection (timeline)))
<child>
<object class="GtkImageMenuItem" id="delete_item">
<property name="visible">True</property>
- <property name="related_action">delete</property>
<property name="use_action_appearance">True</property>
+ <property name="related_action">delete</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
<child>
<object class="GtkMenuItem" id="add_file_item">
<property name="visible">True</property>
- <property name="related_action">add_file</property>
<property name="use_action_appearance">True</property>
+ <property name="related_action">add_file</property>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menuitem4">
<property name="visible">True</property>
- <property name="related_action">add_text</property>
<property name="use_action_appearance">True</property>
+ <property name="related_action">add_text</property>
</object>
</child>
<child>
<child>
<object class="GtkImageMenuItem" id="menuitem2">
<property name="visible">True</property>
- <property name="related_action">play</property>
<property name="use_action_appearance">True</property>
+ <property name="related_action">play</property>
<property name="use_underline">True</property>
<property name="use_stock">True</property>
</object>
<property name="visible">True</property>
<property name="spacing">6</property>
<child>
+ <object class="GtkHBox" id="generic_duration">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="xalign">1</property>
+ <property name="xpad">12</property>
+ <property name="label" translatable="yes">Duration:</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="seconds">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">●</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
<object class="GtkVBox" id="filesource_properties">
<property name="visible">True</property>
<property name="spacing">6</property>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
- <property name="position">0</property>
+ <property name="position">1</property>
</packing>
</child>
<child>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
- <property name="position">1</property>
+ <property name="position">2</property>
</packing>
</child>
</object>
<object class="GtkTreeSelection" id="selection"/>
<object class="GtkSizeGroup" id="LabelSizeGroup">
<widgets>
+ <widget name="label4"/>
<widget name="label3"/>
<widget name="label2"/>
<widget name="label_inpoint"/>
<widget name="label_duration"/>
<widget name="label_duration"/>
<widget name="label_inpoint"/>
+ <widget name="label4"/>
</widgets>
</object>
<object class="GtkAction" id="delete">