add text box to set durations from formatted strings
authorBrandon Lewis <brandon@collabora.co.uk>
Tue, 27 Jul 2010 13:25:20 +0000 (15:25 +0200)
committerEdward Hervey <edward.hervey@collabora.co.uk>
Thu, 2 Sep 2010 16:04:27 +0000 (18:04 +0200)
tests/examples/ges-ui.c
tests/examples/ges-ui.glade

index 33155be..e1e02ec 100644 (file)
  * 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
 {
@@ -44,6 +48,8 @@ typedef struct App
   GtkComboBox *halign;
   GtkComboBox *valign;
   GtkEntry *text;
+  GtkEntry *seconds;
+  GtkWidget *generic_duration;
   GstState state;
   GType selected_type;
 } App;
@@ -108,6 +114,9 @@ void connect_to_title_source (GESTimelineObject * object, App * 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
@@ -194,6 +203,9 @@ app_selection_changed_cb (GtkTreeSelection * selection, App * app)
 
   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
@@ -278,6 +290,74 @@ text_notify_text_changed_cb (GtkEntry * widget, GParamSpec * unused, App * app)
   }
 }
 
+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,
@@ -653,11 +733,23 @@ disconnect_from_filesource (GESTimelineObject * object, App * app)
 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
@@ -717,12 +809,17 @@ create_ui (App * app)
   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)))
index 62ac96d..4d58dd4 100644 (file)
                     <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">&#x25CF;</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">