[gst-debugger/refactor-v1.0] refactor: restore properties module



commit 10f9bc85161bc87ab356bbbb369e74d4c2e3e019
Author: Marcin Kolny <marcin kolny gmail com>
Date:   Fri Oct 2 18:23:08 2015 +0200

    refactor: restore properties module

 src/common/deserializer.c                          |   26 +++++-
 src/common/deserializer.h                          |    3 +-
 src/common/gst-utils.c                             |   23 ++++++
 src/common/gst-utils.h                             |    7 ++
 src/common/gstdebugger.proto                       |    2 +
 src/common/serializer.c                            |    2 +-
 src/debugserver/gstdebugserver.c                   |   12 +++-
 src/debugserver/gstdebugservertypes.c              |    1 +
 src/gst-debugger/Makefile.am                       |   15 ++++-
 src/gst-debugger/controller/command_factory.cpp    |   41 ++++------
 src/gst-debugger/controller/command_factory.h      |    4 +-
 src/gst-debugger/controller/controller.cpp         |   65 +++++++--------
 src/gst-debugger/controller/controller.h           |    2 +
 src/gst-debugger/dialogs/klasses_dialog.cpp        |    4 +-
 src/gst-debugger/dialogs/klasses_dialog.h          |    2 +-
 src/gst-debugger/gvalue-converter/gvalue_base.cpp  |   55 ++++++++++---
 src/gst-debugger/gvalue-converter/gvalue_base.h    |   22 ++++-
 .../gvalue-converter/gvalue_boolean.cpp            |   19 +++--
 src/gst-debugger/gvalue-converter/gvalue_boolean.h |    5 +-
 src/gst-debugger/gvalue-converter/gvalue_caps.cpp  |   29 +++++---
 src/gst-debugger/gvalue-converter/gvalue_caps.h    |    6 +-
 .../gvalue-converter/gvalue_numeric.cpp            |   28 ++++---
 src/gst-debugger/gvalue-converter/gvalue_numeric.h |    8 +-
 .../gvalue-converter/gvalue_string.cpp             |   19 +++--
 src/gst-debugger/gvalue-converter/gvalue_string.h  |    5 +-
 .../gvalue-converter/gvalue_unknown.cpp            |   28 +++++++
 src/gst-debugger/gvalue-converter/gvalue_unknown.h |   26 ++++++
 src/gst-debugger/models/gst_klass_model.h          |   10 +++
 src/gst-debugger/models/gst_pipeline_model.cpp     |   11 ++-
 src/gst-debugger/models/gst_pipeline_model.h       |    6 +-
 src/gst-debugger/modules/gst_properties_module.cpp |   83 +++++++++-----------
 src/gst-debugger/modules/gst_properties_module.h   |    4 +-
 32 files changed, 387 insertions(+), 186 deletions(-)
---
diff --git a/src/common/deserializer.c b/src/common/deserializer.c
index 14a4477..d6dbe11 100644
--- a/src/common/deserializer.c
+++ b/src/common/deserializer.c
@@ -92,15 +92,19 @@ GstBuffer* gst_buffer_deserialize (const gchar * buffer, gint size)
   return gstbuffer;
 }
 
-void g_value_deserialize (GValue * value, GType type, InternalGType internal_type, const gchar * data)
+void g_value_deserialize (GValue * value, GType type, InternalGType internal_type,
+  const gchar * data, gint len)
 {
+  // I don't use string for Value::data field, because serializer implementation
+  // might change in the future (I don't break the API then).
+  gchar *t_data = g_strndup (data, len);
   switch (internal_type) {
   case INTERNAL_GTYPE_ENUM:
   case INTERNAL_GTYPE_FLAGS:
   {
     GValue tmp = G_VALUE_INIT;
     g_value_init (&tmp, type);
-    gst_value_deserialize (&tmp, data);
+    gst_value_deserialize (&tmp, t_data);
     if (internal_type == INTERNAL_GTYPE_ENUM) {
       g_value_init(value, gst_utils_get_virtual_enum_type ());
       g_value_set_enum (value, g_value_get_int (&tmp));
@@ -113,15 +117,25 @@ void g_value_deserialize (GValue * value, GType type, InternalGType internal_typ
   }
   case INTERNAL_GTYPE_GST_OBJECT: // and with pointers
   case INTERNAL_GTYPE_FUNDAMENTAL:
-  case INTERNAL_GTYPE_UNKNOWN:
     g_value_init (value, type);
-    gst_value_deserialize (value, data);
+    gst_value_deserialize (value, t_data);
     break;
+  case INTERNAL_GTYPE_UNKNOWN:
+  {
+    GValue tmp = G_VALUE_INIT;
+    g_value_init (&tmp, G_TYPE_STRING);
+    gst_value_deserialize (&tmp, t_data);
+    g_value_init (value, gst_unknown_type_get_type ());
+    g_value_take_boxed (value, gst_unknown_type_new (g_value_get_string (&tmp)));
+    g_value_unset (&tmp);
+
+    break;
+  }
   case INTERNAL_GTYPE_CAPS:
   {
     GstCaps *caps;
     g_value_init (value, G_TYPE_STRING);
-    gst_value_deserialize (value, data);
+    gst_value_deserialize (value, t_data);
     caps = gst_caps_from_string (g_value_get_string (value));
     g_value_unset (value);
     g_value_init (value, GST_TYPE_CAPS);
@@ -129,4 +143,6 @@ void g_value_deserialize (GValue * value, GType type, InternalGType internal_typ
     break;
   }
   }
+
+  g_free (t_data);
 }
diff --git a/src/common/deserializer.h b/src/common/deserializer.h
index 3070074..7e6a54d 100644
--- a/src/common/deserializer.h
+++ b/src/common/deserializer.h
@@ -22,7 +22,8 @@ GstMessage* gst_message_deserialize (const gchar * buffer, gint size);
 
 GstBuffer* gst_buffer_deserialize (const gchar * buffer, gint size);
 
-void g_value_deserialize (GValue * value, GType type, InternalGType internal_type, const gchar * data);
+void g_value_deserialize (GValue * value, GType type, InternalGType internal_type,
+  const gchar * data, gint len);
 
 G_END_DECLS
 
diff --git a/src/common/gst-utils.c b/src/common/gst-utils.c
index ccfeae3..034538b 100644
--- a/src/common/gst-utils.c
+++ b/src/common/gst-utils.c
@@ -167,3 +167,26 @@ GType gst_utils_get_virtual_flags_type (void)
 
   return (GType) id;
 }
+
+
+static gpointer gst_unknown_type_copy (gpointer *object)
+{
+  return gst_unknown_type_new (((GstUnknownType*)object)->type_name);
+}
+
+static void gst_unknown_type_free (gpointer *object)
+{
+  g_free (((GstUnknownType*)object)->type_name);
+  g_slice_free1 (sizeof (GstUnknownType), object);
+}
+
+G_DEFINE_BOXED_TYPE (GstUnknownType, gst_unknown_type, (GBoxedCopyFunc)gst_unknown_type_copy, 
(GBoxedFreeFunc)gst_unknown_type_free);
+
+GstUnknownType* gst_unknown_type_new (const gchar *type_name)
+{
+  GstUnknownType *self = g_slice_new (GstUnknownType);
+  self->type_name = g_strdup (type_name);
+  return self;
+}
+
+
diff --git a/src/common/gst-utils.h b/src/common/gst-utils.h
index 7d7779c..bd6d71b 100644
--- a/src/common/gst-utils.h
+++ b/src/common/gst-utils.h
@@ -19,6 +19,13 @@ GType gst_utils_get_virtual_enum_type (void);
 
 GType gst_utils_get_virtual_flags_type (void);
 
+typedef struct {
+  gchar *type_name;
+} GstUnknownType;
+
+GType gst_unknown_type_get_type(void);
+GstUnknownType *gst_unknown_type_new (const gchar *type_name);
+
 G_END_DECLS
 
 #endif /* __GST_DEBUGGER_GST_UTILS_H__ */
diff --git a/src/common/gstdebugger.proto b/src/common/gstdebugger.proto
index 52cd357..d4c2aa0 100644
--- a/src/common/gstdebugger.proto
+++ b/src/common/gstdebugger.proto
@@ -11,6 +11,7 @@ message Value {
        required uint64 gtype = 1;
        optional int32 internal_type = 2;
        required bytes data = 3;
+       required string type_name = 4;
 }
 
 message PropertyInfo {
@@ -109,6 +110,7 @@ message Command {
                string log_threshold = 6;
                bool entire_topology = 7;
                PropertyRequest property = 8;
+               PropertyValue property_set = 9;
        }
 }
 
diff --git a/src/common/serializer.c b/src/common/serializer.c
index cb5c3e4..e41a4a5 100644
--- a/src/common/serializer.c
+++ b/src/common/serializer.c
@@ -154,7 +154,7 @@ gchar * g_value_serialize (GValue * value, GType * type, InternalGType * interna
   } else {
     g_value_init(&tmp, G_TYPE_STRING);
     gchar buffer[128];
-    snprintf (buffer, 128, "<unknown type '%s', can not read value>", g_type_name (value->g_type));
+    snprintf (buffer, 128, "%s", g_type_name (value->g_type));
     *type = G_TYPE_STRING;
     *internal_type = INTERNAL_GTYPE_UNKNOWN;
     g_value_set_string (&tmp, g_strdup (buffer));
diff --git a/src/debugserver/gstdebugserver.c b/src/debugserver/gstdebugserver.c
index f64e225..3c2440b 100644
--- a/src/debugserver/gstdebugserver.c
+++ b/src/debugserver/gstdebugserver.c
@@ -218,8 +218,9 @@ gst_debugserver_tracer_send_property (GstDebugserverTcp * tcp_server, TcpClient
   value.data.data = serialized_data;
   value.data.len = serialized_data == NULL ? 0 : strlen (serialized_data);
   value.gtype = out_gtype;
+  value.type_name = (gchar*) g_type_name (spec->value_type);
 
-  if (out_gtype == spec->value_type) {
+  if (out_gtype != spec->value_type) {
     value.internal_type = out_internal_type;
     value.has_internal_type = TRUE;
   } else {
@@ -432,6 +433,15 @@ static void gst_debugserver_command_handler (GstDebugger__Command * command,
   case GST_DEBUGGER__COMMAND__COMMAND_TYPE_PROPERTY:
     gst_debugserver_process_property_request (self, client, command->property);
     break;
+  case GST_DEBUGGER__COMMAND__COMMAND_TYPE_PROPERTY_SET:
+  {
+    GValue val = G_VALUE_INIT;
+    GstElement *element = gst_utils_get_element_from_path (GST_ELEMENT_CAST (self->pipeline), 
command->property_set->object);
+    g_value_deserialize (&val, command->property_set->value->gtype, 
command->property_set->value->internal_type,
+      command->property_set->value->data.data, command->property_set->value->data.len);
+    g_object_set_property (G_OBJECT (element), command->property_set->name, &val);
+    g_value_unset (&val);
+  }
   }
 }
 
diff --git a/src/debugserver/gstdebugservertypes.c b/src/debugserver/gstdebugservertypes.c
index 89fb36c..e20377a 100644
--- a/src/debugserver/gstdebugservertypes.c
+++ b/src/debugserver/gstdebugservertypes.c
@@ -189,6 +189,7 @@ static void gst_debugserver_types_send_klass (GstDebugserverTcp *tcp_server, Tcp
     g_param_value_set_default (specs[i], &gvalue);
     value = (GstDebugger__Value*) g_malloc (sizeof (GstDebugger__Value));
     gst_debugger__value__init (value);
+    value->type_name = (gchar*) g_type_name (specs[i]->value_type);
     value->data.data = (uint8_t*) g_value_serialize (&gvalue, &out_gtype, &out_internal_type);
     value->data.len = value->data.data == NULL ? 0 : strlen (value->data.data);
     value->gtype = out_gtype;
diff --git a/src/gst-debugger/Makefile.am b/src/gst-debugger/Makefile.am
index af2841c..cfad0a9 100644
--- a/src/gst-debugger/Makefile.am
+++ b/src/gst-debugger/Makefile.am
@@ -69,7 +69,20 @@ gst_debugger_ GST_API_VERSION@_SOURCES =             \
        modules/gst_properties_module.h \
        models/gst_klass_model.h \
        dialogs/klasses_dialog.h \
-       dialogs/klasses_dialog.cpp
+       dialogs/klasses_dialog.cpp \
+       gvalue-converter/gvalue_base.cpp \
+       gvalue-converter/gvalue_base.h \
+       gvalue-converter/gvalue_unknown.cpp \
+       gvalue-converter/gvalue_unknown.h \
+       gvalue-converter/gvalue_numeric.cpp \
+       gvalue-converter/gvalue_numeric.h \
+       gvalue-converter/gvalue_boolean.cpp \
+       gvalue-converter/gvalue_boolean.h \
+       gvalue-converter/gvalue_caps.cpp \
+       gvalue-converter/gvalue_caps.h \
+       gvalue-converter/gvalue_string.cpp \
+       gvalue-converter/gvalue_string.h
+       
 
 gst_debugger_ GST_API_VERSION@_LDFLAGS = $(GTKMM_LIBS) $(GSTMM_LIBS) $(GVC_LIBS) $(PROTOBUF_LIBS) -lX11
 gst_debugger_ GST_API_VERSION@_LDADD = ../common/libgst-debugger-common-cpp- GST_DEBUGGER_API_VERSION@.la
diff --git a/src/gst-debugger/controller/command_factory.cpp b/src/gst-debugger/controller/command_factory.cpp
index aa49910..4f20e69 100644
--- a/src/gst-debugger/controller/command_factory.cpp
+++ b/src/gst-debugger/controller/command_factory.cpp
@@ -111,34 +111,29 @@ void CommandFactory::send_request_debug_categories_command()
        client->send_command(cmd);
 }
 
-
-/*
-void CommandFactory::send_request_topology_command()
+void CommandFactory::send_set_property_command(const std::string &path, const std::string &property_name, 
GValue *gvalue)
 {
-       Command cmd;
-       cmd.set_command_type(Command_CommandType_TOPOLOGY);
-
-       client->send_command(cmd);
-}
+       GstDebugger::Value *value = new GstDebugger::Value();
+       GType gtype; InternalGType internal_type;
+       char *data = g_value_serialize(gvalue, &gtype, &internal_type);
+       value->set_data(data);
+       g_free (data);
+       value->set_gtype(gtype);
+       value->set_internal_type(internal_type);
+       value->set_type_name("xxx"); // todo
+
+       GstDebugger::PropertyValue *prop_val = new GstDebugger::PropertyValue();
+       prop_val->set_object(path);
+       prop_val->set_name(property_name);
+       prop_val->set_allocated_value(value);
 
-void CommandFactory::send_property_command(const std::string &path, const std::string &property_name, GValue 
*gvalue)
-{
-       Command cmd;
-       cmd.set_command_type(Command_CommandType_PROPERTY);
-       Property *property = new Property();
-       property->set_element_path(path);
-       property->set_property_name(property_name);
-       GType type; InternalGType internal_type;
-       gchar *serialized = g_value_serialize(gvalue, &type, &internal_type);
-       property->set_property_value(serialized);
-       g_free(serialized);
-       property->set_internal_type(internal_type);
-       property->set_type(type);
-       cmd.set_allocated_property(property);
+       GstDebugger::Command cmd;
+       cmd.set_allocated_property_set(prop_val);
 
        client->send_command(cmd);
-}
 
+}
+/*
 void CommandFactory::send_request_pad_dynamic_info(const std::string &pad_path)
 {
        Command cmd;
diff --git a/src/gst-debugger/controller/command_factory.h b/src/gst-debugger/controller/command_factory.h
index 0e94573..00101f4 100644
--- a/src/gst-debugger/controller/command_factory.h
+++ b/src/gst-debugger/controller/command_factory.h
@@ -28,8 +28,8 @@ public:
        void send_data_type_request_command(const std::string &type_name, 
GstDebugger::TypeDescriptionRequest_Type type);
        void send_request_debug_categories_command();
        void send_request_entire_topology_command();
-       /*void send_property_command(const std::string &path, const std::string &property_name, GValue 
*gvalue);
-       void send_request_pad_dynamic_info(const std::string &pad_path);*/
+       void send_set_property_command(const std::string &path, const std::string &property_name, GValue 
*gvalue);
+       /*void send_request_pad_dynamic_info(const std::string &pad_path);*/
 };
 
 #endif /* SRC_GST_DEBUGGER_CONTROLLER_COMMAND_FACTORY_H_ */
diff --git a/src/gst-debugger/controller/controller.cpp b/src/gst-debugger/controller/controller.cpp
index c9c814c..043c26c 100644
--- a/src/gst-debugger/controller/controller.cpp
+++ b/src/gst-debugger/controller/controller.cpp
@@ -7,6 +7,10 @@
 
 #include "controller.h"
 #include "ui_utils.h"
+#include "element_path_processor.h"
+
+#include "common/common.h"
+#include "common/deserializer.h"
 
 #include <gtkmm.h>
 
@@ -30,6 +34,7 @@ Controller::Controller(IMainView *view)
 int Controller::run(int &argc, char **&argv)
 {
        Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv, 
"eu.cookandcommit.gst-debugger");
+       app->set_flags(app->get_flags() | Gio::APPLICATION_NON_UNIQUE);
        view->set_controller(shared_from_this());
        return app->run(*view);
 }
@@ -74,31 +79,10 @@ void Controller::process_frame(const GstDebugger::GStreamerData &data)
                on_klass_list_changed(data.element_klass().name(), true);
                break;
        case GstDebugger::GStreamerData::kPropertyValue:
+               add_property(data.property_value());
                on_property_value_received(data.property_value());
                break;
        }
-       /*
-       case GstreamerInfo_InfoType_PROPERTY:
-       {
-               std::string name = info.property().type_name();
-               if ((info.property().internal_type() == INTERNAL_GTYPE_ENUM || 
info.property().internal_type() == INTERNAL_GTYPE_FLAGS) && !enum_container.has_item(name))
-               {
-                       send_enum_type_request_command(name);
-               }
-               append_property(info.property());
-               on_property_received(info.property());
-               break;
-       }
-       case GstreamerInfo_InfoType_FACTORY:
-               update_factory_model(info.factory_info());
-               on_factory_list_changed(info.factory_info().name());
-               break;
-       case GstreamerInfo_InfoType_PAD_DYNAMIC_INFO:
-               update_pad_dynamic_info(info.pad_dynamic_info());
-               break;
-       default:
-               break;
-       }*/
 }
 
 template<typename T>
@@ -257,21 +241,32 @@ void Controller::update_klass_model(const GstDebugger::ElementKlass &klass_info)
                *it = model;
        }
 }
-/*
-void Controller::append_property(const Property& property)
+
+void Controller::add_property(const GstDebugger::PropertyValue &value)
 {
-       GValue *value = new GValue;
-       *value = {0};
-       g_value_deserialize(value, property.type(), (InternalGType)property.internal_type(), 
property.property_value().c_str());
-
-       auto element = ElementModel::get_parent_element_from_path(property.element_path());
-       std::shared_ptr<GValueBase> gvalue(GValueBase::build_gvalue(value));
-       element->add_property(property.property_name(), gvalue);
-       gvalue->widget_value_changed.connect([gvalue, property, this] {
-               this->send_property_command(property.element_path(), property.property_name(), 
gvalue->get_gvalue());
-       });
+       auto element = 
std::dynamic_pointer_cast<ElementModel>(ElementPathProcessor(value.object()).get_last_obj());
+
+       if (!element)
+               return;
+
+       GValue *g_val = new GValue;
+       *g_val = {0};
+       g_value_deserialize(g_val, value.value().gtype(), (InternalGType)value.value().internal_type(),
+                       value.value().data().c_str(), value.value().data().length());
+
+       bool had_property = element->has_property(value.name());
+
+       auto vb = element->add_property(value.name(), g_val);
+
+       if (!had_property)
+       {
+               auto obj = value.object(); auto name = value.name();
+               vb->widget_value_changed.connect([this, name, obj, vb]{
+                       this->send_set_property_command(obj, name, vb->get_gvalue());
+               });
+       }
 }
-*/
+
 void Controller::log(const std::string &message)
 {
        // todo date/time?
diff --git a/src/gst-debugger/controller/controller.h b/src/gst-debugger/controller/controller.h
index 8d328d4..a91b176 100644
--- a/src/gst-debugger/controller/controller.h
+++ b/src/gst-debugger/controller/controller.h
@@ -42,6 +42,8 @@ private:
        void update_factory_model(const GstDebugger::FactoryType &factory_info);
        void update_klass_model(const GstDebugger::ElementKlass &klass_element);
 
+       void add_property(const GstDebugger::PropertyValue &value);
+
        /*
 
 
diff --git a/src/gst-debugger/dialogs/klasses_dialog.cpp b/src/gst-debugger/dialogs/klasses_dialog.cpp
index f0af2ef..565d2b2 100644
--- a/src/gst-debugger/dialogs/klasses_dialog.cpp
+++ b/src/gst-debugger/dialogs/klasses_dialog.cpp
@@ -37,7 +37,7 @@ void KlassesDialog::set_controller(const std::shared_ptr<Controller> &controller
                c[klasses_columns.m_col_value] = VALUE; \
        } while (false)
 
-std::string KlassesDialog::g_param_flags_to_string(GParamFlags v, std::string flags_name)
+std::string KlassesDialog::g_param_flags_to_string(GParamFlags v)
 {
 #define xstr(s) str(s)
 #define str(s) #s
@@ -95,7 +95,7 @@ void KlassesDialog::reload_list(const Glib::ustring &klass_name, bool add)
 
                        APPEND_SUB_ROW(cr, "Nick", property.get_nick());
                        APPEND_SUB_ROW(cr, "Blurb", property.get_blurb());
-                       APPEND_SUB_ROW(cr, "Flags", g_param_flags_to_string(property.get_flags(), 
"GParamFlags"));
+                       APPEND_SUB_ROW(cr, "Flags", g_param_flags_to_string(property.get_flags()));
                }
        }
 }
diff --git a/src/gst-debugger/dialogs/klasses_dialog.h b/src/gst-debugger/dialogs/klasses_dialog.h
index a75ae7b..98e401b 100644
--- a/src/gst-debugger/dialogs/klasses_dialog.h
+++ b/src/gst-debugger/dialogs/klasses_dialog.h
@@ -31,7 +31,7 @@ class KlassesDialog : public RemoteDataDialog
 
        void reload_list(const Glib::ustring &klass_name, bool add);
 
-       std::string g_param_flags_to_string(GParamFlags v, std::string flags_name);
+       std::string g_param_flags_to_string(GParamFlags v);
 
 public:
        KlassesDialog(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& builder);
diff --git a/src/gst-debugger/gvalue-converter/gvalue_base.cpp 
b/src/gst-debugger/gvalue-converter/gvalue_base.cpp
index 5799a46..2c57ce9 100644
--- a/src/gst-debugger/gvalue-converter/gvalue_base.cpp
+++ b/src/gst-debugger/gvalue-converter/gvalue_base.cpp
@@ -6,11 +6,13 @@
  */
 
 #include "gvalue_base.h"
+#include "gvalue_unknown.h"
+#include "gvalue_numeric.h"
 #include "gvalue_boolean.h"
 #include "gvalue_caps.h"
-#include "gvalue_enum.h"
-#include "gvalue_numeric.h"
 #include "gvalue_string.h"
+/*#include "gvalue_enum.h"
+*/
 
 #include <gst/gst.h>
 
@@ -21,18 +23,21 @@ GValueBase::GValueBase(GValue *gobj)
 
 GValueBase::~GValueBase()
 {
+       clear_gvalue();
+}
+
+void GValueBase::clear_gvalue()
+{
        if (g_value != nullptr)
        {
                g_value_unset(g_value);
                delete g_value;
        }
-       delete widget;
 }
 
 GValueBase* GValueBase::build_gvalue(GValue* gobj)
 {
        GType value_type = G_VALUE_TYPE(gobj);
-
        switch (value_type)
        {
        case G_TYPE_STRING:
@@ -59,23 +64,51 @@ GValueBase* GValueBase::build_gvalue(GValue* gobj)
                break;
        }
 
-       if (G_TYPE_IS_ENUM(G_VALUE_TYPE(gobj)) || G_TYPE_IS_FLAGS(G_VALUE_TYPE(gobj)))
+       /*if (G_TYPE_IS_ENUM(G_VALUE_TYPE(gobj)) || G_TYPE_IS_FLAGS(G_VALUE_TYPE(gobj)))
        {
                return new GValueEnum(gobj);
        }
+*/
 
-       if (G_VALUE_TYPE(gobj) == gst_caps_get_type())
+       if (G_VALUE_TYPE(gobj) == GST_TYPE_CAPS)
        {
                return new GValueCaps(gobj);
        }
 
-       return nullptr;
+       return new GValueUnknown(gobj);
+}
+
+void GValueBase::destroy_widget(GtkWidget *object, gpointer user_data)
+{
+       GValueBase *val = reinterpret_cast<GValueBase*>(user_data);
+
+       val->widgets.erase(std::remove(val->widgets.begin(),
+                       val->widgets.end(), Glib::wrap(object)), val->widgets.end());
 }
 
-void GValueBase::update_gvalue(const std::shared_ptr<GValueBase> &gvalue)
+Gtk::Widget* GValueBase::get_widget()
 {
-       this->g_value = gvalue->g_value;
-       gvalue->g_value = nullptr;
+       Gtk::Widget* widget = Gtk::manage(create_widget());
 
-       update_widget();
+       g_signal_connect((gpointer)widget->gobj(), "destroy",
+                       (GCallback)&GValueBase::destroy_widget, (gpointer)this);
+
+       widgets.push_back(widget);
+
+       widget->set_data("is-gvalue-widget", GINT_TO_POINTER(1));
+
+       return widget;
+}
+
+void GValueBase::update_gvalue(GValue* gobj)
+{
+       if (gobj != g_value)
+       {
+               clear_gvalue();
+               g_value = gobj;
+       }
+
+       for (auto widget : widgets)
+               update_widget(widget);
 }
+
diff --git a/src/gst-debugger/gvalue-converter/gvalue_base.h b/src/gst-debugger/gvalue-converter/gvalue_base.h
index 91c48ae..c5fa17e 100644
--- a/src/gst-debugger/gvalue-converter/gvalue_base.h
+++ b/src/gst-debugger/gvalue-converter/gvalue_base.h
@@ -13,28 +13,40 @@
 #include <gtkmm.h>
 
 #include <string>
+#include <vector>
 
 class GValueBase
 {
+       void clear_gvalue();
+
 protected:
        GValue* g_value;
-       mutable Gtk::Widget *widget = nullptr;
+       mutable std::vector<Gtk::Widget*> widgets;
+
+       virtual Gtk::Widget *create_widget() = 0;
+
+       virtual void update_widget(Gtk::Widget* widget) = 0;
+
+       static void destroy_widget(GtkWidget *object, gpointer user_data);
 
-       virtual void update_widget() {}
 public:
        GValueBase(GValue* gobj);
        virtual ~GValueBase();
 
        virtual std::string to_string() const = 0;
 
-       virtual Gtk::Widget* get_widget() const = 0;
-
-       void update_gvalue(const std::shared_ptr<GValueBase> &gvalue);
+       /*
+        * caller should manage returned object
+        * by adding it to the container
+        * */
+       Gtk::Widget* get_widget();
 
        static GValueBase* build_gvalue(GValue* g_value);
 
        GValue* get_gvalue() const { return g_value; }
 
+       void update_gvalue(GValue* gobj);
+
        sigc::signal<void> widget_value_changed;
 };
 
diff --git a/src/gst-debugger/gvalue-converter/gvalue_boolean.cpp 
b/src/gst-debugger/gvalue-converter/gvalue_boolean.cpp
index 6d531c6..b231d9b 100644
--- a/src/gst-debugger/gvalue-converter/gvalue_boolean.cpp
+++ b/src/gst-debugger/gvalue-converter/gvalue_boolean.cpp
@@ -28,17 +28,18 @@ std::string GValueBoolean::to_string() const
        return get_value() ? "true" : "false";
 }
 
-Gtk::Widget* GValueBoolean::get_widget() const
+Gtk::Widget* GValueBoolean::create_widget()
 {
-       if (widget == nullptr)
-       {
-               auto cb = new Gtk::CheckButton();
+       auto cb = new Gtk::CheckButton();
 
-               cb->signal_toggled().connect([this, cb]{ g_value_set_boolean(g_value, cb->get_active()); });
-               cb->signal_toggled().connect(widget_value_changed);
+       cb->signal_toggled().connect([this, cb]{ g_value_set_boolean(g_value, cb->get_active()); });
+       cb->signal_toggled().connect(widget_value_changed);
+       update_widget(cb);
 
-               widget = cb;
-       }
+       return cb;
+}
+
+void GValueBoolean::update_widget(Gtk::Widget* widget)
+{
        dynamic_cast<Gtk::CheckButton*>(widget)->set_active(get_value());
-       return widget;
 }
diff --git a/src/gst-debugger/gvalue-converter/gvalue_boolean.h 
b/src/gst-debugger/gvalue-converter/gvalue_boolean.h
index 340565a..3ac979f 100644
--- a/src/gst-debugger/gvalue-converter/gvalue_boolean.h
+++ b/src/gst-debugger/gvalue-converter/gvalue_boolean.h
@@ -12,11 +12,12 @@
 
 class GValueBoolean : public GValueBase
 {
+       Gtk::Widget* create_widget() override;
+
+       void update_widget(Gtk::Widget* widget) override;
 public:
        GValueBoolean(GValue* gobj);
 
-       Gtk::Widget *get_widget() const override;
-
        std::string to_string() const override;
 
        bool get_value() const;
diff --git a/src/gst-debugger/gvalue-converter/gvalue_caps.cpp 
b/src/gst-debugger/gvalue-converter/gvalue_caps.cpp
index f1e64a4..c1d15f9 100644
--- a/src/gst-debugger/gvalue-converter/gvalue_caps.cpp
+++ b/src/gst-debugger/gvalue-converter/gvalue_caps.cpp
@@ -16,19 +16,28 @@ GValueCaps::GValueCaps(GValue *gobj)
 
 std::string GValueCaps::to_string() const
 {
-       Glib::Value<Glib::RefPtr<Gst::Caps>> v;
-       v.init(g_value);
+       gchar *str = gst_caps_to_string(gst_value_get_caps(g_value));
+       std::string caps_str = str;
+       g_free(str);
+       return caps_str;
+}
+
+Gtk::Widget* GValueCaps::create_widget()
+{
+       auto entry = new Gtk::Entry();
+       entry->signal_activate().connect([this, entry] {
+               GstCaps *caps = gst_caps_from_string(entry->get_text().c_str());
+               gst_value_set_caps(this->g_value, caps);
+               gst_caps_unref(caps);
+               update_gvalue(this->g_value);
+       });
 
-       return v.get()->to_string();
+       entry->signal_activate().connect(widget_value_changed);
+       update_widget(entry);
+       return entry;
 }
 
-Gtk::Widget* GValueCaps::get_widget() const
+void GValueCaps::update_widget(Gtk::Widget* widget)
 {
-       if (widget == nullptr)
-       {
-               widget = new Gtk::Entry();
-       }
        dynamic_cast<Gtk::Entry*>(widget)->set_text(to_string());
-       return widget;
 }
-
diff --git a/src/gst-debugger/gvalue-converter/gvalue_caps.h b/src/gst-debugger/gvalue-converter/gvalue_caps.h
index f163123..b866e4b 100644
--- a/src/gst-debugger/gvalue-converter/gvalue_caps.h
+++ b/src/gst-debugger/gvalue-converter/gvalue_caps.h
@@ -12,12 +12,14 @@
 
 class GValueCaps : public GValueBase
 {
+       Gtk::Widget* create_widget() override;
+
+       void update_widget(Gtk::Widget* widget) override;
+
 public:
        GValueCaps(GValue* gobj);
 
        std::string to_string() const override;
-
-       Gtk::Widget* get_widget() const override;
 };
 
 #endif /* SRC_GST_DEBUGGER_GVALUE_CONVERTER_GVALUE_CAPS_H_ */
diff --git a/src/gst-debugger/gvalue-converter/gvalue_numeric.cpp 
b/src/gst-debugger/gvalue-converter/gvalue_numeric.cpp
index ccb9071..3d67a4e 100644
--- a/src/gst-debugger/gvalue-converter/gvalue_numeric.cpp
+++ b/src/gst-debugger/gvalue-converter/gvalue_numeric.cpp
@@ -30,22 +30,28 @@ void GValueNumeric<T>::update_value(const T &val)
        v.set(val);
        g_value_reset(this->g_value);
        g_value_copy(v.gobj(), this->g_value);
+
+       update_gvalue(this->g_value);
 }
 
 template<typename T>
-Gtk::Widget* GValueNumeric<T>::get_widget() const
+void GValueNumeric<T>::update_widget(Gtk::Widget* widget)
 {
-       if (widget == nullptr)
-       {
-               auto entry = new Gtk::Entry();
-               entry->signal_activate().connect([this, entry]{
-                       update_value(std::atol(entry->get_text().c_str()));
-               });
-               entry->signal_activate().connect(widget_value_changed);
-               widget = entry;
-       }
        dynamic_cast<Gtk::Entry*>(widget)->set_text(to_string());
-       return widget;
+}
+
+template<typename T>
+Gtk::Widget* GValueNumeric<T>::create_widget()
+{
+       auto entry = new Gtk::Entry();
+       entry->signal_activate().connect([this, entry]{
+               update_value((T)std::atol(entry->get_text().c_str()));
+       });
+
+       entry->signal_activate().connect(widget_value_changed);
+       update_widget(entry);
+
+       return entry;
 }
 
 // Check GCC
diff --git a/src/gst-debugger/gvalue-converter/gvalue_numeric.h 
b/src/gst-debugger/gvalue-converter/gvalue_numeric.h
index f2c9935..71192fe 100644
--- a/src/gst-debugger/gvalue-converter/gvalue_numeric.h
+++ b/src/gst-debugger/gvalue-converter/gvalue_numeric.h
@@ -13,14 +13,14 @@
 template<typename T>
 class GValueNumeric : public GValueBase
 {
+       void update_value(const T &val);
+       Gtk::Widget* create_widget() override;
+       void update_widget(Gtk::Widget* widget) override;
+
 public:
        GValueNumeric(GValue* gobj);
 
        std::string to_string() const override;
-
-       Gtk::Widget* get_widget() const override;
-
-       void update_value(const T &val);
 };
 
 
diff --git a/src/gst-debugger/gvalue-converter/gvalue_string.cpp 
b/src/gst-debugger/gvalue-converter/gvalue_string.cpp
index 8f144f5..e143a33 100644
--- a/src/gst-debugger/gvalue-converter/gvalue_string.cpp
+++ b/src/gst-debugger/gvalue-converter/gvalue_string.cpp
@@ -21,13 +21,20 @@ std::string GValueString::to_string() const
        return v.get();
 }
 
-Gtk::Widget* GValueString::get_widget() const
+Gtk::Widget* GValueString::create_widget()
 {
-       if (widget == nullptr)
-       {
-               widget = new Gtk::Entry();
-       }
+       auto entry = new Gtk::Entry();
+       entry->signal_activate().connect([this, entry] {
+               g_value_set_string(g_value, entry->get_text().c_str());
+               update_gvalue(this->g_value);
+       });
 
+       entry->signal_activate().connect(widget_value_changed);
+       update_widget(entry);
+       return entry;
+}
+
+void GValueString::update_widget(Gtk::Widget* widget)
+{
        dynamic_cast<Gtk::Entry*>(widget)->set_text(to_string());
-       return widget;
 }
diff --git a/src/gst-debugger/gvalue-converter/gvalue_string.h 
b/src/gst-debugger/gvalue-converter/gvalue_string.h
index 13222e3..dbb5da1 100644
--- a/src/gst-debugger/gvalue-converter/gvalue_string.h
+++ b/src/gst-debugger/gvalue-converter/gvalue_string.h
@@ -12,12 +12,15 @@
 
 class GValueString : public GValueBase
 {
+       Gtk::Widget* create_widget() override;
+
+       void update_widget(Gtk::Widget* widget) override;
+
 public:
        GValueString(GValue* gobj);
 
        std::string to_string() const override;
 
-       Gtk::Widget* get_widget() const override;
 };
 
 #endif /* SRC_GST_DEBUGGER_GVALUE_CONVERTER_GVALUE_STRING_H_ */
diff --git a/src/gst-debugger/gvalue-converter/gvalue_unknown.cpp 
b/src/gst-debugger/gvalue-converter/gvalue_unknown.cpp
new file mode 100644
index 0000000..2c91897
--- /dev/null
+++ b/src/gst-debugger/gvalue-converter/gvalue_unknown.cpp
@@ -0,0 +1,28 @@
+/*
+ * gvalue_unknown.cpp
+ *
+ *  Created on: Oct 1, 2015
+ *      Author: loganek
+ */
+
+#include "gvalue_unknown.h"
+#include "common/gst-utils.h"
+GValueUnknown::GValueUnknown(GValue *gobj)
+: GValueBase(gobj)
+{}
+
+std::string GValueUnknown::to_string() const
+{
+       GstUnknownType *unknown_type = (GstUnknownType*)g_value_get_boxed(g_value);
+       return "unsupported type: " + std::string(unknown_type->type_name);
+}
+
+Gtk::Widget* GValueUnknown::create_widget()
+{
+       auto lbl = new Gtk::Label();
+
+       lbl->set_text(to_string());
+
+       return lbl;
+}
+
diff --git a/src/gst-debugger/gvalue-converter/gvalue_unknown.h 
b/src/gst-debugger/gvalue-converter/gvalue_unknown.h
new file mode 100644
index 0000000..78808df
--- /dev/null
+++ b/src/gst-debugger/gvalue-converter/gvalue_unknown.h
@@ -0,0 +1,26 @@
+/*
+ * gvalue_unknown.h
+ *
+ *  Created on: Oct 1, 2015
+ *      Author: loganek
+ */
+
+#ifndef SRC_GST_DEBUGGER_GVALUE_CONVERTER_GVALUE_UNKNOWN_H_
+#define SRC_GST_DEBUGGER_GVALUE_CONVERTER_GVALUE_UNKNOWN_H_
+
+#include "gvalue_base.h"
+
+class GValueUnknown : public GValueBase
+{
+protected:
+       Gtk::Widget* create_widget() override;
+
+       void update_widget(Gtk::Widget* widget) override{}
+
+public:
+       GValueUnknown(GValue* gobj);
+
+       std::string to_string() const override;
+};
+
+#endif /* SRC_GST_DEBUGGER_GVALUE_CONVERTER_GVALUE_UNKNOWN_H_ */
diff --git a/src/gst-debugger/models/gst_klass_model.h b/src/gst-debugger/models/gst_klass_model.h
index b3669e5..301326e 100644
--- a/src/gst-debugger/models/gst_klass_model.h
+++ b/src/gst-debugger/models/gst_klass_model.h
@@ -51,6 +51,16 @@ public:
        }
 
        const std::vector<PropertyModel>& get_properties() const { return properties; }
+
+       boost::optional<PropertyModel> get_property(const std::string &property_name) const
+       {
+               auto it = std::find_if(properties.begin(), properties.end(), [property_name](const 
PropertyModel& m) { return m.get_name() == property_name; });
+
+               if (it == properties.end())
+                       return boost::none;
+
+               return *it;
+       }
 };
 
 #endif /* SRC_GST_DEBUGGER_MODELS_GST_KLASS_MODEL_H_ */
diff --git a/src/gst-debugger/models/gst_pipeline_model.cpp b/src/gst-debugger/models/gst_pipeline_model.cpp
index 017b2d2..48de45e 100644
--- a/src/gst-debugger/models/gst_pipeline_model.cpp
+++ b/src/gst-debugger/models/gst_pipeline_model.cpp
@@ -70,18 +70,21 @@ std::shared_ptr<ElementModel> ElementModel::get_child(const std::string &child_n
        return (it != children.end()) ? *it : std::shared_ptr<ElementModel>();
 }
 
-/*void ElementModel::add_property(const std::string &name, const std::shared_ptr<GValueBase>& gvalue)
+std::shared_ptr<GValueBase> ElementModel::add_property(const std::string &name, GValue *g_val)
 {
        if (properties.find(name) == properties.end())
        {
-               properties[name] = gvalue;
+               auto vb = std::shared_ptr<GValueBase>(GValueBase::build_gvalue(g_val));
+               properties[name] = vb;
+               return vb;
        }
        else
        {
-               gvalue->update_gvalue(gvalue);
+               properties[name]->update_gvalue(g_val);
+               return properties[name];
        }
 }
-*/
+
 std::shared_ptr<ElementModel> ElementModel::get_parent_element_from_path(const std::string &path)
 {
        ElementPathProcessor proc(path);
diff --git a/src/gst-debugger/models/gst_pipeline_model.h b/src/gst-debugger/models/gst_pipeline_model.h
index 3d233dd..89ba6b2 100644
--- a/src/gst-debugger/models/gst_pipeline_model.h
+++ b/src/gst-debugger/models/gst_pipeline_model.h
@@ -111,12 +111,16 @@ public:
 
        const std::vector<std::shared_ptr<PadModel>>& get_pads() const { return pads; }
 
-       //void add_property(const std::string &name, const std::shared_ptr<GValueBase>& gvalue);
+       std::shared_ptr<GValueBase> add_property(const std::string &name, GValue *g_val);
+
+       bool has_property(const std::string &name) const { return properties.find(name) != properties.end(); }
 
        static std::shared_ptr<ElementModel> get_parent_element_from_path(const std::string &path);
 
        std::map<std::string, std::shared_ptr<GValueBase>> get_properties() const { return properties; }
 
+       std::string get_type_name() const { return type_name; }
+
        std::shared_ptr<GValueBase> get_property(const std::string &name) { return properties[name]; }
 
        void clean_model() { children.clear(); pads.clear(); properties.clear(); }
diff --git a/src/gst-debugger/modules/gst_properties_module.cpp 
b/src/gst-debugger/modules/gst_properties_module.cpp
index 4940e15..405bbc5 100644
--- a/src/gst-debugger/modules/gst_properties_module.cpp
+++ b/src/gst-debugger/modules/gst_properties_module.cpp
@@ -73,23 +73,23 @@ void GstPropertiesModule::new_property_()
                return;
        }
 
-       /* todo std::shared_ptr<GValueBase> value_base = element->get_property(property->name());
-       std::shared_ptr<GValueEnum> value_enum = std::dynamic_pointer_cast<GValueEnum>(value_base);
+       std::shared_ptr<GValueBase> value_base = element->get_property(property->name());
+       /*std::shared_ptr<GValueEnum> value_enum = std::dynamic_pointer_cast<GValueEnum>(value_base);
 
-       auto& container = const_cast<RemoteDataContainer<GstEnumType>&>(controller->get_enum_container());
-       if (value_enum && container.has_item(property->type_name()))
+       if (value_enum && controller->get_enum_type(property->value().type_name()))
        {
-               value_enum->set_type(container.get_item(property->type_name()));
-       }
+               value_enum->set_type(container.get_item(property->value().type_name()));
+       }*/
 
-       if (!update_property(value_base, property))
+       if (!update_property(value_base, property->name()))
        {
-               append_property(value_base, property);
-       }*/
+               append_property(value_base, property->name());
+       }
+
        delete property;
 }
 
-/*bool GstPropertiesModule::update_property(const std::shared_ptr<GValueBase>& value_base, 
GstDebugger::PropertyInfo *property)
+bool GstPropertiesModule::update_property(const std::shared_ptr<GValueBase>& value_base, const std::string 
prop_name)
 {
        for (auto internal_box : properties_box->get_children())
        {
@@ -99,61 +99,52 @@ void GstPropertiesModule::new_property_()
                        continue;
                }
 
-               Gtk::Label *label = nullptr;
-               Gtk::Widget *widget = nullptr;
+               if (reinterpret_cast<gchar*>(hb->get_data("property-name")) != prop_name)
+                       continue;
 
-               for (auto cd : hb->get_children())
+               for (auto widget : hb->get_children())
                {
-                       if (label == nullptr && (label = dynamic_cast<Gtk::Label*>(cd)) != nullptr)
-                       {
-                               if (label->get_text() != property->name())
-                               {
-                                       label = nullptr;
-                                       break;
-                               }
-                       }
-                       else if (dynamic_cast<Gtk::Button*>(cd) == nullptr || 
dynamic_cast<Gtk::CheckButton*>(cd) != nullptr)
+                       if (widget->get_data("is-gvalue-widget") == GINT_TO_POINTER(1))
                        {
-                               widget = cd;
+                               bool sensitive = widget->get_sensitive();
+                               hb->remove(*widget);
+                               widget = value_base->get_widget();
+                               widget->set_sensitive(sensitive);
+                               widget->show();
+                               hb->pack_start(*widget, true, 10);
+                               hb->reorder_child(*widget, 1);
+                               return true;
                        }
                }
-
-               if (label == nullptr || widget == nullptr)
-               {
-                       continue;
-               }
-
-               hb->remove(*widget);
-               widget = value_base->get_widget();
-               widget->show();
-               hb->pack_start(*widget, true, 10);
-               hb->reorder_child(*widget, 1);
-               return true;
        }
 
        return false;
-}*/
-/*
-void GstPropertiesModule::append_property(const std::shared_ptr<GValueBase>& value_base, 
GstDebugger::PropertyInfo *property)
+}
+
+void GstPropertiesModule::append_property(const std::shared_ptr<GValueBase>& value_base, const std::string 
&prop_name)
 {
+       auto e = std::dynamic_pointer_cast<ElementModel>(controller->get_selected_object());
+       if (!e) return;
+       auto klass = controller->get_klass(e->get_type_name());
+       if (!klass) return;
+       auto prop = klass.get().get_property(prop_name);
+       if (!prop) return;
+
        Gtk::Box *hbox = new Gtk::Box (Gtk::ORIENTATION_HORIZONTAL, 0);
-       hbox->show();
-       auto prop_name = property->name();
+       hbox->set_data("property-name", g_strdup (prop_name.c_str()), g_free);
        Gtk::Label *lbl = Gtk::manage(new Gtk::Label(prop_name));
-       lbl->set_tooltip_text(property->blurb());
-       lbl->show();
+       lbl->set_tooltip_text(prop->get_blurb());
        Gtk::Button *btn = Gtk::manage(new Gtk::Button("Refresh"));
        btn->signal_clicked().connect([this, prop_name] {request_selected_element_property(prop_name);});
-       btn->show();
        hbox->pack_start(*lbl, false, false);
        auto value_widget = value_base->get_widget();
-       value_widget->show();
-       value_widget->set_sensitive(property->flags() & G_PARAM_WRITABLE);
+       value_widget->set_sensitive(prop.get().get_flags() & G_PARAM_WRITABLE);
        hbox->pack_start(*value_widget, true, true);
        hbox->pack_start(*btn, false, false);
        properties_box->pack_start(*hbox);
+       hbox->show_all();
 }
-*/
+
 void GstPropertiesModule::clear_widgets()
 {
        for (auto c : properties_box->get_children())
diff --git a/src/gst-debugger/modules/gst_properties_module.h 
b/src/gst-debugger/modules/gst_properties_module.h
index 24dc973..c2342ed 100644
--- a/src/gst-debugger/modules/gst_properties_module.h
+++ b/src/gst-debugger/modules/gst_properties_module.h
@@ -25,8 +25,8 @@ private:
 
        std::string previous_element_path;
 
-//     void append_property(const std::shared_ptr<GValueBase>& value_base, GstDebugger::PropertyInfo 
*property);
-//     bool update_property(const std::shared_ptr<GValueBase>& value_base, GstDebugger::PropertyInfo 
*property);
+       void append_property(const std::shared_ptr<GValueBase>& value_base, const std::string &prop_name);
+       bool update_property(const std::shared_ptr<GValueBase>& value_base, const std::string prop_name);
        void request_selected_element_property(const std::string &property_name);
 
        void show_pad_properties();



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]