[gst-debugger/refactor-v1.0] refactor: part 1



commit 76e77b443d854582ab7c0852b37b117d2c51bf27
Author: Marcin Kolny <marcin kolny gmail com>
Date:   Sun Sep 27 13:58:05 2015 +0200

    refactor: part 1

 src/common/gstdebugger.proto                       |  293 ++++----
 src/common/serializer.c                            |    2 +-
 src/debugserver/Makefile.am                        |    8 +-
 src/debugserver/gstdebugserver.c                   |  784 +++++---------------
 src/debugserver/gstdebugserver.h                   |   16 +-
 src/debugserver/gstdebugserverfactory.c            |  101 ---
 src/debugserver/gstdebugserverlog.c                |  168 +++--
 src/debugserver/gstdebugserverlog.h                |   22 +-
 src/debugserver/gstdebugservermessage.c            |  130 ++--
 src/debugserver/gstdebugservermessage.h            |   38 +-
 src/debugserver/gstdebugserverqe.c                 |  248 +++----
 src/debugserver/gstdebugserverqe.h                 |   23 +-
 src/debugserver/gstdebugservertcp.c                |  267 ++++---
 src/debugserver/gstdebugservertcp.h                |   37 +-
 src/debugserver/gstdebugservertopology.c           |   79 +-
 src/debugserver/gstdebugservertopology.h           |    8 +-
 src/debugserver/gstdebugservertypes.c              |  157 ++++
 ...tdebugserverfactory.h => gstdebugservertypes.h} |   15 +-
 src/debugserver/gstdebugserverwatcher.c            |   95 +++
 src/debugserver/gstdebugserverwatcher.h            |   52 ++
 src/gst-debugger/Makefile.am                       |  137 ++---
 src/gst-debugger/controller/command_factory.cpp    |  132 ++--
 src/gst-debugger/controller/command_factory.h      |   19 +-
 src/gst-debugger/controller/controller.cpp         |  167 +++--
 src/gst-debugger/controller/controller.h           |   52 +-
 src/gst-debugger/controller/tcp_client.cpp         |    9 +-
 src/gst-debugger/controller/tcp_client.h           |    5 +-
 .../controller/topology_controller.cpp             |   30 +-
 src/gst-debugger/controller/topology_controller.h  |    8 +-
 src/gst-debugger/dialogs/enums_dialog.cpp          |    2 +-
 src/gst-debugger/dialogs/factories_dialog.cpp      |    8 +-
 src/gst-debugger/dialogs/factories_dialog.h        |    2 +-
 src/gst-debugger/main.cpp                          |    4 +-
 src/gst-debugger/main_window.cpp                   |    7 +-
 src/gst-debugger/main_window.h                     |   15 +-
 src/gst-debugger/models/gst_pipeline_model.cpp     |    4 +-
 src/gst-debugger/models/gst_pipeline_model.h       |    2 +-
 src/gst-debugger/modules/base_main_module.cpp      |   67 ++-
 src/gst-debugger/modules/base_main_module.h        |   36 +-
 src/gst-debugger/modules/bus_messages_module.cpp   |   95 ---
 src/gst-debugger/modules/bus_messages_module.h     |   44 --
 src/gst-debugger/modules/control_module.h          |  120 ++--
 src/gst-debugger/modules/event_module.cpp          |   79 ++
 src/gst-debugger/modules/event_module.h            |   37 +
 src/gst-debugger/modules/gst_properties_module.cpp |   31 +-
 src/gst-debugger/modules/gst_properties_module.h   |    6 +-
 src/gst-debugger/modules/log_module.cpp            |  118 ++--
 src/gst-debugger/modules/log_module.h              |   40 +-
 src/gst-debugger/modules/main_module.cpp           |   22 +-
 src/gst-debugger/modules/message_module.cpp        |  113 +++
 src/gst-debugger/modules/message_module.h          |   50 ++
 src/gst-debugger/modules/pad_data_modules.cpp      |  209 ------
 src/gst-debugger/modules/pad_data_modules.h        |  100 ---
 .../modules/pad_path_control_module.cpp            |  119 ---
 src/gst-debugger/modules/pad_path_control_module.h |   39 -
 .../modules/pad_path_types_control_module.h        |   51 --
 src/gst-debugger/modules/qe_control_module.h       |   99 +++
 src/gst-debugger/modules/query_module.cpp          |   73 ++
 src/gst-debugger/modules/query_module.h            |   37 +
 src/gst-debugger/modules/types_control_module.cpp  |  145 ----
 src/gst-debugger/modules/types_control_module.h    |   45 --
 src/gst-debugger/pipeline-drawer/graph_module.cpp  |    2 +-
 src/gst-debugger/ui/gst-debugger.glade             |    9 +-
 src/gst-debugger/ui_utils.cpp                      |    2 +-
 src/gst-debugger/ui_utils.h                        |    2 +-
 65 files changed, 2262 insertions(+), 2674 deletions(-)
---
diff --git a/src/common/gstdebugger.proto b/src/common/gstdebugger.proto
index 78abc61..e53afa7 100644
--- a/src/common/gstdebugger.proto
+++ b/src/common/gstdebugger.proto
@@ -1,118 +1,166 @@
 syntax = "proto2";
 
-enum Toggle {
-       ENABLE = 0;
-       DISABLE = 1;
+package GstDebugger;
+
+enum Action {
+       ADD = 0;
+       REMOVE = 1;
 }
 
-message PadWatch {
-       required string pad_path = 1;
-       required Toggle toggle = 2;
+message Value {
+       required uint64 gtype = 1;
+       optional int32 internal_type = 2;
+       required bytes data = 3;
+}
 
-       enum WatchType {
-               BUFFER = 0;
-               EVENT = 1;
-               QUERY = 2;
-       }
-       required WatchType watch_type = 3;
-       optional int32 qe_type = 4;
+message PropertyInfo {
+       required string name = 1;
+       required string nick = 2;
+       required string blurb = 3;
+       required int32 flags = 4;
+       required Value value = 5;
+       required string object = 6;
 }
 
-message LogWatch {
-       required int32 log_level = 1; // not supported yet
-       required Toggle toggle = 2;
-       optional string log_category = 3; // not supported yet
+message PropertyRequest {
+       optional string name = 1;
+       required string object = 2;
 }
 
-message MessageWatch {
-       required int32 message_type = 1;
-       required Toggle toggle = 2;
+message MessageRequest {
+       required Action action = 1;
+       required int32 type = 2;
 }
 
-message DebugCategoryList {
-       required string list = 1;
+message MessageInfo {
+       required int32 type = 1;
+       required uint64 timestamp = 2;
+       required string source = 3;
+       required uint32 seqnum = 4;
+       required bytes structure_data = 5;
 }
 
-message LogThreshold {
-       required string list = 1;
-       required bool overwrite = 2;
+message LogRequest {
+       required Action action = 1;
+       required int32 level = 2;
+       optional string category = 3;
 }
 
-message EnumEntry {
-       required string name = 1;
-       required int32 value = 2;
-       required string nick = 3;
+message QueryWatchRequest {
+       required int32 type = 1;
 }
 
-message EnumType {
-       repeated EnumEntry entry = 1;
-       required string type_name = 2;
-       required uint64 base_gtype = 3;
-}
-
-message Property {
-       required string element_path = 1;
-       required string property_name = 2;
-       optional uint32 type = 3;
-       optional int32 internal_type = 4;
-       optional string type_name = 5;
-       optional string property_value = 6;
-       optional string description = 7;
-       optional int32 flags = 8;
-}
-
-message Command {      
-       optional PadWatch pad_watch = 1;
-       optional LogWatch log_watch = 2;
-       optional MessageWatch message_watch = 3;
-       optional LogThreshold log_threshold = 4;
-       optional Property property = 5;
-       optional string enum_name = 6;
-       optional string factory_name = 7;
-       optional string pad_path = 8;
-
-       enum CommandType {
-               PAD_WATCH = 0;
-               LOG_WATCH = 1;
-               MESSAGE_WATCH = 2;
-               LOG_THRESHOLD = 3;
-               DEBUG_CATEGORIES = 4;
-               TOPOLOGY = 5;
-               PROPERTY = 6;
-               ENUM_TYPE = 7;
-               FACTORY = 8;
-               PAD_DYNAMIC_INFO = 9;
+message BufferWatchRequest {
+       required bool send_data = 1;
+}
+
+message EventWatchRequest {
+       required int32 type = 1;
+}
+
+message PadWatchRequest {
+       required Action action = 1;
+       optional string pad = 2;
+       
+       oneof pad_watch_type {
+               QueryWatchRequest query = 3;
+               BufferWatchRequest buffer = 4;
+               EventWatchRequest event = 5;
        }
-       required CommandType command_type = 9;
 }
 
-message GstreamerLog {
+message EventInfo {
+       required int32 type = 1;
+       required uint64 timestamp = 2;
+       required uint32 seqnum = 3;
+       required string pad = 4;
+       required bytes structure_data = 5;
+}
+
+message QueryInfo {
+       required int32 type = 1;
+       required string pad = 2;
+       required bytes structure_data = 3;
+}
+
+message TypeDescriptionRequest {
+       enum Type {
+               FACTORY = 0;
+               ENUM_FLAGS = 1;
+               KLASS = 2;
+       }
+       
+       required string name = 1;
+       required Type type = 2;
+}
+
+message Command {
+       oneof command_type {
+               TypeDescriptionRequest type_description = 1;
+               bool debug_categories_list = 2;
+               MessageRequest message = 3;
+               LogRequest log = 4;
+               PadWatchRequest pad_watch = 5;
+               string log_threshold = 6;
+               bool entire_topology = 7;
+               PropertyRequest property = 8;
+       }
+}
+
+message DebugCategories {
+       repeated string category = 1;
+}
+
+message LogInfo {
        required int32 level = 1;
-       required string category_name = 2;
+       required string category = 2;
        required string file = 3;
        required string function = 4;
        required int32 line = 5;
-       required string object_path = 6;
+       required string object = 6;
        required string message = 7;
 }
 
-message GstreamerQEBM {
-       required bytes payload = 1;
-       optional string pad_path = 2;
+message EnumFlagsValue {
+       required string name = 1;
+       required int32 value = 2;
+       required string nick = 3;
+}
+
+message EnumFlagsType {
+       enum EnumFlagsKind {
+               ENUM = 0;
+               FLAGS = 1;
+       }
+
+       required string type_name = 1;
+       required EnumFlagsKind kind = 2;
+       repeated EnumFlagsValue values = 3;
 }
 
-message TopologyLink {
-       required string src_pad_path = 1;
-       required string sink_pad_path = 2;
+message FactoryMeta {
+       required string key = 1;
+       required string value = 2;
 }
 
-message TopologyTemplate {
+message PadTemplate {
        required string name_template = 1;
        required int32 direction = 2;
        required int32 presence = 3;
        required string caps = 4;
 }
 
+message FactoryType {
+       required string name = 1;
+       repeated FactoryMeta metadata = 2;
+       repeated PadTemplate templates = 3;
+}
+
+message TopologyLink {
+       required string src_pad = 1;
+       required string sink_pad = 2;
+}
+
 message TopologyElement {
        required string path = 1;
        required string type_name = 2;
@@ -125,77 +173,30 @@ message TopologyPad {
        required bool is_ghostpad = 2;
        required int32 direction = 3;
        required int32 presence = 4;
-       optional TopologyTemplate template = 5;
+       optional PadTemplate template = 5;
 }
 
-message PadDynamicInfo {
-       required string allowed_caps = 1;
-       required string current_caps = 2;
-       required string pad_path = 3;
-}
+message TopologyInfo {
+       required Action action = 1;
 
-message FactoryMetaEntry {
-       required string key = 1;
-       required string value = 2;
-}
-
-message FactoryInfo {
-       required string name = 1;
-       repeated TopologyTemplate templates = 2;
-       repeated FactoryMetaEntry meta_entries = 3;
+       oneof topology_type {
+               TopologyLink link = 2;
+               TopologyElement element = 3;
+               TopologyPad pad = 4;
+       }
 }
 
-message Topology {
-       enum ObjectType {
-               PAD = 0;
-               ELEMENT = 1;
-               LINK = 2;
+message GStreamerData {
+       oneof info_type {
+               DebugCategories debug_categories = 1;
+               LogInfo log_info = 2;
+               EnumFlagsType enum_flags_type = 3;
+               FactoryType factory = 4;
+               MessageInfo message_info = 5;
+               Command confirmation = 6;
+               EventInfo event_info = 7;
+               TopologyInfo topology_info = 8;
+               QueryInfo query_info = 9;
+               PropertyInfo property_info = 10;
        }
-       enum Action {
-               ADD = 0;
-               REMOVE = 1;
-       }
-       
-       required ObjectType type = 1;
-       required Action action = 2;
-       optional TopologyPad pad = 3;
-       optional TopologyElement element = 4;
-       optional TopologyLink link = 5;
-}
-
-message ServerError {
-       required string message = 1;
-}
-
-message GstreamerInfo {
-       enum InfoType {
-               BUFFER = 0;
-               EVENT = 1;
-               QUERY = 2;
-               MESSAGE = 3;
-               LOG = 4;
-               DEBUG_CATEGORIES = 5;
-               TOPOLOGY = 6;
-               PAD_WATCH_CONFIRMATION = 7;
-               MESSAGE_CONFIRMATION = 8;
-               PROPERTY = 9;
-               SERVER_ERROR = 10;
-               ENUM_TYPE = 11;
-               FACTORY = 12;
-               PAD_DYNAMIC_INFO = 13;
-       }
-       
-       required InfoType info_type = 1;
-       
-       optional GstreamerLog log = 2;
-       optional DebugCategoryList debug_categories = 3;
-       optional GstreamerQEBM qebm = 4;
-       optional PadWatch confirmation = 5;
-       optional MessageWatch bus_msg_confirmation = 6;
-       optional Topology topology = 7;
-       optional Property property = 8;
-       optional ServerError server_error = 9;
-       optional EnumType enum_type = 10;
-       optional FactoryInfo factory_info = 11;
-       optional PadDynamicInfo pad_dynamic_info = 12;
-}
\ No newline at end of file
+}
diff --git a/src/common/serializer.c b/src/common/serializer.c
index 52beffa..6ab3c04 100644
--- a/src/common/serializer.c
+++ b/src/common/serializer.c
@@ -128,7 +128,7 @@ gchar * g_value_serialize (GValue * value, GType * type, InternalGType * interna
       val = g_value_get_flags (value);
       *internal_type = INTERNAL_GTYPE_FLAGS;
     } else {
-      val = g_value_get_enum(value);
+      val = g_value_get_enum (value);
       *internal_type = INTERNAL_GTYPE_ENUM;
     }
     g_value_set_int(&tmp, val);
diff --git a/src/debugserver/Makefile.am b/src/debugserver/Makefile.am
index b2feecf..ba3f26e 100644
--- a/src/debugserver/Makefile.am
+++ b/src/debugserver/Makefile.am
@@ -3,12 +3,14 @@ plugin_LTLIBRARIES = libgstdebugserver.la
 libgstdebugserver_la_SOURCES = \
        gstdebugserver.c gstdebugserver.h \
        gstdebugservertcp.c gstdebugservertcp.h \
-       gstdebugserverbuffer.c gstdebugserverbuffer.h \
-       gstdebugservermessage.c gstdebugservermessage.h \
        gstdebugserverlog.c gstdebugserverlog.h \
+       gstdebugservermessage.c gstdebugservermessage.h \
+       gstdebugservertypes.c gstdebugservertypes.h \
        gstdebugserverqe.c gstdebugserverqe.h \
        gstdebugservertopology.c gstdebugservertopology.h \
-       gstdebugserverfactory.c gstdebugserverfactory.h
+       gstdebugserverwatcher.c gstdebugserverwatcher.h
+#      gstdebugserverbuffer.c gstdebugserverbuffer.h \
+#      gstdebugserverfactory.c gstdebugserverfactory.h
 
 libgstdebugserver_la_LDFLAGS  = $(GSTREAMER_LIBS) $(PROTOBUF_C_LIBS) $(GIO_LIBS)
 libgstdebugserver_la_LIBADD = ../common/libgst-debugger-common-c- GST_DEBUGGER_API_VERSION@.la
diff --git a/src/debugserver/gstdebugserver.c b/src/debugserver/gstdebugserver.c
index ff6d950..789ef9c 100644
--- a/src/debugserver/gstdebugserver.c
+++ b/src/debugserver/gstdebugserver.c
@@ -31,12 +31,11 @@
 #endif
 
 #include "gstdebugserver.h"
+
 #include "gstdebugservertopology.h"
-#include "gstdebugserverfactory.h"
+
 #include "common/gst-utils.h"
-#include "common/buffer-prepare-utils.h"
 #include "common/serializer.h"
-#include "common/deserializer.h"
 
 #include <string.h>
 
@@ -61,49 +60,33 @@ static void gst_debugserver_tracer_set_property (GObject * object,
 static void gst_debugserver_tracer_get_property (GObject * object,
     guint prop_id, GValue * value, GParamSpec * pspec);
 
+static void gst_debugserver_command_handler (GstDebugger__Command * command,
+    gpointer debugtracer, TcpClient * client);
+
 static void gst_debugserver_tracer_finalize (GObject * obj);
 
 static void
-gst_debugserver_handle_error (GstDebugserverTracer *server,
-  GSocketConnection * client_id, const gchar * message);
+gst_debugserver_log_handler (GstDebugCategory *category, GstDebugLevel level,
+  const gchar *file, const gchar *function, gint line, GObject *object,
+  GstDebugMessage *message, gpointer user_data) G_GNUC_NO_INSTRUMENT;
 
 static void
-gst_debugserver_tracer_log_function (GstDebugCategory * category,
-    GstDebugLevel level, const gchar * file, const gchar * function, gint line,
-    GObject * object, GstDebugMessage * message, gpointer user_data)
-    G_GNUC_NO_INSTRUMENT;
-
-static void gst_debugserver_tracer_close_connection (GstDebugserverTracer * debugserver)
+gst_debugserver_log_handler (GstDebugCategory *category, GstDebugLevel level,
+  const gchar *file, const gchar *function, gint line, GObject *object,
+  GstDebugMessage *message, gpointer user_data)
 {
-  gst_debugserver_message_clean (debugserver->msg_handler);
-  gst_debugserver_log_clean (debugserver->log_handler);
-  gst_debugserver_qe_clean (debugserver->event_handler);
-  gst_debugserver_qe_clean (debugserver->query_handler);
-  gst_debugserver_buffer_clean (debugserver->buffer_handler);
+  GstDebugserverTracer *tracer = GST_DEBUGSERVER_TRACER (user_data);
 
-  gst_debugserver_tcp_stop_server (debugserver->tcp_server);
+  gst_debugserver_log_send_log (tracer->log, tracer->tcp_server, category, level,
+    file, function, line, object, message);
 }
 
 static void
 message_broadcaster (GstBus * bus, GstMessage * message, gpointer user_data)
 {
-  GstDebugserverTracer *debugserver = GST_DEBUGSERVER_TRACER (user_data);
-  GSocketConnection *connection;
-  GSList *clients = gst_debugserver_message_get_clients (debugserver->msg_handler,
-    GST_MESSAGE_TYPE (message));
-  GSList *cl_tmp = clients;
-  gsize size;
-  gchar buff[1024];
-
-  while (clients != NULL) {
-    connection = (GSocketConnection*)clients->data;
-    size = gst_debugserver_qebm_prepare_buffer (GST_MINI_OBJECT (message), NULL, buff, 1024);
-    gst_debugserver_tcp_send_packet (debugserver->tcp_server, connection,
-      buff, size);
-    clients = clients->next;
-  }
+  GstDebugserverTracer *self = GST_DEBUGSERVER_TRACER (user_data);
 
-  g_slist_free (cl_tmp);
+  gst_debugserver_message_send_message (self->message, self->tcp_server, message);
 }
 
 static void
@@ -122,28 +105,25 @@ do_element_new (GstTracer * self, guint64 ts, GstElement * element)
 static void
 do_pad_unlink_post (GstTracer * self, guint64 ts, GstPad * src, GstPad * sink, gboolean result)
 {
-  if (result == FALSE) {
-    return;
+  if (result == TRUE) {
+    gst_debugserver_topology_send_pad_link (src, sink, FALSE, GST_DEBUGSERVER_TRACER (self)->tcp_server, 
NULL);
   }
-  gst_debugserver_topology_send_pad_link (src, sink, FALSE, GST_DEBUGSERVER_TRACER (self)->tcp_server, NULL);
 }
 
 static void
 do_pad_link_post (GstTracer * self, guint64 ts, GstPad * src, GstPad * sink, GstPadLinkReturn result)
 {
-  if (result == FALSE) {
-    return;
+  if (result == TRUE) {
+    gst_debugserver_topology_send_pad_link (src, sink, TRUE, GST_DEBUGSERVER_TRACER (self)->tcp_server, 
NULL);
   }
-  gst_debugserver_topology_send_pad_link (src, sink, TRUE, GST_DEBUGSERVER_TRACER (self)->tcp_server, NULL);
 }
 
 static void
 do_bin_add_post (GstTracer * self, gint64 ts, GstBin * bin, GstElement * element, gboolean result)
 {
-  if (result == FALSE) {
-    return;
+  if (result == TRUE) {
+    gst_debugserver_topology_send_element_in_bin (bin, element, TRUE, GST_DEBUGSERVER_TRACER 
(self)->tcp_server, NULL);
   }
-  gst_debugserver_topology_send_element_in_bin (bin, element, TRUE, GST_DEBUGSERVER_TRACER 
(self)->tcp_server, NULL);
 }
 
 static void
@@ -164,518 +144,36 @@ do_element_remove_pad (GstTracer * self, gint64 ts, GstElement * element, GstPad
   gst_debugserver_topology_send_pad_in_element (element, pad, FALSE, GST_DEBUGSERVER_TRACER 
(self)->tcp_server, NULL);
 }
 
-
 static void
 do_push_event_pre (GstTracer * self, guint64 ts, GstPad * pad, GstEvent * event)
 {
-  GstDebugserverTracer *debugserver = GST_DEBUGSERVER_TRACER (self);
-  GSocketConnection *connection;
-  GSList *clients = gst_debugserver_qe_get_clients (debugserver->event_handler,
-    pad, event->type);
-  gsize size;
-  SAFE_PREPARE_BUFFER_INIT (1024);
+  GstDebugserverTracer *tracer = GST_DEBUGSERVER_TRACER (self);
 
-  if (clients == NULL) {
-    return;
-  }
-
-  SAFE_PREPARE_BUFFER (
-        gst_debugserver_qebm_prepare_buffer (GST_MINI_OBJECT (event), gst_utils_get_object_path 
(GST_OBJECT_CAST (pad)), m_buff, max_m_buff_size), size);
-
-  while (clients != NULL) {
-    connection = (GSocketConnection*)clients->data;
-    gst_debugserver_tcp_send_packet (GST_DEBUGSERVER_TRACER (self)->tcp_server, connection,
-      m_buff, size);
-    clients = clients->next;
-  }
-
-  SAFE_PREPARE_BUFFER_CLEAN;
+  gst_debugserver_qe_send_qe (tracer->event, tracer->tcp_server, pad, GST_MINI_OBJECT_CAST (event));
 }
 
 static void
 do_pad_query_pre (GstTracer * self, guint64 ts, GstPad * pad, GstQuery * query)
 {
-  GstDebugserverTracer *debugserver = GST_DEBUGSERVER_TRACER (self);
-  GSocketConnection *connection;
-  GSList *clients = gst_debugserver_qe_get_clients (debugserver->query_handler,
-    pad, query->type);
-  gsize size;
-  gchar buff[1024];
-
-  while (clients != NULL) {
-    connection = (GSocketConnection*)clients->data;
-    size = gst_debugserver_qebm_prepare_buffer (GST_MINI_OBJECT (query), gst_utils_get_object_path 
(GST_OBJECT_CAST (pad)), buff, 1024);
-    gst_debugserver_tcp_send_packet (GST_DEBUGSERVER_TRACER (self)->tcp_server, connection,
-      buff, size);
-    clients = clients->next;
-  }
-}
-
-static void
-do_pad_push_pre (GstTracer * self, guint64 ts, GstPad * pad, GstBuffer * buffer)
-{
-  GstDebugserverTracer *debugserver = GST_DEBUGSERVER_TRACER (self);
-  GSocketConnection *connection;
-  GSList *clients = gst_debugserver_buffer_get_clients (debugserver->buffer_handler,
-    pad);
-  gsize size;
-  SAFE_PREPARE_BUFFER_INIT (1024);
-
-  if (clients == NULL) {
-    return;
-  }
-
-  SAFE_PREPARE_BUFFER (
-    gst_debugserver_qebm_prepare_buffer (GST_MINI_OBJECT (buffer), gst_utils_get_object_path 
(GST_OBJECT_CAST (pad)), m_buff, max_m_buff_size), size);
-
-  while (clients != NULL) {
-    connection = (GSocketConnection*)clients->data;
-    gst_debugserver_tcp_send_packet (GST_DEBUGSERVER_TRACER (self)->tcp_server, connection,
-      m_buff, size);
-    clients = clients->next;
-  }
-
-  SAFE_PREPARE_BUFFER_CLEAN;
-
-  g_slist_free (clients);
-}
-
-#define ENUM_FLAG_PREPARE_BUFFER_METHOD(KLASS_VALUE, BASE_GTYPE) \
-  do { \
-    KLASS_VALUE *values = klass->values; \
-    guint i = 0; \
-    EnumEntry **entries; \
-    GstreamerInfo info = GSTREAMER_INFO__INIT; \
-    EnumType msg = ENUM_TYPE__INIT; \
-    info.info_type = GSTREAMER_INFO__INFO_TYPE__ENUM_TYPE; \
-    gint len; \
-    entries = g_malloc (sizeof (EnumEntry) * (klass->n_values));  \
-    for (i = 0; i < klass->n_values; i++) { \
-      entries[i] = g_malloc (sizeof (EnumEntry)); \
-      enum_entry__init (entries[i]); \
-      entries[i]->name = (gchar*) values[i].value_name; \
-      entries[i]->value = values[i].value; \
-      entries[i]->nick = (gchar*) values[i].value_nick; \
-    } \
-    msg.entry = entries; \
-    msg.n_entry = klass->n_values; \
-    msg.type_name = (gchar*) G_ENUM_CLASS_TYPE_NAME (klass); \
-    msg.base_gtype = BASE_GTYPE; \
-    info.enum_type = &msg; \
-    len = gstreamer_info__get_packed_size (&info); \
-    if (len > size) { \
-      goto finalize; \
-    } \
-    gstreamer_info__pack (&info, (uint8_t*) buffer); \
-  finalize: \
-    for (i = 0; i < klass->n_values; i++) { \
-      g_free (entries[i]); \
-    } \
-    g_free (entries); \
-    return len; \
-  } while (FALSE);
-
-static gint
-gst_debug_server_prepare_enum_type_buffer (GEnumClass * klass, gchar * buffer, gint size)
-{
-  ENUM_FLAG_PREPARE_BUFFER_METHOD(GEnumValue, G_TYPE_ENUM)
-}
+  GstDebugserverTracer *tracer = GST_DEBUGSERVER_TRACER (self);
 
-static gint
-gst_debug_server_prepare_flags_type_buffer (GFlagsClass * klass, gchar * buffer, gint size)
-{
-  ENUM_FLAG_PREPARE_BUFFER_METHOD(GFlagsValue, G_TYPE_FLAGS)
+  gst_debugserver_qe_send_qe (tracer->query, tracer->tcp_server, pad, GST_MINI_OBJECT_CAST (query));
 }
 
 static void
-gst_debugserver_send_enum (GstDebugserverTracer * debugserver, GSocketConnection * client, const gchar * 
klass_name)
-{
-  GType type = g_type_from_name (klass_name);
-  GEnumClass *klass = g_type_class_peek (type);
-  SAFE_PREPARE_BUFFER_INIT (1024);
-  gint size;
-
-  if (klass == NULL) {
-    gst_debugserver_handle_error (debugserver, client, "Cannot find enum type");
-    return;
-  }
-
-  SAFE_PREPARE_BUFFER (
-    gst_debug_server_prepare_enum_type_buffer (klass, m_buff, max_m_buff_size), size);
-
-  gst_debugserver_tcp_send_packet (debugserver->tcp_server, client, m_buff, size);
-  SAFE_PREPARE_BUFFER_CLEAN;
-}
-
-static void
-gst_debugserver_send_flag (GstDebugserverTracer * debugserver, GSocketConnection * client, const gchar * 
klass_name)
-{
-  GType type = g_type_from_name (klass_name);
-  GFlagsClass *klass = g_type_class_peek (type);
-  SAFE_PREPARE_BUFFER_INIT (1024);
-  gint size;
-
-  if (klass == NULL) {
-    gst_debugserver_handle_error (debugserver, client, "Cannot find flags type");
-    return;
-  }
-
-  SAFE_PREPARE_BUFFER (
-    gst_debug_server_prepare_flags_type_buffer (klass, m_buff, max_m_buff_size), size);
-
-  gst_debugserver_tcp_send_packet (debugserver->tcp_server, client, m_buff, size);
-  SAFE_PREPARE_BUFFER_CLEAN;
-}
-
-static void
-gst_debugserver_send_enum_flags (GstDebugserverTracer * debugserver, GSocketConnection * client, const gchar 
* klass_name)
-{
-  GType type = g_type_from_name (klass_name);
-
-  if (G_TYPE_IS_ENUM (type)) {
-    gst_debugserver_send_enum (debugserver, client, klass_name);
-  } else if (G_TYPE_IS_FLAGS (type)) {
-    gst_debugserver_send_flag (debugserver, client, klass_name);
-  } else {
-    gst_debugserver_handle_error (debugserver, client, "requested type info is neither enum nor flags");
-  }
-}
-
-static gint
-gst_debugserver_pad_prepare_dynamic_info_buffer (GstPad * pad, gchar * buffer, gint max_size)
-{
-  GstreamerInfo info = GSTREAMER_INFO__INIT;
-  PadDynamicInfo pad_info = PAD_DYNAMIC_INFO__INIT;
-  gint size;
-  GstCaps *allowed_caps = gst_pad_get_allowed_caps (pad);
-  gchar *allowed_caps_str = gst_caps_to_string (allowed_caps);
-  GstCaps *current_caps = gst_pad_get_current_caps (pad);
-  gchar *current_caps_str = gst_caps_to_string (current_caps);
-  gchar *pad_path = gst_utils_get_object_path (GST_OBJECT_CAST (pad));
-  pad_info.pad_path = pad_path;
-  pad_info.allowed_caps = allowed_caps_str;
-  pad_info.current_caps = current_caps_str;
-  info.pad_dynamic_info = &pad_info;
-  info.info_type = GSTREAMER_INFO__INFO_TYPE__PAD_DYNAMIC_INFO;
-
-  size = gstreamer_info__get_packed_size (&info);
-  if (size > max_size) {
-    goto finalize;
-  }
-  gstreamer_info__pack (&info, (guint8*)buffer);
-
-finalize:
-  if (allowed_caps != NULL) {
-    gst_caps_unref (allowed_caps);
-  }
-  if (current_caps != NULL) {
-    gst_caps_unref (current_caps);
-  }
-  g_free (allowed_caps_str);
-  g_free (current_caps_str);
-
-  return size;
-
-}
-
-static void
-gst_debugserver_send_pad_dynamic_info (GstDebugserverTracer * debugserver, GSocketConnection * client, const 
gchar * pad_path)
-{
-  gint size;
-  GstPad *pad = gst_utils_get_pad_from_path (GST_ELEMENT_CAST (debugserver->pipeline), pad_path);
-  SAFE_PREPARE_BUFFER_INIT (1024);
-
-  if (pad == NULL) {
-    gst_debugserver_handle_error (debugserver, client, "Cannot find pad for sending dynamic info");
-    return;
-  }
-
-  SAFE_PREPARE_BUFFER (
-    gst_debugserver_pad_prepare_dynamic_info_buffer (pad, m_buff, max_m_buff_size), size);
-
-  gst_debugserver_tcp_send_packet (debugserver->tcp_server, client, m_buff, size);
-  SAFE_PREPARE_BUFFER_CLEAN;
-}
-
-static void
-gst_debugserver_tracer_send_categories (GstDebugserverTracer * debugserver, gpointer client_id)
-{
-  gint size;
-  GSocketConnection *connection = (GSocketConnection*) client_id;
-  SAFE_PREPARE_BUFFER_INIT (1024);
-  SAFE_PREPARE_BUFFER (gst_debugserver_log_prepare_categories_buffer (m_buff, max_m_buff_size), size);
-  gst_debugserver_tcp_send_packet (debugserver->tcp_server, connection,
-    m_buff, size);
-  SAFE_PREPARE_BUFFER_CLEAN;
-}
-
-static void
-gst_debugserver_tracer_send_factory (GstDebugserverTracer * debugserver, gpointer client_id, const gchar * 
factory_name)
-{
-  gint size;
-  GstElementFactory *factory = gst_element_factory_find (factory_name);
-  if (factory == NULL) {
-    gchar *msg = g_strdup_printf ("Cannot find factory %s", factory_name);
-    gst_debugserver_handle_error (debugserver, client_id, msg);
-    g_free (msg);
-    return;
-  }
-  GSocketConnection *connection = (GSocketConnection*) client_id;
-  SAFE_PREPARE_BUFFER_INIT (1024);
-  SAFE_PREPARE_BUFFER (gst_debugserver_factory_prepare_buffer (factory, m_buff, max_m_buff_size), size);
-  gst_debugserver_tcp_send_packet (debugserver->tcp_server, connection,
-    m_buff, size);
-  SAFE_PREPARE_BUFFER_CLEAN;
-
-  gst_object_unref (factory);
-}
-
-static void
-gst_debugserver_tracer_client_disconnected (gpointer client_id, gpointer user_data)
-{
-  GstDebugserverTracer *debugserver = GST_DEBUGSERVER_TRACER (user_data);
-
-  gst_debugserver_log_set_watch (debugserver->log_handler, FALSE, client_id);
-  gst_debugserver_qe_remove_client (debugserver->event_handler, client_id);
-  gst_debugserver_qe_remove_client (debugserver->query_handler, client_id);
-  gst_debugserver_buffer_remove_client (debugserver->buffer_handler, client_id);
-  gst_debugserver_message_remove_client (debugserver->msg_handler, client_id);
-}
-
-static void
-gst_debugserver_tracer_client_connected (gpointer client_id, gpointer user_data)
-{
-  GstDebugserverTracer *debugserver = GST_DEBUGSERVER_TRACER (user_data);
-
-  gst_debugserver_topology_send_entire_topology (
-    GST_BIN (debugserver->pipeline), debugserver->tcp_server, client_id);
-
-  gst_debugserver_send_enum (debugserver, client_id, "GstQueryType");
-
-  gst_debugserver_send_enum (debugserver, client_id, "GstEventType");
-
-  gst_debugserver_send_flag (debugserver, client_id, "GstMessageType");
-
-  gst_debugserver_tracer_send_categories (debugserver, client_id);
-}
-
-static gint
-gst_debugserver_prepare_property (const gchar * element_path, const GstElement *element, const GParamSpec 
*param, gchar * buffer, gint max_size)
-{
-  GValue value = {0};
-  GstreamerInfo info = GSTREAMER_INFO__INIT;
-  Property property = PROPERTY__INIT;
-  info.info_type = GSTREAMER_INFO__INFO_TYPE__PROPERTY;
-  gint size;
-  GType tmptype;
-  InternalGType internal_type;
-
-  g_value_init (&value, param->value_type);
-  g_object_get_property (G_OBJECT (element), param->name, &value);
-
-  property.element_path = (gchar*) element_path;
-  property.property_name = (gchar*) param->name;
-  property.property_value = g_value_serialize (&value, &tmptype, &internal_type);
-  property.internal_type = internal_type;
-  property.has_internal_type = TRUE;
-  property.type = tmptype;
-  property.has_type = TRUE;
-  property.type_name = (gchar*) g_type_name (value.g_type);
-  property.description = (gchar*) g_param_spec_get_blurb ((GParamSpec*) param);
-  property.has_flags = TRUE;
-  property.flags = param->flags;
-  info.property = &property;
-  size = gstreamer_info__get_packed_size (&info);
-
-  if (size > max_size) {
-    goto finalize;
-   }
-  gstreamer_info__pack (&info, (guint8*)buffer);
-
-finalize:
-  return size;
-}
-
-static void
-gst_debugserver_property_send_single_property (GstDebugserverTracer * server, GSocketConnection * client_id,
-  const gchar * element_path, const GstElement *element, const GParamSpec *param)
-{
-  gint size;
-  SAFE_PREPARE_BUFFER_INIT (1024);
-
-  SAFE_PREPARE_BUFFER (
-    gst_debugserver_prepare_property (element_path, element, param, m_buff, max_m_buff_size), size);
-
-  gst_debugserver_tcp_send_packet (server->tcp_server, client_id, m_buff, size);
-
-  SAFE_PREPARE_BUFFER_CLEAN;
-}
-
-static gint
-gst_debugserver_prepare_error (const gchar * message, gchar * buffer, gint max_size)
-{
-  GstreamerInfo info = GSTREAMER_INFO__INIT;
-  ServerError s_err = SERVER_ERROR__INIT;
-  gint size;
-
-  info.info_type = GSTREAMER_INFO__INFO_TYPE__SERVER_ERROR;
-  s_err.message = (gchar*) message;
-  info.server_error = &s_err;
-
-  size = gstreamer_info__get_packed_size (&info);
-
-  if (size > max_size) {
-    goto finalize;
-  }
-
-  gstreamer_info__pack (&info, (guint8*)buffer);
-
-finalize:
-  return size;
-}
-
-static void
-gst_debugserver_handle_error (GstDebugserverTracer *server, GSocketConnection * client_id, const gchar * 
message)
-{
-  gint size;
-  SAFE_PREPARE_BUFFER_INIT (1024);
-
-  GST_WARNING_OBJECT (server, "%s", message);
-
-  SAFE_PREPARE_BUFFER (
-    gst_debugserver_prepare_error (message, m_buff, max_m_buff_size), size);
-
-  gst_debugserver_tcp_send_packet (server->tcp_server, client_id, m_buff, size);
-
-  SAFE_PREPARE_BUFFER_CLEAN;
-}
-
-static void
-gst_debugserver_property_send_property (GstDebugserverTracer * server, GSocketConnection * client_id, const 
gchar * element_path, const gchar * property_name)
-{
-  GstElement *element = gst_utils_get_element_from_path (GST_ELEMENT_CAST (server->pipeline), element_path);
-
-  if (element == NULL) {
-    gst_debugserver_handle_error (server, client_id, "Cannot find element");
-    return;
-  }
-
-  GstElementClass *element_class = GST_ELEMENT_GET_CLASS (element);
-
-  if (property_name == NULL || strlen (property_name) == 0) {
-    guint num_properties, i;
-    GParamSpec **property_specs = g_object_class_list_properties
-        (G_OBJECT_GET_CLASS (element), &num_properties);
-
-    for (i = 0; i < num_properties; i++) {
-      gst_debugserver_property_send_single_property (server, client_id, element_path, element, 
property_specs[i]);
-    }
-
-    g_free (property_specs);
-  } else {
-    GParamSpec *param = g_object_class_find_property ((GObjectClass *)element_class, property_name);
-    if (param == NULL) {
-      gst_debugserver_handle_error (server, client_id, "Cannot find property");
-      return;
-    }
-    gst_debugserver_property_send_single_property (server, client_id, element_path, element, param);
-  }
-}
-
-static void
-gst_debugserver_tracer_process_pad_watch_command (GstDebugserverTracer* debugserver, PadWatch *watch, 
gpointer client_id)
+do_pad_push_pre (GstTracer * self, guint64 ts, GstPad * pad, GstBuffer * buffer)
 {
-  gint size;
-  gchar buff[1024];
-
-  switch (watch->watch_type) {
-  case PAD_WATCH__WATCH_TYPE__EVENT:
-  case PAD_WATCH__WATCH_TYPE__QUERY:
-    if (gst_debugserver_qe_set_watch (
-            watch->watch_type == PAD_WATCH__WATCH_TYPE__EVENT ?  debugserver->event_handler : 
debugserver->query_handler,
-            watch->toggle == TOGGLE__ENABLE,
-            gst_utils_get_pad_from_path (GST_ELEMENT (debugserver->pipeline), watch->pad_path),
-            watch->qe_type, client_id)) {
-      size = gst_debugserver_qeb_prepare_confirmation_buffer (watch->pad_path,
-          watch->qe_type, watch->toggle, buff, 1024, watch->watch_type);
-      gst_debugserver_tcp_send_packet (debugserver->tcp_server, client_id,
-          buff, size);
-      }
-      break;
-  case PAD_WATCH__WATCH_TYPE__BUFFER:
-    if (gst_debugserver_buffer_set_watch (debugserver->buffer_handler,
-          watch->toggle == TOGGLE__ENABLE,
-          gst_utils_get_pad_from_path (GST_ELEMENT (debugserver->pipeline), watch->pad_path),
-          client_id)) {
-      size = gst_debugserver_qeb_prepare_confirmation_buffer (watch->pad_path,
-          -1, watch->toggle, buff, 1024, PAD_WATCH__WATCH_TYPE__BUFFER);
-      gst_debugserver_tcp_send_packet (debugserver->tcp_server, client_id,
-          buff, size);
-    }
-    break;
-  default:
-    break;
-  }
 }
 
 static void
-gst_debugserver_tracer_process_command (Command * cmd, gpointer client_id,
-  gpointer user_data)
+gst_debugserver_tracer_client_disconnected (TcpClient * client, gpointer user_data)
 {
-  gchar buff[1024];
-  gint size;
-  GstDebugserverTracer *debugserver = GST_DEBUGSERVER_TRACER (user_data);
+  GstDebugserverTracer *self = GST_DEBUGSERVER_TRACER (user_data);
 
-  switch (cmd->command_type) {
-  case COMMAND__COMMAND_TYPE__LOG_THRESHOLD:
-    gst_debug_set_threshold_from_string (cmd->log_threshold->list, cmd->log_threshold->overwrite);
-    break;
-  case COMMAND__COMMAND_TYPE__MESSAGE_WATCH:
-    if (gst_debugserver_message_set_watch (debugserver->msg_handler,
-          cmd->message_watch->toggle == TOGGLE__ENABLE,
-          cmd->message_watch->message_type, client_id)) {
-      size = gst_debugserver_message_prepare_confirmation_buffer (cmd->message_watch,
-        buff, 1024);
-      gst_debugserver_tcp_send_packet (debugserver->tcp_server, client_id,
-        buff, size);
-    }
-    break;
-  case COMMAND__COMMAND_TYPE__LOG_WATCH:
-    gst_debugserver_log_set_watch (debugserver->log_handler,
-          cmd->log_watch->toggle == TOGGLE__ENABLE, client_id);
-    break;
-  case COMMAND__COMMAND_TYPE__PAD_WATCH:
-    gst_debugserver_tracer_process_pad_watch_command (debugserver, cmd->pad_watch, client_id);
-    break;
-  case COMMAND__COMMAND_TYPE__DEBUG_CATEGORIES:
-      gst_debugserver_tracer_send_categories (debugserver, client_id);
-      break;
-  case COMMAND__COMMAND_TYPE__FACTORY:
-      gst_debugserver_tracer_send_factory (debugserver, client_id, cmd->factory_name);
-      break;
-  case COMMAND__COMMAND_TYPE__TOPOLOGY:
-    gst_debugserver_topology_send_entire_topology (GST_BIN (debugserver->pipeline), debugserver->tcp_server, 
client_id);
-    break;
-  case COMMAND__COMMAND_TYPE__PROPERTY:
-    if (cmd->property->has_type == FALSE) {
-      gst_debugserver_property_send_property (debugserver, client_id, cmd->property->element_path, 
cmd->property->property_name);
-    } else {
-      GValue val = G_VALUE_INIT;
-      GstElement *element = gst_utils_get_element_from_path (GST_ELEMENT_CAST (debugserver->pipeline), 
cmd->property->element_path);
-      g_value_deserialize (&val, cmd->property->type, cmd->property->internal_type, 
cmd->property->property_value);
-      g_object_set_property (G_OBJECT (element), cmd->property->property_name, &val);
-      g_value_unset (&val);
-    }
-    break;
-  case COMMAND__COMMAND_TYPE__ENUM_TYPE:
-    gst_debugserver_send_enum_flags (debugserver, client_id, cmd->enum_name);
-    break;
-  case COMMAND__COMMAND_TYPE__PAD_DYNAMIC_INFO:
-      gst_debugserver_send_pad_dynamic_info (debugserver, client_id, cmd->pad_path);
-      break;
-  default:
-    GST_WARNING_OBJECT (debugserver, "Unsupported command type %d", cmd->command_type);
-  }
+  gst_debugserver_log_remove_client (self->log, client);
+  gst_debugserver_message_remove_client (self->message, client);
+  gst_debugserver_qe_remove_client (self->event, client);
+  gst_debugserver_qe_remove_client (self->query, client);
 }
 
 static void
@@ -694,31 +192,52 @@ gst_debugserver_tracer_class_init (GstDebugserverTracerClass * klass)
 }
 
 static void
-gst_debugserver_tracer_log_function (GstDebugCategory * category,
-    GstDebugLevel level, const gchar * file, const gchar * function, gint line,
-    GObject * object, GstDebugMessage * message, gpointer user_data)
+gst_debugserver_tracer_send_property (GstDebugserverTcp * tcp_server, TcpClient * client, GParamSpec * spec, 
GstElement * element)
 {
-  GstDebugserverTracer *debugserver = GST_DEBUGSERVER_TRACER (user_data);
-  GSocketConnection *connection;
-  GSList *clients = gst_debugserver_log_get_clients (debugserver->log_handler);
-  gsize size;
-  SAFE_PREPARE_BUFFER_INIT (1024);
+  GstDebugger__GStreamerData gst_data = GST_DEBUGGER__GSTREAMER_DATA__INIT;
+  GstDebugger__PropertyInfo property = GST_DEBUGGER__PROPERTY_INFO__INIT;
+  GstDebugger__Value value = GST_DEBUGGER__VALUE__INIT;
+  GType out_gtype;
+  InternalGType out_internal_type;
+  GValue gvalue = G_VALUE_INIT;
+  gchar *object = gst_utils_get_object_path (GST_OBJECT_CAST (element));
+  gchar *serialized_data = NULL;
 
-  if (clients == NULL) {
+  if (spec == NULL) {
     return;
   }
 
-  SAFE_PREPARE_BUFFER (gst_debugserver_log_prepare_buffer (category, level, file, function,
-    line, object, message, m_buff, max_m_buff_size), size);
+  property.blurb = (gchar*) g_param_spec_get_blurb (spec);
+  property.flags = spec->flags;
+  property.name = (gchar*) g_param_spec_get_name (spec);
+  property.nick = (gchar*) g_param_spec_get_nick (spec);
+  property.object = (gchar*) object;
+
+  g_value_init (&gvalue, spec->value_type);
+  g_object_get_property (G_OBJECT (element), g_param_spec_get_name (spec), &gvalue);
+
+  serialized_data = g_value_serialize (&gvalue, &out_gtype, &out_internal_type);
 
-  while (clients != NULL) {
-    connection = (GSocketConnection*)clients->data;
-    gst_debugserver_tcp_send_packet (debugserver->tcp_server, connection,
-      m_buff, size);
-    clients = clients->next;
+  value.data.data = serialized_data;
+  value.data.len = serialized_data == NULL ? 0 : strlen (serialized_data);
+  value.gtype = out_gtype;
+
+  if (out_gtype == spec->value_type) {
+    value.internal_type = out_internal_type;
+    value.has_internal_type = TRUE;
+  } else {
+    value.has_internal_type = FALSE;
   }
 
-  SAFE_PREPARE_BUFFER_CLEAN;
+  property.value = &value;
+  gst_data.property_info = &property;
+  gst_data.info_type_case = GST_DEBUGGER__GSTREAMER_DATA__INFO_TYPE_PROPERTY_INFO;
+
+  gst_debugserver_tcp_send_packet (tcp_server, client, &gst_data);
+
+  g_value_unset (&gvalue);
+  g_free (serialized_data);
+  g_free (object);
 }
 
 static void
@@ -726,13 +245,22 @@ gst_debugserver_tracer_init (GstDebugserverTracer * self)
 {
   GstTracer *tracer = GST_TRACER (self);
 
-  self->pipeline = NULL;
   self->port = DEFAULT_PORT;
-  self->msg_handler = gst_debugserver_message_new ();
-  self->log_handler = gst_debugserver_log_new ();
-  self->event_handler = gst_debugserver_qe_new ();
-  self->query_handler = gst_debugserver_qe_new ();
-  self->buffer_handler = gst_debugserver_buffer_new ();
+
+  self->log = gst_debugserver_log_new ();
+  gst_debug_add_log_function (gst_debugserver_log_handler, self, NULL);
+
+  self->tcp_server = gst_debugserver_tcp_new ();
+  self->tcp_server->command_handler = gst_debugserver_command_handler;
+  self->tcp_server->client_disconnected_handler = gst_debugserver_tracer_client_disconnected;
+  self->tcp_server->owner = self;
+  gst_debugserver_tcp_start_server (self->tcp_server, self->port);
+
+  self->message = gst_debugserver_message_new ();
+
+  self->event = gst_debugserver_qe_new ();
+
+  self->query = gst_debugserver_qe_new ();
 
   gst_tracing_register_hook (tracer, "element-new",
       G_CALLBACK (do_element_new));
@@ -754,52 +282,36 @@ gst_debugserver_tracer_init (GstDebugserverTracer * self)
       G_CALLBACK (do_pad_link_post));
   gst_tracing_register_hook (tracer, "pad-unlink-post",
       G_CALLBACK (do_pad_unlink_post));
-
-  gst_debug_add_log_function (gst_debugserver_tracer_log_function, self, NULL);
-
-  self->tcp_server = gst_debugserver_tcp_new ();
-  self->tcp_server->process_command = gst_debugserver_tracer_process_command;
-  self->tcp_server->process_command_user_data = self;
-  self->tcp_server->client_disconnected = gst_debugserver_tracer_client_disconnected;
-  self->tcp_server->parent = self;
-  self->tcp_server->client_connected = gst_debugserver_tracer_client_connected;
-  gst_debugserver_tcp_start_server (self->tcp_server, self->port);
 }
 
 static void
 gst_debugserver_tracer_finalize (GObject * obj)
 {
-  GstDebugserverTracer *debugserver = GST_DEBUGSERVER_TRACER (obj);
+  GstDebugserverTracer *self = GST_DEBUGSERVER_TRACER (obj);
 
-  gst_debug_remove_log_function (gst_debugserver_tracer_log_function);
+  gst_object_unref (GST_DEBUGSERVER_TCP (self->tcp_server));
 
-  gst_debugserver_tracer_close_connection (debugserver);
-
-  gst_debugserver_message_free (debugserver->msg_handler);
-  gst_debugserver_log_free (debugserver->log_handler);
-  gst_debugserver_qe_free (debugserver->event_handler);
-  gst_debugserver_qe_free (debugserver->query_handler);
- // gst_debugserver_buffer_free (debugserver->buffer_handler);
-
-  g_object_unref (G_OBJECT (debugserver->tcp_server));
+  gst_debug_remove_log_function (gst_debugserver_log_handler);
+  gst_debugserver_log_free (self->log);
+  gst_debugserver_message_free (self->message);
+  gst_debugserver_qe_free (self->event);
+  gst_debugserver_qe_free (self->query);
 }
 
 static void
 gst_debugserver_tracer_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec)
 {
-  GstDebugserverTracer *debugserver;
+  GstDebugserverTracer *self = GST_DEBUGSERVER_TRACER (object);
   gint tmp_port;
 
-  debugserver = GST_DEBUGSERVER_TRACER (object);
-
   switch (prop_id) {
     case PROP_PORT:
       tmp_port = g_value_get_int (value);
-      if (tmp_port != debugserver->port) {
-        debugserver->port = g_value_get_int (value);
-        gst_debugserver_tracer_close_connection (debugserver);
-        gst_debugserver_tcp_start_server (debugserver->tcp_server, debugserver->port);
+      if (tmp_port != self->port) {
+        self->port = g_value_get_int (value);
+        gst_debugserver_tcp_stop_server (self->tcp_server);
+        gst_debugserver_tcp_start_server (self->tcp_server, self->port);
       }
       break;
     default:
@@ -826,6 +338,106 @@ gst_debugserver_tracer_get_property (GObject * object, guint prop_id,
   }
 }
 
+static void gst_debugserver_process_pad_watch (GstDebugserverTracer * self, GstDebugger__Command * command, 
TcpClient * client)
+{
+  GstDebugger__PadWatchRequest *request = command->pad_watch;
+  GstPad *pad = gst_utils_get_pad_from_path (GST_ELEMENT_CAST (self->pipeline), request->pad);
+
+  switch (request->pad_watch_type_case)
+  {
+  case GST_DEBUGGER__PAD_WATCH_REQUEST__PAD_WATCH_TYPE_EVENT:
+    if (gst_debugserver_qe_set_watch (self->event, request->action == GST_DEBUGGER__ACTION__ADD, 
request->event->type, pad, request->pad, client)) {
+      GstDebugger__GStreamerData data = GST_DEBUGGER__GSTREAMER_DATA__INIT;
+      data.confirmation = command;
+      data.info_type_case = GST_DEBUGGER__GSTREAMER_DATA__INFO_TYPE_CONFIRMATION;
+      gst_debugserver_tcp_send_packet (self->tcp_server, client, &data);
+    }
+    break;
+  case GST_DEBUGGER__PAD_WATCH_REQUEST__PAD_WATCH_TYPE_QUERY:
+    if (gst_debugserver_qe_set_watch (self->query, request->action == GST_DEBUGGER__ACTION__ADD, 
request->query->type, pad, request->pad, client)) {
+      GstDebugger__GStreamerData data = GST_DEBUGGER__GSTREAMER_DATA__INIT;
+      data.confirmation = command;
+      data.info_type_case = GST_DEBUGGER__GSTREAMER_DATA__INFO_TYPE_CONFIRMATION;
+      gst_debugserver_tcp_send_packet (self->tcp_server, client, &data);
+    }
+    break;
+  }
+}
+
+static void gst_debugserver_send_single_property (GstDebugserverTracer * self, TcpClient * client, 
GstElement * element, const gchar * name)
+{
+  GParamSpec *spec = g_object_class_find_property (G_OBJECT_CLASS (GST_ELEMENT_GET_CLASS (element)), name);
+
+  gst_debugserver_tracer_send_property (self->tcp_server, client, spec, element);
+}
+
+static void gst_debugserver_process_property_request (GstDebugserverTracer * self, TcpClient * client,
+  GstDebugger__PropertyRequest * request)
+{
+  GstElement * element = gst_utils_get_element_from_path (GST_ELEMENT_CAST (self->pipeline), 
request->object);
+  gint n_properties, i;
+  GParamSpec **spec;
+
+  if (element == NULL) {
+    return;
+  }
+
+  if (request->name == NULL || request->name[0] == '\0') {
+    spec = g_object_class_list_properties (G_OBJECT_CLASS (GST_ELEMENT_GET_CLASS (element)), &n_properties);
+
+    for (i = 0; i < n_properties; i++) {
+      gst_debugserver_send_single_property (self, client, element, spec[i]->name);
+    }
+  } else {
+    gst_debugserver_send_single_property (self, client, element, request->name);
+  }
+}
+
+static void gst_debugserver_command_handler (GstDebugger__Command * command,
+    gpointer debugtracer, TcpClient * client)
+{
+  GstDebugserverTracer *self = GST_DEBUGSERVER_TRACER (debugtracer);
+  GstDebugserverTcp * tcp = self->tcp_server;
+
+  switch (command->command_type_case) {
+  case GST_DEBUGGER__COMMAND__COMMAND_TYPE_TYPE_DESCRIPTION:
+    gst_debugserver_types_send_type (tcp, client, command->type_description);
+    break;
+  case GST_DEBUGGER__COMMAND__COMMAND_TYPE_DEBUG_CATEGORIES_LIST:
+    gst_debugserver_log_send_debug_categories (tcp, client);
+    break;
+  case GST_DEBUGGER__COMMAND__COMMAND_TYPE_LOG_THRESHOLD:
+    gst_debugserver_log_set_threshold (command->log_threshold);
+    break;
+  case GST_DEBUGGER__COMMAND__COMMAND_TYPE_MESSAGE:
+    if (gst_debugserver_message_set_watch (self->message, client, command->message)) {
+      GstDebugger__GStreamerData data = GST_DEBUGGER__GSTREAMER_DATA__INIT;
+      data.confirmation = command;
+      data.info_type_case = GST_DEBUGGER__GSTREAMER_DATA__INFO_TYPE_CONFIRMATION;
+      gst_debugserver_tcp_send_packet (self->tcp_server, client, &data);
+    }
+    break;
+  case GST_DEBUGGER__COMMAND__COMMAND_TYPE_LOG:
+    if (gst_debugserver_log_set_watch (self->log, command->log->action == GST_DEBUGGER__ACTION__ADD,
+          command->log->level, command->log->category, client)) {
+      GstDebugger__GStreamerData data = GST_DEBUGGER__GSTREAMER_DATA__INIT;
+      data.confirmation = command;
+      data.info_type_case = GST_DEBUGGER__GSTREAMER_DATA__INFO_TYPE_CONFIRMATION;
+      gst_debugserver_tcp_send_packet (self->tcp_server, client, &data);
+    }
+    break;
+  case GST_DEBUGGER__COMMAND__COMMAND_TYPE_PAD_WATCH:
+    gst_debugserver_process_pad_watch (self, command, client);
+    break;
+  case GST_DEBUGGER__COMMAND__COMMAND_TYPE_ENTIRE_TOPOLOGY:
+    gst_debugserver_topology_send_entire_topology (GST_BIN_CAST (self->pipeline), self->tcp_server, client);
+    break;
+  case GST_DEBUGGER__COMMAND__COMMAND_TYPE_PROPERTY:
+    gst_debugserver_process_property_request (self, client, command->property);
+    break;
+  }
+}
+
 static gboolean
 plugin_init (GstPlugin * plugin)
 {
diff --git a/src/debugserver/gstdebugserver.h b/src/debugserver/gstdebugserver.h
index 5296457..fc35572 100644
--- a/src/debugserver/gstdebugserver.h
+++ b/src/debugserver/gstdebugserver.h
@@ -24,9 +24,8 @@
 #define __GST_DEBUGSERVER_TRACER_H__
 
 #include "gstdebugservertcp.h"
-#include "gstdebugservermessage.h"
 #include "gstdebugserverlog.h"
-#include "gstdebugserverbuffer.h"
+#include "gstdebugservermessage.h"
 #include "gstdebugserverqe.h"
 
 #include <gst/gst.h>
@@ -60,14 +59,13 @@ struct _GstDebugserverTracer {
   GstTracer     parent;
 
   /*< private >*/
+  GstPipeline *pipeline;
   gint port;
-  GstPipeline * pipeline;
-  GstDebugserverTcp * tcp_server;
-  GstDebugserverMessage * msg_handler;
-  GstDebugserverLog * log_handler;
-  GstDebugserverQE * event_handler;
-  GstDebugserverQE * query_handler;
-  GstDebugserverBuffer * buffer_handler;
+  GstDebugserverTcp *tcp_server;
+  GstDebugserverLog *log;
+  GstDebugserverMessage *message;
+  GstDebugserverQE *event;
+  GstDebugserverQE *query;
 };
 
 struct _GstDebugserverTracerClass {
diff --git a/src/debugserver/gstdebugserverlog.c b/src/debugserver/gstdebugserverlog.c
index 13a5a9f..9d33fe9 100644
--- a/src/debugserver/gstdebugserverlog.c
+++ b/src/debugserver/gstdebugserverlog.c
@@ -22,64 +22,122 @@
 
 #include <string.h>
 
+typedef struct {
+  GstDebugLevel level;
+  gchar * category;
+} DebugWatch;
+
+static DebugWatch * debug_watch_new (GstDebugLevel level, const gchar * category)
+{
+  DebugWatch * watch = (DebugWatch *) g_malloc (sizeof (DebugWatch));
+
+  watch->level = level;
+  watch->category = g_strdup (category);
+
+  return watch;
+}
+
+static void debug_watch_free (DebugWatch * watch)
+{
+  g_free (watch->category);
+  g_free (watch);
+}
+
+static void debug_watch_list_free (gpointer ptr)
+{
+  g_slist_free_full (ptr, (GDestroyNotify) debug_watch_free);
+}
+
+static gint debug_watch_compare (gconstpointer p1, gconstpointer p2)
+{
+  const DebugWatch *w1 = p1, *w2 = p2;
+
+  if (w1->level >= w2->level && (w1->category == NULL ||
+      g_strcmp0 (w1->category, w2->category) == 0)) {
+    return 0;
+  } else {
+    return 1;
+  }
+}
+
+static gboolean gst_debugserver_log_ok (GstDebugger__GStreamerData* original, gpointer new_ptr)
+{
+  GstDebugger__LogInfo* info = original->log_info;
+  GSList *list = new_ptr;
+  DebugWatch watch = { info->level, info->category };
+
+  return g_slist_find_custom (list, &watch, debug_watch_compare) != NULL;
+}
+
 GstDebugserverLog * gst_debugserver_log_new (void)
 {
   GstDebugserverLog *log = (GstDebugserverLog*)g_malloc (sizeof(GstDebugserverLog));
-  log->clients = NULL;
+  gst_debugserver_watcher_init (&log->watcher, gst_debugserver_log_ok, (GDestroyNotify) 
debug_watch_list_free, debug_watch_compare);
 
   return log;
 }
 
 void gst_debugserver_log_free (GstDebugserverLog * log)
 {
-  g_slist_free (log->clients);
+  gst_debugserver_log_clean (log);
+  gst_debugserver_watcher_deinit (&log->watcher);
   g_free (log);
 }
 
-void gst_debugserver_log_set_watch (GstDebugserverLog * log, gboolean enable,
-  gpointer client_info)
+void gst_debugserver_log_clean (GstDebugserverLog * log)
+{
+  gst_debugserver_watcher_clean (&log->watcher);
+}
+
+static gboolean gst_debugserver_log_add_watch (GstDebugserverLog * log, gint level,
+  const gchar * category, TcpClient * client)
 {
-  if (enable == TRUE) {
-    if (g_slist_find (log->clients, client_info) == NULL) {
-      log->clients = g_slist_append (log->clients, client_info);
-    }
+  DebugWatch *w = debug_watch_new (level, category);
+  if (gst_debugserver_watcher_add_watch (&log->watcher, w, client) == TRUE) {
+    return TRUE;
   } else {
-    log->clients = g_slist_remove (log->clients, client_info);
+    debug_watch_free (w);
+    return FALSE;
   }
 }
 
-GSList* gst_debugserver_log_get_clients (GstDebugserverLog * log)
+static gboolean gst_debugserver_log_remove_watch (GstDebugserverLog * log,
+  gint level, const gchar * category, TcpClient * client)
 {
-  return log->clients;
+  DebugWatch w = { level, (gchar*)category };
+
+  return gst_debugserver_watcher_remove_watch (&log->watcher, &w, client);
 }
 
-gint gst_debugserver_log_prepare_buffer (GstDebugCategory * category,
-  GstDebugLevel level, const gchar * file, const gchar * function, gint line,
-  GObject * object, GstDebugMessage * message, gchar * buffer, gint max_size)
+gboolean gst_debugserver_log_set_watch (GstDebugserverLog * log, gboolean enable,
+  gint level, const gchar * category, TcpClient * client)
 {
-  GstreamerInfo info = GSTREAMER_INFO__INIT;
-  GstreamerLog log = GSTREAMER_LOG__INIT;
-  gint size;
+  if (enable) {
+    return gst_debugserver_log_add_watch (log, level, category, client);
+  } else {
+    return gst_debugserver_log_remove_watch (log, level, category, client);
+  }
+}
 
-  log.level = (gint)level;
-  log.category_name = (gchar*) gst_debug_category_get_name (category);
-  log.file = (gchar*) file;
-  log.function = (gchar*) function;
-  log.line = line;
-  log.object_path = "todo";
-  log.message = (gchar*) gst_debug_message_get (message);
-  info.info_type = GSTREAMER_INFO__INFO_TYPE__LOG;
-  info.log = &log;
-  size = gstreamer_info__get_packed_size (&info);
+void gst_debugserver_log_send_log (GstDebugserverLog * log, GstDebugserverTcp * tcp_server,
+  GstDebugCategory * category, GstDebugLevel level, const gchar * file, const gchar * function,
+  gint line, GObject * object, GstDebugMessage * message)
+{
+  GstDebugger__GStreamerData gst_data = GST_DEBUGGER__GSTREAMER_DATA__INIT;
+  GstDebugger__LogInfo log_info = GST_DEBUGGER__LOG_INFO__INIT;
 
-  if (max_size < size) {
-    goto finalize;
-  }
+  log_info.level = (gint)level;
+  log_info.category = (gchar*) gst_debug_category_get_name (category);
+  log_info.file = (gchar*) file;
+  log_info.function = (gchar*) function;
+  log_info.line = line;
+  log_info.object = "todo";
+  log_info.message = (gchar*) gst_debug_message_get (message);
 
-  gstreamer_info__pack (&info, (guint8*)buffer);
+  gst_data.info_type_case = GST_DEBUGGER__GSTREAMER_DATA__INFO_TYPE_LOG_INFO;
+  gst_data.log_info = &log_info;
 
-finalize:
-  return size;
+  gst_debugserver_watcher_send_data (&log->watcher, tcp_server, &gst_data);
 }
 
 static gint
@@ -89,41 +147,43 @@ sort_by_category_name (gconstpointer a, gconstpointer b)
       gst_debug_category_get_name ((GstDebugCategory *) b));
 }
 
-gint gst_debugserver_log_prepare_categories_buffer (gchar * buffer, gint max_size)
+void gst_debugserver_log_send_debug_categories (GstDebugserverTcp *tcp_server, TcpClient *client)
 {
+  GstDebugger__GStreamerData gst_data = GST_DEBUGGER__GSTREAMER_DATA__INIT;
+  GstDebugger__DebugCategories debug_categories = GST_DEBUGGER__DEBUG_CATEGORIES__INIT;
+  gint categories_count, i = 0;
+
+  gst_data.info_type_case = GST_DEBUGGER__GSTREAMER_DATA__INFO_TYPE_DEBUG_CATEGORIES;
+
   GSList *tmp, *all_categories = gst_debug_get_all_categories ();
-  GString *categories = g_string_new (NULL);
-  GstreamerInfo info = GSTREAMER_INFO__INIT;
-  DebugCategoryList category_list = DEBUG_CATEGORY_LIST__INIT;
-  gint size;
 
   tmp = all_categories = g_slist_sort (all_categories, sort_by_category_name);
+  categories_count = g_slist_length (all_categories);
+
+  debug_categories.n_category = categories_count;
+  debug_categories.category = (char **) g_malloc (sizeof (char*) * categories_count);
 
   while (tmp) {
     GstDebugCategory *cat = (GstDebugCategory *) tmp->data;
-    g_string_append (categories, gst_debug_category_get_name (cat));
-    g_string_append_c (categories, ';');
+    debug_categories.category[i++] = (char *) gst_debug_category_get_name (cat);
     tmp = g_slist_next (tmp);
   }
+  g_slist_free (all_categories);
 
-  category_list.list = g_string_free (categories, FALSE);
-  info.info_type = GSTREAMER_INFO__INFO_TYPE__DEBUG_CATEGORIES;
-  info.debug_categories = &category_list;
-  size = gstreamer_info__get_packed_size (&info);
-  if (size > max_size) {
-    goto finalize;
-  }
-  gstreamer_info__pack (&info, (guint8*)buffer);
+  gst_data.debug_categories = &debug_categories;
 
-finalize:
-  g_slist_free (all_categories);
+  gst_debugserver_tcp_send_packet (tcp_server, client, &gst_data);
 
-  return size;
+  g_free (debug_categories.category);
+}
 
+void gst_debugserver_log_set_threshold (const gchar * threshold)
+{
+  gst_debug_set_threshold_from_string (threshold, TRUE);
 }
 
-void gst_debugserver_log_clean (GstDebugserverLog * log)
+void gst_debugserver_log_remove_client (GstDebugserverLog * log,
+  TcpClient * client)
 {
-  g_slist_free (log->clients);
-  log->clients = NULL;
+  g_hash_table_remove (log->watcher.clients, client);
 }
diff --git a/src/debugserver/gstdebugserverlog.h b/src/debugserver/gstdebugserverlog.h
index a7f5fe7..1b4cbef 100644
--- a/src/debugserver/gstdebugserverlog.h
+++ b/src/debugserver/gstdebugserverlog.h
@@ -20,34 +20,38 @@
 #ifndef __GST_DEBUGSERVER_LOG_H__
 #define __GST_DEBUGSERVER_LOG_H__
 
+#include "gstdebugserverwatcher.h"
+
 #include <gst/gst.h>
-#include <glib.h>
 
 G_BEGIN_DECLS
 
 typedef struct _GstDebugserverLog GstDebugserverLog;
 
 struct _GstDebugserverLog {
-  GSList *clients;
+  GstDebugserverWatcher watcher;
 };
 
 GstDebugserverLog * gst_debugserver_log_new (void);
 
 void gst_debugserver_log_free (GstDebugserverLog * log);
 
-gint gst_debugserver_log_prepare_buffer (GstDebugCategory * category,
-  GstDebugLevel level, const gchar * file, const gchar * function, gint line,
-  GObject * object, GstDebugMessage * message, gchar * buffer, gint max_size);
+void gst_debugserver_log_send_log (GstDebugserverLog * log, GstDebugserverTcp * tcp_server,
+  GstDebugCategory * category, GstDebugLevel level, const gchar * file, const gchar * function,
+  gint line, GObject * object, GstDebugMessage * message);
 
-GSList* gst_debugserver_log_get_clients (GstDebugserverLog * log);
+gboolean gst_debugserver_log_set_watch (GstDebugserverLog * log, gboolean enable, gint level,
+  const gchar * category, TcpClient * client);
 
-void gst_debugserver_log_set_watch (GstDebugserverLog * log, gboolean enable,
-  gpointer client_info);
+void gst_debugserver_log_send_debug_categories (GstDebugserverTcp *tcp_server, TcpClient *client);
 
-gint gst_debugserver_log_prepare_categories_buffer (gchar * buffer, gint max_size);
+void gst_debugserver_log_set_threshold (const gchar * threshold);
 
 void gst_debugserver_log_clean (GstDebugserverLog * log);
 
+void gst_debugserver_log_remove_client (GstDebugserverLog * log,
+  TcpClient * client);
+
 G_END_DECLS
 
 #endif /* __GST_DEBUGSERVER_LOG_H__ */
diff --git a/src/debugserver/gstdebugservermessage.c b/src/debugserver/gstdebugservermessage.c
index 77cc4a4..007d3f5 100644
--- a/src/debugserver/gstdebugservermessage.c
+++ b/src/debugserver/gstdebugservermessage.c
@@ -19,116 +19,84 @@
 
 #include "gstdebugservermessage.h"
 
+#include <string.h>
 #include <assert.h>
 
-GstDebugserverMessage * gst_debugserver_message_new (void)
+static gint g_int_cmp (gconstpointer v1, gconstpointer v2)
 {
-  GstDebugserverMessage *msg = (GstDebugserverMessage*)g_malloc (sizeof(GstDebugserverMessage));
-  msg->clients = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
-    (GDestroyNotify) g_slist_free);
-
-  return msg;
-}
-
-void gst_debugserver_message_free (GstDebugserverMessage * msg)
-{
-  g_hash_table_unref (msg->clients);
-  g_free (msg);
+  return GPOINTER_TO_INT (v1) != GPOINTER_TO_INT (v2);
 }
 
-gboolean gst_debugserver_message_add_watch (GstDebugserverMessage * msg,
-  GstMessageType msg_type, gpointer client_info)
+static gboolean gst_debugserver_message_ok (GstDebugger__GStreamerData* original, gpointer new_ptr)
 {
-  GSList *listeners =
-      (GSList *) g_hash_table_lookup (msg->clients, GINT_TO_POINTER (msg_type));
+  GSList *list = new_ptr;
+  GstDebugger__MessageInfo *msg = original->message_info;
 
-  if (listeners == NULL) {
-    listeners = g_slist_append (listeners, client_info);
-    g_hash_table_insert (msg->clients, GINT_TO_POINTER (msg_type), listeners);
-    return TRUE;
+  while (list) {
+    if (msg->type == GPOINTER_TO_INT (list->data) || GPOINTER_TO_INT (list->data) == GST_MESSAGE_ANY) {
+      return TRUE;
+    }
+    list = g_slist_next (list);
   }
 
-  if (g_slist_find (listeners, client_info) == NULL) {
-    listeners = g_slist_append (listeners, client_info);
-    g_hash_table_replace (msg->clients, GINT_TO_POINTER (msg_type),
-        listeners);
-    return TRUE;
-  } else {
-    return FALSE;
-  }
+  return FALSE;
 }
 
-gboolean gst_debugserver_message_remove_watch (GstDebugserverMessage * msg,
-  GstMessageType msg_type, gpointer client_info)
+GstDebugserverMessage * gst_debugserver_message_new (void)
 {
-  GSList *listeners =
-      (GSList *) g_hash_table_lookup (msg->clients, GINT_TO_POINTER (msg_type));
+  GstDebugserverMessage *msg = (GstDebugserverMessage*)g_malloc (sizeof(GstDebugserverMessage));
 
-  if (g_slist_find (listeners, client_info) == NULL) {
-    return FALSE;
-  } else {
-    listeners = g_slist_remove (listeners, client_info);
-    g_hash_table_replace (msg->clients, GINT_TO_POINTER (msg_type), listeners);
-    return TRUE;
-  }
+  gst_debugserver_watcher_init (&msg->watcher, gst_debugserver_message_ok, (GDestroyNotify) g_slist_free, 
g_int_cmp);
+
+  return msg;
 }
 
-void gst_debugserver_message_remove_client (GstDebugserverMessage * msg,
-  gpointer client_info)
+void gst_debugserver_message_free (GstDebugserverMessage * msg)
 {
-  GList * keys = g_hash_table_get_keys (msg->clients);
-
-  while (keys) {
-    gst_debugserver_message_remove_watch (msg, GPOINTER_TO_INT (keys->data), client_info);
-    keys = keys->next;
-  }
+  gst_debugserver_log_clean (msg);
+  gst_debugserver_watcher_deinit (&msg->watcher);
+  g_free (msg);
 }
 
-GSList* gst_debugserver_message_get_clients (GstDebugserverMessage * msg,
-  GstMessageType msg_type)
+void gst_debugserver_message_clean (GstDebugserverMessage * msg)
 {
-  GSList *base = (GSList *) g_hash_table_lookup (msg->clients, GINT_TO_POINTER (msg_type));
-  GSList *clients = g_slist_copy (base);
-  base = (GSList *) g_hash_table_lookup (msg->clients, GINT_TO_POINTER(GST_MESSAGE_ANY));
-
-  for (; base != NULL; base = g_slist_next (base)) {
-    if (g_slist_find (clients, base->data) == NULL) {
-      clients = g_slist_append(clients, base->data);
-    }
-  }
-
-  return clients;
+  gst_debugserver_watcher_clean (&msg->watcher);
 }
 
 gboolean gst_debugserver_message_set_watch (GstDebugserverMessage * msg,
-  gboolean enable, GstMessageType msg_type, gpointer client_info)
+  TcpClient * client, GstDebugger__MessageRequest * request)
 {
-  if (enable) {
-    return gst_debugserver_message_add_watch (msg, msg_type, client_info);
+  if (request->action == GST_DEBUGGER__ACTION__ADD) {
+    return gst_debugserver_watcher_add_watch (&msg->watcher, GINT_TO_POINTER (request->type), client);
   } else {
-    return gst_debugserver_message_remove_watch (msg, msg_type, client_info);
+    return gst_debugserver_watcher_remove_watch (&msg->watcher, GINT_TO_POINTER (request->type), client);
   }
 }
 
-gint gst_debugserver_message_prepare_confirmation_buffer (MessageWatch *watch,
-  gchar * buffer, gint max_size)
+void gst_debugserver_message_remove_client (GstDebugserverMessage * msg,
+  TcpClient * client)
 {
-  GstreamerInfo info = GSTREAMER_INFO__INIT;
-  gint size;
-  MessageWatch msg_watch = MESSAGE_WATCH__INIT;
-
-  info.info_type = GSTREAMER_INFO__INFO_TYPE__MESSAGE_CONFIRMATION;
-  msg_watch.message_type = watch->message_type;
-  msg_watch.toggle = watch->toggle;
-  info.bus_msg_confirmation = &msg_watch;
-  size = gstreamer_info__get_packed_size (&info);
-  assert(size <= max_size);
-  gstreamer_info__pack (&info, (guint8*)buffer);
-
-  return size;
+  g_hash_table_remove (msg->watcher.clients, client);
 }
 
-void gst_debugserver_message_clean (GstDebugserverMessage * msg)
+
+void gst_debugserver_message_send_message (GstDebugserverMessage * msg, GstDebugserverTcp * tcp_server,
+  GstMessage * gst_msg)
 {
-  g_hash_table_remove_all (msg->clients);
+  GstDebugger__GStreamerData gst_data = GST_DEBUGGER__GSTREAMER_DATA__INIT;
+  GstDebugger__MessageInfo msg_info = GST_DEBUGGER__MESSAGE_INFO__INIT;
+  gchar *structure_data = gst_structure_to_string (gst_message_get_structure (gst_msg));
+
+  msg_info.seqnum = gst_msg->seqnum;
+  msg_info.timestamp = gst_msg->timestamp;
+  msg_info.type = gst_msg->type;
+  msg_info.structure_data.data = structure_data;
+  msg_info.structure_data.len = strlen (structure_data);
+
+  gst_data.info_type_case = GST_DEBUGGER__GSTREAMER_DATA__INFO_TYPE_MESSAGE_INFO;
+  gst_data.message_info = &msg_info;
+
+  gst_debugserver_watcher_send_data (&msg->watcher, tcp_server, &gst_data);
+
+  g_free (structure_data);
 }
diff --git a/src/debugserver/gstdebugservermessage.h b/src/debugserver/gstdebugservermessage.h
index 5a560fe..ae866fa 100644
--- a/src/debugserver/gstdebugservermessage.h
+++ b/src/debugserver/gstdebugservermessage.h
@@ -20,7 +20,8 @@
 #ifndef __GST_DEBUGSERVER_MESSAGE_H__
 #define __GST_DEBUGSERVER_MESSAGE_H__
 
-#include "common/gstdebugger.pb-c.h"
+#include "gstdebugservertcp.h"
+#include "gstdebugserverwatcher.h"
 
 #include <gst/gst.h>
 #include <glib.h>
@@ -29,35 +30,34 @@ G_BEGIN_DECLS
 
 typedef struct _GstDebugserverMessage GstDebugserverMessage;
 
-struct _GstDebugserverMessage {
+typedef struct {
   GHashTable *clients;
+
+  gboolean (*accept_client) (gpointer);
+  void (*serialize_data) (GstDebugger__GStreamerData*);
+  void (*free_data) (GstDebugger__GStreamerData*);
+  void (*compare) (gpointer, gpointer);
+} Watcher;
+
+
+struct _GstDebugserverMessage {
+  GstDebugserverWatcher watcher;
 };
 
 GstDebugserverMessage * gst_debugserver_message_new (void);
-void gst_debugserver_message_free (GstDebugserverMessage * msg);
 
-gboolean gst_debugserver_message_add_watch (GstDebugserverMessage * msg,
-  GstMessageType msg_type, gpointer client_info);
+void gst_debugserver_message_free (GstDebugserverMessage * msg);
 
-gboolean gst_debugserver_message_remove_watch (GstDebugserverMessage * msg,
-  GstMessageType msg_type, gpointer client_info);
+void gst_debugserver_message_clean (GstDebugserverMessage * msg);
 
 gboolean gst_debugserver_message_set_watch (GstDebugserverMessage * msg,
-  gboolean enable, GstMessageType msg_type, gpointer client_info);
+  TcpClient * client, GstDebugger__MessageRequest * request);
 
 void gst_debugserver_message_remove_client (GstDebugserverMessage * msg,
-  gpointer client_info);
-
-GSList* gst_debugserver_message_get_clients (GstDebugserverMessage * msg,
-  GstMessageType msg_type);
+  TcpClient * client);
 
-gint gst_debugserver_message_prepare_buffer (GstMessage * gst_msg,
-  gchar * buffer, gint max_size);
-
-gint gst_debugserver_message_prepare_confirmation_buffer (MessageWatch *msg_watch,
-  gchar * buffer, gint max_size);
-
-void gst_debugserver_message_clean (GstDebugserverMessage * msg);
+void gst_debugserver_message_send_message (GstDebugserverMessage * msg,
+  GstDebugserverTcp * tcp_server, GstMessage * gst_msg);
 
 G_END_DECLS
 
diff --git a/src/debugserver/gstdebugserverqe.c b/src/debugserver/gstdebugserverqe.c
index 8023cc6..0a82727 100644
--- a/src/debugserver/gstdebugserverqe.c
+++ b/src/debugserver/gstdebugserverqe.c
@@ -21,199 +21,147 @@
 
 #include "common/serializer.h"
 #include "common/gstdebugger.pb-c.h"
-
-#include "common/buffer-prepare-utils.h"
+#include "common/gst-utils.h"
 
 #include <string.h>
 
-GstDebugserverQE * gst_debugserver_qe_new (void)
+typedef struct _QEWatch {
+  gint qe_type;
+  GstPad * pad;
+  gchar * pad_path;
+} QEWatch;
+
+static QEWatch * qe_watch_new (gint type, GstPad * pad, gchar * pad_path)
 {
-  GstDebugserverQE *qe = (GstDebugserverQE*)g_malloc (sizeof(GstDebugserverQE));
-  qe->watches = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL);
+  QEWatch * watch = (QEWatch *) g_malloc (sizeof (QEWatch));
 
-  return qe;
-}
+  watch->qe_type = type;
+  watch->pad = pad;
+  watch->pad_path = g_strdup (pad_path);
 
-static void gst_debugserver_qe_clean_client (gpointer key, gpointer value,
-  gpointer user_data)
-{
-  g_slist_free_full (value, g_free);
+  return watch;
 }
 
-void gst_debugserver_qe_free (GstDebugserverQE * qe)
+static void qe_watch_free (QEWatch * watch)
 {
-  g_hash_table_foreach (qe->watches, gst_debugserver_qe_clean_client, NULL);
-  g_hash_table_destroy (qe->watches);
-  g_free (qe);
+  g_free (watch->pad_path);
+  g_free (watch);
 }
 
-gint gst_debugserver_qeb_prepare_confirmation_buffer (gchar * pad_path, gint qe_type,
-  gboolean toggle, gchar * buffer, gint max_size, PadWatch__WatchType type)
+static void qe_watch_list_free (gpointer ptr)
 {
-  GstreamerInfo info = GSTREAMER_INFO__INIT;
-  PadWatch pad_watch = PAD_WATCH__INIT;
-  gint size;
-  pad_watch.pad_path = pad_path;
-  pad_watch.toggle = toggle;
-  pad_watch.watch_type = type;
-  pad_watch.has_qe_type = 1;
-  pad_watch.qe_type = qe_type;
-  info.confirmation = &pad_watch;
-  info.info_type = GSTREAMER_INFO__INFO_TYPE__PAD_WATCH_CONFIRMATION;
-
-  size = gstreamer_info__get_packed_size (&info);
-  assert(size <= max_size);
-  gstreamer_info__pack (&info, (guint8*)buffer);
-  return size;
+  g_slist_free_full (ptr, (GDestroyNotify) qe_watch_free);
 }
 
-// todo improve performance (when size > max_size)
-gint gst_debugserver_qebm_prepare_buffer (GstMiniObject * miniobj, gchar *pad_path, gchar * buffer, gint 
max_size)
+static gint qe_watch_compare (gconstpointer a, gconstpointer b)
 {
-  gint size;
-  SAFE_PREPARE_BUFFER_INIT (1024);
-
-  GstreamerInfo__InfoType info_type;
-  if (GST_IS_QUERY (miniobj)) {
-    SAFE_PREPARE_BUFFER (
-      gst_query_serialize (GST_QUERY (miniobj), m_buff, max_m_buff_size), size);
-    info_type = GSTREAMER_INFO__INFO_TYPE__QUERY;
-  } else if (GST_IS_EVENT (miniobj)) {
-    SAFE_PREPARE_BUFFER (
-      gst_event_serialize (GST_EVENT (miniobj), m_buff, max_m_buff_size), size);
-    info_type = GSTREAMER_INFO__INFO_TYPE__EVENT;
-  } else if (GST_IS_MESSAGE (miniobj)) {
-    SAFE_PREPARE_BUFFER (
-      gst_message_serialize (GST_MESSAGE (miniobj), m_buff, max_m_buff_size), size);
-    info_type = GSTREAMER_INFO__INFO_TYPE__MESSAGE;
-  } else if (GST_IS_BUFFER (miniobj)) {
-    SAFE_PREPARE_BUFFER (
-      gst_buffer_serialize (GST_BUFFER (miniobj), m_buff, max_m_buff_size), size);
-    info_type = GSTREAMER_INFO__INFO_TYPE__BUFFER;
-  }
+  QEWatch *a1 = (QEWatch*) a;
+  QEWatch *b1 = (QEWatch*) b;
 
-  GstreamerInfo info = GSTREAMER_INFO__INIT;
-  GstreamerQEBM evt = GSTREAMER_QEBM__INIT;
-  evt.payload.len = size;
-  evt.pad_path = pad_path;
-  evt.payload.data = (uint8_t*) m_buff;
-  info.info_type = info_type;
-  info.qebm = &evt;
-  size = gstreamer_info__get_packed_size (&info);
-
-  if (size > max_size) {
-    goto finalize;
+  if (a1->qe_type == b1->qe_type && (g_strcmp0 (a1->pad_path, b1->pad_path) == 0 || a1->pad == NULL)) {
+    return 0;
+  } else {
+    return 1;
   }
-
-  gstreamer_info__pack (&info, (guint8*)buffer);
-
-finalize:
-  SAFE_PREPARE_BUFFER_CLEAN;
-  return size;
 }
 
-static void gst_debugserver_qe_append_client (gpointer key, gpointer value,
-  gpointer user_data)
+static gboolean gst_debugserver_qe_ok (GstDebugger__GStreamerData* original, gpointer new_ptr)
 {
-  GArray *tmp = (GArray *) user_data;
-  GSList **clients = g_array_index (tmp, GSList**, 0);
-  gint type = *g_array_index (tmp, gint*, 1);
-  GstPad *pad = g_array_index (tmp, GstPad*, 2);
-  GSList * watches = (GSList*) value;
-  QEWatch *watch;
-  gboolean pad_ok, type_ok;
-
-  while (watches != NULL) {
-    watch = (QEWatch*)watches->data;
-    pad_ok = watch->pad == NULL || watch->pad == pad;
-    type_ok = watch->qe_type == -1 || type == watch->qe_type;
-
-    if (pad_ok && type_ok) {
-      *clients = g_slist_append (*clients, key);
-      break;
-    }
-    watches = watches->next;
+  GSList *list = new_ptr;
+  QEWatch watch;
+
+  watch.pad = NULL;
+
+  if (original->event_info != NULL) {
+    watch.qe_type = original->event_info->type;
+    watch.pad_path = original->event_info->pad;
+  } else {
+    watch.qe_type = original->query_info->type;
+    watch.pad_path = original->query_info->pad;
   }
+
+  return g_slist_find_custom (list, &watch, qe_watch_compare) != NULL;
 }
 
-GSList* gst_debugserver_qe_get_clients (GstDebugserverQE * evt, GstPad * pad,
-  gint type)
+GstDebugserverQE * gst_debugserver_qe_new (void)
 {
-  GSList * clients = NULL;
-  GSList ** ptr_clients = &clients;
-  GArray *tmp = g_array_new (FALSE, FALSE, sizeof (gpointer));
-  gpointer type_ptr = &type;
-
-  g_array_insert_val (tmp, 0, ptr_clients);
-  g_array_insert_val (tmp, 1, type_ptr);
-  g_array_insert_val (tmp, 2, pad);
-
-  g_hash_table_foreach (evt->watches, gst_debugserver_qe_append_client, tmp);
-  g_array_unref (tmp);
+  GstDebugserverQE *qe = (GstDebugserverQE*)g_malloc (sizeof(GstDebugserverQE));
+  gst_debugserver_watcher_init (&qe->watcher, gst_debugserver_qe_ok, (GDestroyNotify) qe_watch_list_free, 
qe_watch_compare);
 
-  return clients;
+  return qe;
 }
 
-static gint qe_watch_compare (gconstpointer a, gconstpointer b)
+void gst_debugserver_qe_free (GstDebugserverQE * qe)
 {
-  QEWatch *a1 = (QEWatch*) a;
-  QEWatch *b1 = (QEWatch*) b;
+  gst_debugserver_qe_clean (qe);
+  gst_debugserver_watcher_deinit (&qe->watcher);
+  g_free (qe);
+}
 
-  if (a1->qe_type == b1->qe_type && a1->pad == b1->pad) {
-    return 0;
+static gboolean gst_debugserver_qe_add_watch (GstDebugserverQE * qe, gint type,
+  GstPad * pad, gchar * pad_path, TcpClient * client)
+{
+  QEWatch *w = qe_watch_new (type, pad, pad_path);
+  if (gst_debugserver_watcher_add_watch (&qe->watcher, w, client) == TRUE) {
+    return TRUE;
   } else {
-    return 1;
+    qe_watch_free (w);
+    return FALSE;
   }
 }
 
-gboolean gst_debugserver_qe_set_watch (GstDebugserverQE * evt, gboolean enable,
-  GstPad * pad, gint type, gpointer client_info)
+static gboolean gst_debugserver_qe_remove_watch (GstDebugserverQE * qe,
+  gint type, GstPad * pad, gchar * pad_path, TcpClient * client)
 {
-  if (enable == TRUE) {
-         QEWatch *watch = g_malloc (sizeof (QEWatch));
-    watch->qe_type = type;
-    watch->pad = pad;
-    GSList *watches = g_hash_table_lookup (evt->watches, client_info);
-    if (watches == NULL) {
-      watches = g_slist_append (watches, watch);
-      g_hash_table_insert (evt->watches, client_info, watches);
-      return TRUE;
-    } else if (g_slist_find_custom (watches, watch, qe_watch_compare) != NULL) {
-      return FALSE;
-    }
-
-    watches = g_slist_append (watches, watch);
-    g_hash_table_replace (evt->watches, client_info, watches);
-    return TRUE;
+  QEWatch w = { type, pad, pad_path };
+
+  return gst_debugserver_watcher_remove_watch (&qe->watcher, &w, client);
+}
+
+gboolean gst_debugserver_qe_set_watch (GstDebugserverQE * qe, gboolean enable,
+  gint type, GstPad * pad, gchar * pad_path, TcpClient * client)
+{
+  if (enable) {
+    return gst_debugserver_qe_add_watch (qe, type, pad, pad_path, client);
   } else {
-    GSList *list = g_hash_table_lookup (evt->watches, client_info);
-    if (list == NULL) {
-      return FALSE;
-    }
-    QEWatch w; w.pad = pad; w.qe_type = type;
-    GSList *link = g_slist_find_custom (list, &w, qe_watch_compare);
-    if (link == NULL) {
-      return FALSE;
-    }
-    g_free (link->data);
-    list = g_slist_delete_link (list, link);
-    g_hash_table_replace (evt->watches, client_info, list);
-    return TRUE;
+    return gst_debugserver_qe_remove_watch (qe, type, pad, pad_path, client);
   }
 }
 
-void gst_debugserver_qe_remove_client (GstDebugserverQE * evt, gpointer client_info)
+void gst_debugserver_qe_send_qe (GstDebugserverQE * qe, GstDebugserverTcp * tcp_server, GstPad * pad, 
GstMiniObject * obj)
 {
-  GSList *list = g_hash_table_lookup (evt->watches, client_info);
-  if (list == NULL) {
-    return;
+  GstDebugger__GStreamerData gst_data = GST_DEBUGGER__GSTREAMER_DATA__INIT;
+  GstDebugger__EventInfo event_info = GST_DEBUGGER__EVENT_INFO__INIT;
+  GstDebugger__QueryInfo query_info = GST_DEBUGGER__QUERY_INFO__INIT;
+  gchar *pad_path = gst_utils_get_object_path (GST_OBJECT_CAST (pad));
+
+  if (GST_IS_EVENT (obj)) {
+    GstEvent *event = GST_EVENT_CAST (obj);
+    event_info.type = event->type;
+    event_info.seqnum = event->seqnum;
+    event_info.timestamp = event->timestamp;
+    event_info.pad = pad_path;
+    gst_data.event_info = &event_info;
+    gst_data.info_type_case = GST_DEBUGGER__GSTREAMER_DATA__INFO_TYPE_EVENT_INFO;
+  } else if (GST_IS_QUERY (obj)) {
+    GstQuery *query = GST_QUERY_CAST (obj);
+    query_info.type = query->type;
+    query_info.pad = pad_path;
+    gst_data.query_info = &query_info;
+    gst_data.info_type_case = GST_DEBUGGER__GSTREAMER_DATA__INFO_TYPE_QUERY_INFO;
   }
 
-  g_slist_free_full (list, g_free);
-  g_hash_table_remove (evt->watches, client_info);
+  gst_debugserver_watcher_send_data (&qe->watcher, tcp_server, &gst_data);
+
+  g_free (pad_path);
 }
 
 void gst_debugserver_qe_clean (GstDebugserverQE * qe)
 {
-  g_hash_table_remove_all (qe->watches);
+  gst_debugserver_watcher_clean (&qe->watcher);
+}
+
+void gst_debugserver_qe_remove_client (GstDebugserverQE * qe, TcpClient * client)
+{
+  g_hash_table_remove (qe->watcher.clients, client);
 }
diff --git a/src/debugserver/gstdebugserverqe.h b/src/debugserver/gstdebugserverqe.h
index 5cb9462..8a37c3d 100644
--- a/src/debugserver/gstdebugserverqe.h
+++ b/src/debugserver/gstdebugserverqe.h
@@ -20,43 +20,30 @@
 #ifndef __GST_DEBUGSERVER_EVENT_H__
 #define __GST_DEBUGSERVER_EVENT_H__
 
-#include "common/gstdebugger.pb-c.h"
+#include "gstdebugserverwatcher.h"
 
 #include <gst/gst.h>
-#include <glib.h>
 
 G_BEGIN_DECLS
 
 typedef struct _GstDebugserverQE GstDebugserverQE;
 
-typedef struct _QEWatch {
-  gint qe_type;
-  GstPad * pad;
-} QEWatch;
-
 struct _GstDebugserverQE {
-  GHashTable * watches;
+  GstDebugserverWatcher watcher;
 };
 
 GstDebugserverQE * gst_debugserver_qe_new (void);
 
 void gst_debugserver_qe_free (GstDebugserverQE * qe);
 
-gint gst_debugserver_qeb_prepare_confirmation_buffer (gchar * pad_path, gint qe_type,
-  gboolean toggle, gchar * buffer, gint max_size, PadWatch__WatchType type);
-
 gboolean gst_debugserver_qe_set_watch (GstDebugserverQE * qe, gboolean enable,
-  GstPad * pad, gint qe_type, gpointer client_info);
-
-GSList* gst_debugserver_qe_get_clients (GstDebugserverQE * qe, GstPad * pad,
-  gint type);
+  gint qe_type, GstPad * pad, gchar * pad_path, TcpClient * client);
 
-gint gst_debugserver_qebm_prepare_buffer (GstMiniObject * miniobj, gchar *pad_path,
-  gchar * buffer, gint max_size);
+void gst_debugserver_qe_send_qe (GstDebugserverQE * qe, GstDebugserverTcp * tcp_server, GstPad * pad, 
GstMiniObject * obj);
 
 void gst_debugserver_qe_clean (GstDebugserverQE * qe);
 
-void gst_debugserver_qe_remove_client (GstDebugserverQE * evt, gpointer client_info);
+void gst_debugserver_qe_remove_client (GstDebugserverQE * evt, TcpClient * client);
 
 G_END_DECLS
 
diff --git a/src/debugserver/gstdebugservertcp.c b/src/debugserver/gstdebugservertcp.c
index b3855f9..ed6891b 100644
--- a/src/debugserver/gstdebugservertcp.c
+++ b/src/debugserver/gstdebugservertcp.c
@@ -18,7 +18,9 @@
  */
 
 #include "gstdebugservertcp.h"
+
 #include "common/protocol_utils.h"
+#include "common/gstdebugger.pb-c.h"
 
 #include <gst/gst.h>
 #define GST_USE_UNSTABLE_API
@@ -32,9 +34,21 @@ GST_DEBUG_CATEGORY_STATIC (gst_debugserver_tcp);
 G_DEFINE_TYPE_WITH_CODE (GstDebugserverTcp, gst_debugserver_tcp,
     G_TYPE_OBJECT, _do_init)
 
-static void gst_debugserver_tcp_finalize (GObject * tcp);
+static void
+gst_debugserver_tcp_finalize (GObject * tcp);
+
+static gboolean
+gst_debugserver_tcp_incoming_callback (GSocketService * service,
+    GSocketConnection * connection, GObject * source_object, gpointer user_data);
 
-static TcpClient* gst_debugserver_tcp_find_client (GstDebugserverTcp * tcp, GSocketConnection * connection);
+static gpointer
+gst_debugserver_tcp_handle_client (gpointer user_data);
+
+static TcpClient*
+gst_debugserver_tcp_add_client (GstDebugserverTcp * tcp, GSocketConnection * connection);
+
+static gboolean
+gst_debugserver_tcp_send_packet_to_all_clients (GstDebugserverTcp * tcp, GstDebugger__GStreamerData * 
gst_data);
 
 static void
 gst_debugserver_tcp_class_init (GstDebugserverTcpClass * klass)
@@ -46,24 +60,6 @@ gst_debugserver_tcp_class_init (GstDebugserverTcpClass * klass)
 }
 
 static void
-gst_debugserver_tcp_init (GstDebugserverTcp * self)
-{
-  self->service = NULL;
-  self->process_command = NULL;
-  self->process_command_user_data = NULL;
-  self->client_disconnected = NULL;
-  self->parent = NULL;
-  self->client_connected = NULL;
-}
-
-GstDebugserverTcp * gst_debugserver_tcp_new (void)
-{
-  GstDebugserverTcp * tcp = g_object_new (GST_TYPE_DEBUGSERVER_TCP, NULL);
-  tcp->clients = NULL;
-  return tcp;
-}
-
-static void
 gst_debugserver_tcp_finalize (GObject * obj)
 {
   GstDebugserverTcp * tcp = GST_DEBUGSERVER_TCP (obj);
@@ -71,98 +67,45 @@ gst_debugserver_tcp_finalize (GObject * obj)
   g_slist_free_full (tcp->clients, g_free);
 }
 
-static gpointer
-gst_debugserver_tcp_process_client (gpointer user_data)
+static void
+gst_debugserver_tcp_init (GstDebugserverTcp * self)
 {
-  GArray *tmp = (GArray *) user_data;
-  GSocketConnection *connection = g_array_index (tmp, GSocketConnection *, 0);
-  GstDebugserverTcp *tcp =
-      g_array_index (tmp, GstDebugserverTcp*, 1);
-  GInputStream *istream;
-  gchar message[1024];
-  Command *command;
-  gint size;
-
-  g_array_unref (tmp);
-
-  istream = g_io_stream_get_input_stream (G_IO_STREAM (connection));
-
-  GST_DEBUG_OBJECT (tcp, "Received connection from client!\n");
-
-  if (tcp->client_connected != NULL) {
-    tcp->client_connected (connection, tcp->parent);
-  }
-
-  while ((size = gst_debugger_protocol_utils_read_header (istream, NULL)) > 0) {
-     assert (size <= 1024);
-     GST_DEBUG_OBJECT (tcp, "Received message of size: %d\n", size);
-     gst_debugger_protocol_utils_read_requested_size (istream, size, message, NULL);
-     command = command__unpack (NULL, size, (guint8*)message);
-     if (command == NULL) {
-       g_print ("error unpacking incoming message\n");
-       continue;
-     }
-
-     GST_LOG_OBJECT (tcp, "Command type: %d\n", command->command_type);
-
-     if (tcp->process_command)
-       tcp->process_command (command, connection, tcp->process_command_user_data);
-
-     command__free_unpacked (command, NULL);
-   }
-
-  if (tcp->client_disconnected)
-    tcp->client_disconnected (connection, tcp->parent);
-
-  TcpClient *c = gst_debugserver_tcp_find_client (tcp, connection);
-  tcp->clients = g_slist_remove (tcp->clients, c);
-  g_free (c);
-
-  GST_LOG_OBJECT (tcp, "Client disconnected");
-
-  return NULL;
+  self->service = NULL;
+  self->clients = NULL;
+  self->client_disconnected_handler = NULL;
+  self->command_handler = NULL;
+  self->owner = NULL;
 }
 
-static void gst_debugserver_tcp_add_client (GstDebugserverTcp * tcp, GSocketConnection * connection)
+GstDebugserverTcp * gst_debugserver_tcp_new (void)
 {
-  TcpClient *client = (TcpClient*) g_malloc (sizeof (TcpClient));
-  client->connection = connection;
-  g_mutex_init (&client->mutex);
-  tcp->clients = g_slist_append (tcp->clients, client);
-}
+  GstDebugserverTcp * tcp = g_object_new (GST_TYPE_DEBUGSERVER_TCP, NULL);
 
-static gboolean
-gst_debugserver_tcp_incoming_callback (GSocketService * service,
-    GSocketConnection * connection, GObject * source_object, gpointer user_data)
-{
-  GArray *tmp = g_array_new (FALSE, FALSE, sizeof (gpointer));
-  gst_debugserver_tcp_add_client (GST_DEBUGSERVER_TCP (user_data), connection);
-  g_array_insert_val (tmp, 0, connection);
-  g_array_insert_val (tmp, 1, user_data);
-  g_object_ref (connection);
-  g_thread_new ("connection",
-      (GThreadFunc) gst_debugserver_tcp_process_client, tmp);
-  return TRUE;
+  return tcp;
 }
 
-void
+gboolean
 gst_debugserver_tcp_start_server (GstDebugserverTcp * tcp, guint port)
 {
   GError *error = NULL;
+
   tcp->service = g_socket_service_new ();
 
   g_socket_listener_add_inet_port ((GSocketListener *) tcp->service,
       port, NULL, &error);
 
   if (error != NULL) {
-    GST_ERROR ("%s", error->message);
+    GST_ERROR ("Error on running server: %s", error->message);
     g_error_free (error);
+    return FALSE;
   }
 
   g_signal_connect (tcp->service,
       "incoming", G_CALLBACK (gst_debugserver_tcp_incoming_callback), tcp);
 
   g_socket_service_start (tcp->service);
+
+  return TRUE;
 }
 
 void
@@ -174,7 +117,82 @@ gst_debugserver_tcp_stop_server (GstDebugserverTcp * tcp)
   }
 }
 
-TcpClient* gst_debugserver_tcp_find_client (GstDebugserverTcp * tcp, GSocketConnection * connection)
+static gboolean
+gst_debugserver_tcp_incoming_callback (GSocketService * service,
+    GSocketConnection * connection, GObject * source_object, gpointer user_data)
+{
+  GArray *user_data_array = g_array_new (FALSE, FALSE, sizeof (gpointer));
+  TcpClient *client = gst_debugserver_tcp_add_client (GST_DEBUGSERVER_TCP (user_data), connection);
+
+  g_array_insert_val (user_data_array, 0, client);
+  g_array_insert_val (user_data_array, 1, user_data);
+  g_object_ref (connection);
+  g_thread_new ("connection",
+      (GThreadFunc) gst_debugserver_tcp_handle_client, user_data_array);
+
+  return TRUE;
+}
+
+static TcpClient*
+gst_debugserver_tcp_add_client (GstDebugserverTcp * tcp, GSocketConnection * connection)
+{
+  TcpClient *client = (TcpClient*) g_malloc (sizeof (TcpClient));
+
+  g_mutex_init (&client->mutex);
+  client->connection = connection;
+  tcp->clients = g_slist_append (tcp->clients, client);
+
+  return client;
+}
+
+static gpointer
+gst_debugserver_tcp_handle_client (gpointer user_data)
+{
+  GArray *user_data_array = (GArray *) user_data;
+  TcpClient *client = g_array_index (user_data_array, TcpClient *, 0);
+  GstDebugserverTcp *self = g_array_index (user_data_array, GstDebugserverTcp*, 1);
+  GInputStream *istream;
+  gchar buffer[1024];
+  gint size;
+  GstDebugger__Command *command;
+
+  g_array_unref (user_data_array);
+
+  istream = g_io_stream_get_input_stream (G_IO_STREAM (client->connection));
+
+  GST_DEBUG_OBJECT (self, "Received connection from client!\n");
+
+  while ((size = gst_debugger_protocol_utils_read_header (istream, NULL)) > 0) {
+     assert (size <= 1024); // todo max message size in global file
+     GST_DEBUG_OBJECT (self, "Received message of size: %d\n", size);
+     gst_debugger_protocol_utils_read_requested_size (istream, size, buffer, NULL);
+     command = gst_debugger__command__unpack (NULL, size, (uint8_t*) buffer);
+     if (command == NULL) {
+       g_print ("error unpacking incoming message\n");
+       continue;
+     }
+
+     if (self->command_handler != NULL) {
+       self->command_handler (command, self->owner, client);
+     }
+
+     gst_debugger__command__free_unpacked (command, NULL);
+   }
+
+  self->clients = g_slist_remove (self->clients, client);
+
+  if (self->client_disconnected_handler)
+    self->client_disconnected_handler (client, self->owner);
+
+  g_free (client);
+
+  GST_LOG_OBJECT (self, "Client disconnected");
+
+  return NULL;
+}
+
+TcpClient*
+gst_debugserver_tcp_find_client (GstDebugserverTcp * tcp, GSocketConnection * connection)
 {
   GSList *client_list = tcp->clients;
   TcpClient *client;
@@ -186,29 +204,59 @@ TcpClient* gst_debugserver_tcp_find_client (GstDebugserverTcp * tcp, GSocketConn
     }
     client_list = g_slist_next (client_list);
   }
-  return NULL;
+ return NULL;
 }
 
-gboolean gst_debugserver_tcp_send_packet (GstDebugserverTcp * tcp, GSocketConnection * connection,
-  gchar * buffer, gint size)
+#define SAFE_PREPARE_BUFFER_INIT(BUFFER_SIZE) \
+  gchar buff[BUFFER_SIZE]; \
+  gchar *m_buff = buff; \
+  gint max_m_buff_size = BUFFER_SIZE;
+
+#define SAFE_PREPARE_BUFFER(FUNCTION_CALL, SIZE_VAR) \
+  do { \
+    SIZE_VAR = (FUNCTION_CALL); \
+    if (SIZE_VAR > 1024) { \
+      m_buff = (gchar *) g_malloc (SIZE_VAR); \
+      max_m_buff_size = SIZE_VAR; \
+      SIZE_VAR = (FUNCTION_CALL); \
+    } \
+  } while (0)
+
+#define SAFE_PREPARE_BUFFER_CLEAN \
+  do { \
+    if (m_buff != buff) { \
+      g_free (m_buff); \
+    } \
+  } while (0)
+
+gboolean
+gst_debugserver_tcp_send_packet (GstDebugserverTcp * tcp, TcpClient * client,
+  GstDebugger__GStreamerData * gst_data)
 {
   GError *err = NULL;
   gchar size_buffer[4];
   GSocket *socket;
-  TcpClient *client;
+  gchar buff[1024];
+  gchar *m_buff = buff;
+  gint size;
+
+  if (client == NULL) {
+    return gst_debugserver_tcp_send_packet_to_all_clients (tcp, gst_data);
+  }
+
+  g_mutex_lock (&client->mutex);
 
-  if (connection == NULL) {
-    return gst_debugserver_tcp_send_packet_to_all_clients (tcp, buffer, size);
+  if (!g_socket_connection_is_connected (client->connection)) {
+    return FALSE;
   }
 
-  client = gst_debugserver_tcp_find_client (tcp, connection);
-  assert (client != NULL);
-  socket = g_socket_connection_get_socket (connection);
+  socket = g_socket_connection_get_socket (client->connection);
 
+  size = gst_debugger__gstreamer_data__get_packed_size (gst_data);
   gst_debugger_protocol_utils_serialize_integer64 (size, size_buffer, 4);
 
-  g_mutex_lock (&client->mutex);
   g_socket_send (socket, (gchar*)size_buffer, 4, NULL, &err);
+
   if (err) {
     g_mutex_unlock (&client->mutex);
     g_print ("cannot send size of data: %s\n", err->message);
@@ -216,8 +264,20 @@ gboolean gst_debugserver_tcp_send_packet (GstDebugserverTcp * tcp, GSocketConnec
     return FALSE;
   }
 
-  g_socket_send (socket, (gchar*)buffer, size, NULL, &err);
+  if (size > 1024) {
+    m_buff = (char*) g_malloc (size * sizeof (char));
+  }
+
+  gst_debugger__gstreamer_data__pack (gst_data, m_buff);
+
+  g_socket_send (socket, (gchar*)m_buff, size, NULL, &err);
+
+  if (m_buff != buff) {
+    g_free (m_buff);
+  }
+
   g_mutex_unlock (&client->mutex);
+
   if (err) {
     g_print ("cannot send data: %s\n", err->message);
     g_error_free (err);
@@ -227,7 +287,8 @@ gboolean gst_debugserver_tcp_send_packet (GstDebugserverTcp * tcp, GSocketConnec
   return TRUE;
 }
 
-gboolean gst_debugserver_tcp_send_packet_to_all_clients (GstDebugserverTcp * tcp, gchar * buffer, gint size)
+static gboolean
+gst_debugserver_tcp_send_packet_to_all_clients (GstDebugserverTcp * tcp, GstDebugger__GStreamerData * 
gst_data)
 {
   GSList *clients = tcp->clients;
   TcpClient *client;
@@ -235,7 +296,7 @@ gboolean gst_debugserver_tcp_send_packet_to_all_clients (GstDebugserverTcp * tcp
 
   while (clients != NULL) {
     client = (TcpClient*)clients->data;
-    ret = ret && gst_debugserver_tcp_send_packet (tcp, client->connection, buffer, size);
+    ret = ret && gst_debugserver_tcp_send_packet (tcp, client, gst_data);
     clients = clients->next;
   }
 
diff --git a/src/debugserver/gstdebugservertcp.h b/src/debugserver/gstdebugservertcp.h
index 521de28..6d14c59 100644
--- a/src/debugserver/gstdebugservertcp.h
+++ b/src/debugserver/gstdebugservertcp.h
@@ -38,29 +38,26 @@ G_BEGIN_DECLS
   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DEBUGSERVER_TCP))
 #define GST_DEBUGSERVER_TCP_CAST(obj) ((GstDebugserverTcp *)(obj))
 
-typedef struct _GstDebugserverTcp GstDebugserverTcp;
-typedef struct _GstDebugserverTcpClass GstDebugserverTcpClass;
-
-typedef void (*GstDebugserverTcpProcessCommandFunction)
-    (Command * command, gpointer client_id, gpointer user_data);
-
-typedef void (*GstDebugserverTcpClientChanged)
-    (gpointer client_id, gpointer user_data);
-
 typedef struct _TcpClient {
   GSocketConnection * connection;
   GMutex mutex;
 } TcpClient;
 
+typedef void (*GstDebugserverTcpHandleCommandFunction)
+    (GstDebugger__Command * command, gpointer user_data, TcpClient * client);
+
+typedef void (*GstDebugserverTcpClientDisconnectedFunction)
+    (TcpClient * client, gpointer user_data);
+
+typedef struct _GstDebugserverTcp GstDebugserverTcp;
+typedef struct _GstDebugserverTcpClass GstDebugserverTcpClass;
+
 struct _GstDebugserverTcp {
   GObject parent_instance;
+  gpointer owner;
 
-  GstDebugserverTcpProcessCommandFunction process_command;
-  gpointer process_command_user_data;
-
-  GstDebugserverTcpClientChanged client_disconnected;
-  GstDebugserverTcpClientChanged client_connected;
-  gpointer parent;
+  GstDebugserverTcpHandleCommandFunction command_handler;
+  GstDebugserverTcpClientDisconnectedFunction client_disconnected_handler;
 
   /*< private >*/
   GSocketService * service;
@@ -71,18 +68,18 @@ struct _GstDebugserverTcp {
 struct _GstDebugserverTcpClass
 {
   GObjectClass parent_class;
+
+  void (*command_received)     (gpointer *tracer, GstDebugger__Command *command);
 };
 
 GstDebugserverTcp * gst_debugserver_tcp_new (void);
 
-void gst_debugserver_tcp_start_server (GstDebugserverTcp * tcp, guint port);
+gboolean gst_debugserver_tcp_start_server (GstDebugserverTcp * tcp, guint port);
 
 void gst_debugserver_tcp_stop_server (GstDebugserverTcp * tcp);
 
-gboolean gst_debugserver_tcp_send_packet (GstDebugserverTcp * tcp, GSocketConnection * connection,
-  gchar * buffer, gint size);
-
-gboolean gst_debugserver_tcp_send_packet_to_all_clients (GstDebugserverTcp * tcp, gchar * buffer, gint size);
+gboolean gst_debugserver_tcp_send_packet (GstDebugserverTcp * tcp, TcpClient * client,
+  GstDebugger__GStreamerData * gst_data);
 
 G_GNUC_INTERNAL GType gst_debugserver_tcp_get_type (void);
 
diff --git a/src/debugserver/gstdebugservertopology.c b/src/debugserver/gstdebugservertopology.c
index 119601e..c1fe0f9 100644
--- a/src/debugserver/gstdebugservertopology.c
+++ b/src/debugserver/gstdebugservertopology.c
@@ -25,10 +25,10 @@
 
 GSList *src_pads;
 
-static TopologyTemplate
+static GstDebugger__PadTemplate
 get_topology_template_object (GstPadTemplate *template)
 {
-  TopologyTemplate tpl = TOPOLOGY_TEMPLATE__INIT;
+  GstDebugger__PadTemplate tpl = GST_DEBUGGER__PAD_TEMPLATE__INIT;
 
   tpl.caps = gst_caps_to_string (GST_PAD_TEMPLATE_CAPS (template));
   tpl.direction = GST_PAD_TEMPLATE_DIRECTION (template);
@@ -39,17 +39,17 @@ get_topology_template_object (GstPadTemplate *template)
 }
 
 static void
-send_object (GstObject *object, Topology__Action action, GstDebugserverTcp * server, GSocketConnection * 
client)
+send_object (GstObject *object, GstDebugger__Action action, GstDebugserverTcp * server, TcpClient * client)
 {
-  GstreamerInfo info = GSTREAMER_INFO__INIT;
-  Topology topology = TOPOLOGY__INIT;
+  GstDebugger__GStreamerData info = GST_DEBUGGER__GSTREAMER_DATA__INIT;
+  GstDebugger__TopologyInfo topology = GST_DEBUGGER__TOPOLOGY_INFO__INIT;
   gint size;
   gchar buffer[1024];
-  TopologyElement element_tp = TOPOLOGY_ELEMENT__INIT;
-  TopologyPad pad_tp = TOPOLOGY_PAD__INIT;
-  TopologyTemplate template = TOPOLOGY_TEMPLATE__INIT;
+  GstDebugger__TopologyElement element_tp = GST_DEBUGGER__TOPOLOGY_ELEMENT__INIT;
+  GstDebugger__TopologyPad pad_tp = GST_DEBUGGER__TOPOLOGY_PAD__INIT;
+  GstDebugger__PadTemplate template = GST_DEBUGGER__PAD_TEMPLATE__INIT;
 
-  info.info_type = GSTREAMER_INFO__INFO_TYPE__TOPOLOGY;
+  info.info_type_case = GST_DEBUGGER__GSTREAMER_DATA__INFO_TYPE_TOPOLOGY_INFO;
   topology.action = action;
 
   if (GST_IS_ELEMENT (object)) {
@@ -58,7 +58,7 @@ send_object (GstObject *object, Topology__Action action, GstDebugserverTcp * ser
     element_tp.is_bin = GST_IS_BIN (object);
     element_tp.factory_name = gst_plugin_feature_get_name (gst_element_get_factory (GST_ELEMENT_CAST 
(object)));
     topology.element = &element_tp;
-    topology.type = TOPOLOGY__OBJECT_TYPE__ELEMENT;
+    topology.topology_type_case = GST_DEBUGGER__TOPOLOGY_INFO__TOPOLOGY_TYPE_ELEMENT;
   } else if (GST_IS_PAD (object)) {
     GstPad *pad = GST_PAD (object);
     pad_tp.path = gst_utils_get_object_path (object);
@@ -70,42 +70,39 @@ send_object (GstObject *object, Topology__Action action, GstDebugserverTcp * ser
       pad_tp.template_ = &template;
     }
     topology.pad = &pad_tp;
-    topology.type = TOPOLOGY__OBJECT_TYPE__PAD;
+    topology.topology_type_case = GST_DEBUGGER__TOPOLOGY_INFO__TOPOLOGY_TYPE_PAD;
   } else {
     assert (FALSE);
   }
-  info.topology = &topology;
-  size = gstreamer_info__get_packed_size (&info);
-  assert(size <= 1024);
-  gstreamer_info__pack (&info, (guint8*)buffer);
+  info.topology_info = &topology;
 
+  gst_debugserver_tcp_send_packet (server, client, &info);
   g_free (template.caps);
 
-  gst_debugserver_tcp_send_packet (server, client, buffer, size);
 }
 
 static void
-send_link (GstPad *src_pad, GstPad *sink_pad, Topology__Action action, GstDebugserverTcp *server, 
GSocketConnection * client)
+send_link (GstPad *src_pad, GstPad *sink_pad, GstDebugger__Action action, GstDebugserverTcp *server, 
TcpClient * client)
 {
-  GstreamerInfo info = GSTREAMER_INFO__INIT;
-  Topology topology = TOPOLOGY__INIT;
+  GstDebugger__GStreamerData info = GST_DEBUGGER__GSTREAMER_DATA__INIT;
+  GstDebugger__TopologyInfo topology = GST_DEBUGGER__TOPOLOGY_INFO__INIT;
   gint size;
   gchar buffer[1024];
-  TopologyLink link_tp = TOPOLOGY_LINK__INIT;
+  GstDebugger__TopologyLink link_tp = GST_DEBUGGER__TOPOLOGY_LINK__INIT;
 
   if (!gst_utils_check_pad_has_element_parent (src_pad) || !gst_utils_check_pad_has_element_parent 
(sink_pad)) {
     return;
   }
 
-  info.info_type = GSTREAMER_INFO__INFO_TYPE__TOPOLOGY;
+  info.info_type_case = GST_DEBUGGER__GSTREAMER_DATA__INFO_TYPE_TOPOLOGY_INFO;
   topology.action = action;
-  topology.type = TOPOLOGY__OBJECT_TYPE__LINK;
+  topology.topology_type_case = GST_DEBUGGER__TOPOLOGY_INFO__TOPOLOGY_TYPE_LINK;
 
   if (GST_IS_PROXY_PAD (src_pad) && !GST_IS_GHOST_PAD (src_pad)) {
     return;
   }
 
-  link_tp.src_pad_path = gst_utils_get_object_path (GST_OBJECT_CAST (src_pad));
+  link_tp.src_pad = gst_utils_get_object_path (GST_OBJECT_CAST (src_pad));
   if (GST_IS_PROXY_PAD (sink_pad)) {
     if (GST_IS_GHOST_PAD (sink_pad)) {
       GstPad *internal = gst_pad_get_peer (GST_PAD_CAST (gst_proxy_pad_get_internal (GST_PROXY_PAD 
(sink_pad))));
@@ -117,18 +114,16 @@ send_link (GstPad *src_pad, GstPad *sink_pad, Topology__Action action, GstDebugs
     }
   }
 
-  link_tp.sink_pad_path = gst_utils_get_object_path (GST_OBJECT_CAST (sink_pad));
+  link_tp.sink_pad = gst_utils_get_object_path (GST_OBJECT_CAST (sink_pad));
   topology.link = &link_tp;
-  topology.type = TOPOLOGY__OBJECT_TYPE__LINK;
-  info.topology = &topology;
-  size = gstreamer_info__get_packed_size (&info);
-  assert(size <= 1024);
-  gstreamer_info__pack (&info, (guint8*)buffer);
-  gst_debugserver_tcp_send_packet (server, client, buffer, size);
+  topology.topology_type_case = GST_DEBUGGER__TOPOLOGY_INFO__TOPOLOGY_TYPE_LINK;
+  info.topology_info = &topology;
+
+  gst_debugserver_tcp_send_packet (server, client, &info);
 }
 
 static void
-send_element_pads (GstElement * element, GstDebugserverTcp *server, GSocketConnection * client)
+send_element_pads (GstElement * element, GstDebugserverTcp *server, TcpClient * client)
 {
   gboolean done;
   GstPad *pad;
@@ -143,7 +138,7 @@ send_element_pads (GstElement * element, GstDebugserverTcp *server, GSocketConne
         if (gst_pad_get_direction (pad) == GST_PAD_SRC && gst_pad_get_peer (pad)) {
           src_pads = g_slist_append (src_pads, pad);
         }
-        send_object (GST_OBJECT (pad), TOPOLOGY__ACTION__ADD, server, client);
+        send_object (GST_OBJECT (pad), GST_DEBUGGER__ACTION__ADD, server, client);
         g_value_reset (&item);
         break;
       case GST_ITERATOR_RESYNC:
@@ -160,13 +155,13 @@ send_element_pads (GstElement * element, GstDebugserverTcp *server, GSocketConne
 }
 
 static void
-gst_debugserver_topology_send_element (GstElement * element, GstDebugserverTcp *server, GSocketConnection * 
client)
+gst_debugserver_topology_send_element (GstElement * element, GstDebugserverTcp *server, TcpClient * client)
 {
   GstIterator *element_it;
   gboolean done;
 
   if (GST_ELEMENT_PARENT (element) != NULL) {
-    send_object (GST_OBJECT (element), TOPOLOGY__ACTION__ADD, server, client);
+    send_object (GST_OBJECT (element), GST_DEBUGGER__ACTION__ADD, server, client);
   }
 
   send_element_pads (element, server, client);
@@ -198,36 +193,36 @@ gst_debugserver_topology_send_element (GstElement * element, GstDebugserverTcp *
   gst_iterator_free (element_it);
 }
 
-void gst_debugserver_topology_send_entire_topology (GstBin *bin, GstDebugserverTcp * server, 
GSocketConnection * client)
+void gst_debugserver_topology_send_entire_topology (GstBin *bin, GstDebugserverTcp * server, TcpClient * 
client)
 {
   src_pads = NULL;
   gst_debugserver_topology_send_element (GST_ELEMENT (bin), server, client);
   GSList *tmp_list = src_pads;
   while (tmp_list != NULL) {
     GstPad *pad = (GstPad*)tmp_list->data;
-    send_link (pad, gst_pad_get_peer (pad), TOPOLOGY__ACTION__ADD, server, client);
+    send_link (pad, gst_pad_get_peer (pad), GST_DEBUGGER__ACTION__ADD, server, client);
     tmp_list = tmp_list->next;
   }
 
   g_slist_free (src_pads);
 }
 
-void gst_debugserver_topology_send_pad_link (GstPad * src, GstPad * sink, gboolean link, GstDebugserverTcp * 
server, GSocketConnection * client)
+void gst_debugserver_topology_send_pad_link (GstPad * src, GstPad * sink, gboolean link, GstDebugserverTcp * 
server, TcpClient * client)
 {
-  send_link (src, sink, link ? TOPOLOGY__ACTION__ADD : TOPOLOGY__ACTION__REMOVE, server, client);
+  send_link (src, sink, link ? GST_DEBUGGER__ACTION__ADD : GST_DEBUGGER__ACTION__REMOVE, server, client);
 }
 
-void gst_debugserver_topology_send_element_in_bin (GstBin * bin, GstElement * element, gboolean add, 
GstDebugserverTcp * server, GSocketConnection * client)
+void gst_debugserver_topology_send_element_in_bin (GstBin * bin, GstElement * element, gboolean add, 
GstDebugserverTcp * server, TcpClient * client)
 {
-  send_object (GST_OBJECT_CAST (element), add ? TOPOLOGY__ACTION__ADD : TOPOLOGY__ACTION__REMOVE, server, 
client);
+  send_object (GST_OBJECT_CAST (element), add ? GST_DEBUGGER__ACTION__ADD : GST_DEBUGGER__ACTION__REMOVE, 
server, client);
 }
 
-void gst_debugserver_topology_send_pad_in_element (GstElement * element, GstPad * pad, gboolean add, 
GstDebugserverTcp * server, GSocketConnection * client)
+void gst_debugserver_topology_send_pad_in_element (GstElement * element, GstPad * pad, gboolean add, 
GstDebugserverTcp * server, TcpClient * client)
 {
   if (GST_OBJECT_PARENT (element) == NULL) {
     return;
   }
 
-  send_object (GST_OBJECT_CAST (pad), add ? TOPOLOGY__ACTION__ADD : TOPOLOGY__ACTION__REMOVE, server, 
client);
+  send_object (GST_OBJECT_CAST (pad), add ? GST_DEBUGGER__ACTION__ADD : GST_DEBUGGER__ACTION__REMOVE, 
server, client);
 }
 
diff --git a/src/debugserver/gstdebugservertopology.h b/src/debugserver/gstdebugservertopology.h
index 7691c11..8f69218 100644
--- a/src/debugserver/gstdebugservertopology.h
+++ b/src/debugserver/gstdebugservertopology.h
@@ -24,12 +24,12 @@
 
 #include <gst/gst.h>
 
-void gst_debugserver_topology_send_entire_topology (GstBin *root, GstDebugserverTcp * server, 
GSocketConnection * client);
+void gst_debugserver_topology_send_entire_topology (GstBin *root, GstDebugserverTcp * server, TcpClient * 
client);
 
-void gst_debugserver_topology_send_pad_link (GstPad * src, GstPad * sink, gboolean link, GstDebugserverTcp * 
server, GSocketConnection * client);
+void gst_debugserver_topology_send_pad_link (GstPad * src, GstPad * sink, gboolean link, GstDebugserverTcp * 
server, TcpClient * client);
 
-void gst_debugserver_topology_send_element_in_bin (GstBin * bin, GstElement * element, gboolean add, 
GstDebugserverTcp * server, GSocketConnection * client);
+void gst_debugserver_topology_send_element_in_bin (GstBin * bin, GstElement * element, gboolean add, 
GstDebugserverTcp * server, TcpClient * client);
 
-void gst_debugserver_topology_send_pad_in_element (GstElement * element, GstPad * pad, gboolean add, 
GstDebugserverTcp * server, GSocketConnection * client);
+void gst_debugserver_topology_send_pad_in_element (GstElement * element, GstPad * pad, gboolean add, 
GstDebugserverTcp * server, TcpClient * client);
 
 #endif /* SRC_DEBUGSERVER_GSTDEBUGSERVERTOPOLOGY_H_ */
diff --git a/src/debugserver/gstdebugservertypes.c b/src/debugserver/gstdebugservertypes.c
new file mode 100644
index 0000000..7f70f98
--- /dev/null
+++ b/src/debugserver/gstdebugservertypes.c
@@ -0,0 +1,157 @@
+/* GStreamer
+ * Copyright (C) 2015 Marcin Kolny <marcin kolny gmail com>
+ *
+ * gstdebugserver.c: tracing module that sends serialized data to
+ * an user.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "gstdebugservertypes.h"
+
+#include <gst/gst.h>
+
+#define SERIALIZE_ENUM_FLAGS \
+  do { \
+    n_values = klass->n_values; \
+    values = g_malloc (sizeof (GstDebugger__EnumFlagsValue*) * n_values); \
+    \
+    for (i = 0; i < klass->n_values; i++) { \
+      values[i] = (GstDebugger__EnumFlagsValue*) g_malloc (sizeof (GstDebugger__EnumFlagsValue)); \
+      gst_debugger__enum_flags_value__init (values[i]); \
+      values[i]->name = (gchar*) klass->values[i].value_name; \
+      values[i]->nick = (gchar*) klass->values[i].value_nick; \
+      values[i]->value = klass->values[i].value; \
+    } \
+    \
+    data_type.values = values; \
+    data_type.n_values = klass->n_values; \
+    data_type.type_name = (gchar*) name; \
+    gst_data.enum_flags_type = &data_type; \
+  } while (FALSE)
+
+static void gst_debugserver_types_send_enum_flags (GstDebugserverTcp *tcp_server, TcpClient *client, const 
gchar * name)
+{
+  GType type = g_type_from_name (name);
+  GstDebugger__GStreamerData gst_data = GST_DEBUGGER__GSTREAMER_DATA__INIT;
+  GstDebugger__EnumFlagsType data_type = GST_DEBUGGER__ENUM_FLAGS_TYPE__INIT;
+  GstDebugger__EnumFlagsValue **values = NULL;
+  gint i = 0, n_values = 0;
+
+  if (G_TYPE_IS_ENUM (type)) {
+    GEnumClass * klass = g_type_class_peek (type);
+    SERIALIZE_ENUM_FLAGS;
+    data_type.kind = GST_DEBUGGER__ENUM_FLAGS_TYPE__ENUM_FLAGS_KIND__ENUM;
+  } else if (G_TYPE_IS_FLAGS (type)) {
+    GFlagsClass * klass = g_type_class_peek (type);
+    SERIALIZE_ENUM_FLAGS;
+    data_type.kind = GST_DEBUGGER__ENUM_FLAGS_TYPE__ENUM_FLAGS_KIND__FLAGS;
+  } else {
+    // todo
+  }
+
+  gst_data.enum_flags_type = &data_type;
+  gst_data.info_type_case = GST_DEBUGGER__GSTREAMER_DATA__INFO_TYPE_ENUM_FLAGS_TYPE;
+
+  gst_debugserver_tcp_send_packet (tcp_server, client, &gst_data);
+
+  for (i = 0; i < n_values; i++) {
+    g_free (values[i]);
+  }
+  g_free (values);
+}
+
+static void gst_debugserver_types_send_factory (GstDebugserverTcp *tcp_server, TcpClient *client, const 
gchar * name)
+{
+  GstDebugger__GStreamerData gst_data = GST_DEBUGGER__GSTREAMER_DATA__INIT;
+  GstDebugger__FactoryType factory_type = GST_DEBUGGER__FACTORY_TYPE__INIT;
+  GstDebugger__PadTemplate **templates = NULL;
+  GstElementFactory *factory = gst_element_factory_find (name);
+  GstStaticPadTemplate *static_template = NULL;
+  GList *tpls = NULL;
+  gint i = 0;
+
+  if (factory == NULL) {
+    // todo
+    return;
+  }
+
+  factory_type.name = gst_plugin_feature_get_name (factory);
+  factory_type.n_templates = gst_element_factory_get_num_pad_templates (factory);
+  if (factory_type.n_templates != 0) {
+    templates = g_malloc (factory_type.n_templates * sizeof (GstDebugger__PadTemplate*));
+    tpls = (GList*)gst_element_factory_get_static_pad_templates (factory);
+
+    while (tpls) {
+      static_template = (GstStaticPadTemplate*) tpls->data;
+      tpls = g_list_next (tpls);
+      templates[i] = g_malloc (sizeof (GstDebugger__PadTemplate));
+      gst_debugger__pad_template__init (templates[i]);
+      templates[i]->caps = (gchar*) static_template->static_caps.string;
+      templates[i]->direction = static_template->direction;
+      templates[i]->presence = static_template->presence;
+      templates[i]->name_template = (gchar*) static_template->name_template;
+      i++;
+    }
+  }
+  factory_type.templates = templates;
+
+  gchar **keys, **k;
+  gint meta_cnt = 0;
+  i = 0;
+  GstDebugger__FactoryMeta **entries = NULL;
+  keys = gst_element_factory_get_metadata_keys (factory);
+  if (keys != NULL) {
+    for (k = keys; *k != NULL; ++k) { meta_cnt++; }
+    entries = g_malloc (sizeof (GstDebugger__FactoryMeta*) * meta_cnt);
+    for (k = keys; *k != NULL; ++k) {
+      entries[i] = g_malloc (sizeof (GstDebugger__FactoryMeta));
+      gst_debugger__factory_meta__init (entries[i]);
+      entries[i]->key = *k;
+      entries[i]->value = (gchar*) gst_element_factory_get_metadata (factory, *k);
+      i++;
+    }
+  }
+  factory_type.metadata = entries;
+  factory_type.n_metadata = meta_cnt;
+
+  gst_data.factory = &factory_type;
+  gst_data.info_type_case = GST_DEBUGGER__GSTREAMER_DATA__INFO_TYPE_FACTORY;
+
+  gst_debugserver_tcp_send_packet (tcp_server, client, &gst_data);
+
+  for (i = 0; i < (gint) factory_type.n_templates; i++) {
+    g_free (templates[i]);
+  }
+  g_free (templates);
+
+  for (i = 0; i < (gint) factory_type.n_metadata; i++) {
+    g_free (entries[i]);
+  }
+  g_free (entries);
+  g_strfreev (keys);
+}
+
+void gst_debugserver_types_send_type (GstDebugserverTcp *tcp_server, TcpClient *client, const 
GstDebugger__TypeDescriptionRequest *request)
+{
+  switch (request->type) {
+  case GST_DEBUGGER__TYPE_DESCRIPTION_REQUEST__TYPE__FACTORY:
+    gst_debugserver_types_send_factory (tcp_server, client, request->name);
+    break;
+  case GST_DEBUGGER__TYPE_DESCRIPTION_REQUEST__TYPE__ENUM_FLAGS:
+    gst_debugserver_types_send_enum_flags (tcp_server, client, request->name);
+  }
+}
diff --git a/src/debugserver/gstdebugserverfactory.h b/src/debugserver/gstdebugservertypes.h
similarity index 69%
rename from src/debugserver/gstdebugserverfactory.h
rename to src/debugserver/gstdebugservertypes.h
index 32429c3..2f6e35d 100644
--- a/src/debugserver/gstdebugserverfactory.h
+++ b/src/debugserver/gstdebugservertypes.h
@@ -1,6 +1,9 @@
 /* GStreamer
  * Copyright (C) 2015 Marcin Kolny <marcin kolny gmail com>
  *
+ * gstdebugserver.c: tracing module that sends serialized data to
+ * an user.
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
  * License as published by the Free Software Foundation; either
@@ -17,11 +20,13 @@
  * Boston, MA 02110-1301, USA.
  */
 
-#ifndef __GST_DEBUGSERVER_FACTORY_H__
-#define __GST_DEBUGSERVER_FACTORY_H__
+#ifndef __GST_DEBUGSERVER_ENUM_H__
+#define __GST_DEBUGSERVER_ENUM_H__
+
+#include "gstdebugservertcp.h"
 
-#include <gst/gst.h>
+void gst_debugserver_types_send_type (GstDebugserverTcp *tcp_server, TcpClient *client,
+    const GstDebugger__TypeDescriptionRequest *request);
 
-gint gst_debugserver_factory_prepare_buffer (GstElementFactory *factory, gchar * buffer, gint max_size);
 
-#endif /* __GST_DEBUGSERVER_FACTORY_H__ */
+#endif /* __GST_DEBUGSERVER_ENUM_H__ */
diff --git a/src/debugserver/gstdebugserverwatcher.c b/src/debugserver/gstdebugserverwatcher.c
new file mode 100644
index 0000000..1cb7d85
--- /dev/null
+++ b/src/debugserver/gstdebugserverwatcher.c
@@ -0,0 +1,95 @@
+/* GStreamer
+ * Copyright (C) 2015 Marcin Kolny <marcin kolny gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "gstdebugserverwatcher.h"
+
+void gst_debugserver_watcher_init (GstDebugserverWatcher * watcher, OkFunction ok_function,
+  GDestroyNotify hash_destroy, GCompareFunc cmp_func)
+{
+  watcher->clients = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, hash_destroy);
+  g_mutex_init (&watcher->mutex);
+  watcher->ok_function = ok_function;
+  watcher->cmp_function = cmp_func;
+}
+
+void gst_debugserver_watcher_deinit (GstDebugserverWatcher * watcher)
+{
+  g_mutex_lock (&watcher->mutex);
+  g_hash_table_destroy (watcher->clients);
+  g_mutex_unlock (&watcher->mutex);
+}
+
+void gst_debugserver_watcher_clean (GstDebugserverWatcher * watcher)
+{
+  g_mutex_lock (&watcher->mutex);
+  g_hash_table_remove_all (watcher->clients);
+  g_mutex_unlock (&watcher->mutex);
+}
+
+void gst_debugserver_watcher_send_data (GstDebugserverWatcher * watcher, GstDebugserverTcp * tcp_server, 
GstDebugger__GStreamerData * gst_data)
+{
+  GHashTableIter iter;
+  gpointer client, value;
+
+  g_mutex_lock (&watcher->mutex);
+  g_hash_table_iter_init (&iter, watcher->clients);
+  while (g_hash_table_iter_next (&iter, &client, &value)) {
+    if (watcher->ok_function (gst_data, value))
+      gst_debugserver_tcp_send_packet (tcp_server, (TcpClient*) client, gst_data);
+  }
+  g_mutex_unlock (&watcher->mutex);
+}
+
+gboolean gst_debugserver_watcher_add_watch (GstDebugserverWatcher * watcher, gpointer data, TcpClient * 
client)
+{
+  GSList *listeners =
+      (GSList *) g_hash_table_lookup (watcher->clients, client);
+
+  if (listeners == NULL) {
+    listeners = g_slist_append (listeners, data);
+    g_hash_table_insert (watcher->clients, client, listeners);
+    return TRUE;
+  }
+
+  if (g_slist_find_custom (listeners, data, watcher->cmp_function) == NULL) {
+    listeners = g_slist_append (listeners, data);
+    g_hash_table_steal (watcher->clients, client);
+    g_hash_table_insert (watcher->clients, client, listeners);
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+gboolean gst_debugserver_watcher_remove_watch (GstDebugserverWatcher * watcher,
+  gpointer data, TcpClient * client)
+{
+  GSList *listeners =
+      (GSList *) g_hash_table_lookup (watcher->clients, client);
+
+  GSList *l = g_slist_find_custom (listeners, data, watcher->cmp_function);
+  if (l == NULL) {
+    return FALSE;
+  } else {
+    listeners = g_slist_remove_link (listeners, l);
+    g_hash_table_steal (watcher->clients, client);
+    g_hash_table_insert (watcher->clients, client, listeners);
+    return TRUE;
+  }
+}
diff --git a/src/debugserver/gstdebugserverwatcher.h b/src/debugserver/gstdebugserverwatcher.h
new file mode 100644
index 0000000..445ad9d
--- /dev/null
+++ b/src/debugserver/gstdebugserverwatcher.h
@@ -0,0 +1,52 @@
+/* GStreamer
+ * Copyright (C) 2015 Marcin Kolny <marcin kolny gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __GST_DEBUGSERVER_WATCHER_H__
+#define __GST_DEBUGSERVER_WATCHER_H__
+
+#include "gstdebugservertcp.h"
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef gboolean (*OkFunction)(GstDebugger__GStreamerData*, gpointer);
+
+typedef struct {
+  GHashTable *clients;
+  GMutex mutex;
+  OkFunction ok_function;
+  GCompareFunc cmp_function;
+} GstDebugserverWatcher;
+
+void gst_debugserver_watcher_init (GstDebugserverWatcher * watcher, OkFunction ok_function, GDestroyNotify 
hash_destroy, GCompareFunc cmp_func);
+
+void gst_debugserver_watcher_deinit (GstDebugserverWatcher * watcher);
+
+void gst_debugserver_watcher_clean (GstDebugserverWatcher * watcher);
+
+gboolean gst_debugserver_watcher_add_watch (GstDebugserverWatcher * watcher,
+  gpointer data, TcpClient * client);
+
+gboolean gst_debugserver_watcher_remove_watch (GstDebugserverWatcher * watcher,
+  gpointer data, TcpClient * client);
+
+G_END_DECLS
+
+#endif
diff --git a/src/gst-debugger/Makefile.am b/src/gst-debugger/Makefile.am
index 4d361a8..b213570 100644
--- a/src/gst-debugger/Makefile.am
+++ b/src/gst-debugger/Makefile.am
@@ -14,92 +14,59 @@ BUILT_SOURCES = gst-debugger-resources.h
 
 bin_PROGRAMS = gst-debugger- GST_API_VERSION@
 
-gst_debugger_headers =                                 \
-       common_model_columns.h                          \
-       controller/base_controller.h                    \
-       controller/command_factory.h                    \
-       controller/connection_controller.h              \
-       controller/controller.h                         \
-       controller/element_path_processor.h             \
-       controller/iview.h                              \
-       controller/tcp_client.h                         \
-       controller/topology_controller.h                \
-       dialogs/buffer_data_dialog.h                    \
-       dialogs/connection_properties_dialog.h          \
-       dialogs/enums_dialog.h                          \
-       dialogs/factories_dialog.h                      \
-       dialogs/remote_data_dialog.h                    \
-       filter-parser/expression.h                      \
-       filter-parser/lexer.h                           \
-       filter-parser/parser.h                          \
-       filter-parser/tokens.h                          \
-       graphviz-plugin/graphviz-gstdebugger.h          \
-       gst-debugger-resources.h                        \
-       gvalue-converter/gvalue_base.h                  \
-       gvalue-converter/gvalue_boolean.h               \
-       gvalue-converter/gvalue_caps.h                  \
-       gvalue-converter/gvalue_enum.h                  \
-       gvalue-converter/gvalue_numeric.h               \
-       gvalue-converter/gvalue_string.h                \
-       main_window.h                                   \
-       models/gst_enum_model.h                         \
-       models/gst_factory_model.h                      \
-       models/gst_pipeline_model.h                     \
-       models/remote_data_container.h                  \
-       modules/base_main_module.h                      \
-       modules/bus_messages_module.h                   \
-       modules/control_module.h                        \
-       modules/filter_utils.h                          \
-       modules/gst_properties_module.h                 \
-       modules/log_module.h                            \
-       modules/main_module.h                           \
-       modules/pad_data_modules.h                      \
-       modules/pad_path_control_module.h               \
-       modules/pad_path_types_control_module.h         \
-       modules/types_control_module.h                  \
-       pipeline-drawer/graph_module.h                  \
-       pipeline-drawer/gst_bin_to_dot_converter.h      \
-       ui_utils.h                                      
-
-
 gst_debugger_ GST_API_VERSION@_SOURCES =               \
-       controller/command_factory.cpp                  \
-       controller/controller.cpp                       \
-       controller/tcp_client.cpp                       \
-       controller/topology_controller.cpp              \
-       dialogs/buffer_data_dialog.cpp                  \
-       dialogs/connection_properties_dialog.cpp        \
-       dialogs/enums_dialog.cpp                        \
-       dialogs/factories_dialog.cpp                    \
-       graphviz-plugin/gvdevice_gstdebugger.c          \
-       filter-parser/lexer.cpp                         \
-       filter-parser/parser.cpp                        \
-       filter-parser/tokens.cpp                        \
-       graphviz-plugin/gvplugin_gstdebugger.c          \
-       gst-debugger-resources.c                        \
-       gvalue-converter/gvalue_base.cpp                \
-       gvalue-converter/gvalue_boolean.cpp             \
-       gvalue-converter/gvalue_caps.cpp                \
-       gvalue-converter/gvalue_enum.cpp                \
-       gvalue-converter/gvalue_numeric.cpp             \
-       gvalue-converter/gvalue_string.cpp              \
-       main.cpp                                        \
-       main_window.cpp                                 \
-       models/gst_factory_model.cpp                    \
-       models/gst_pipeline_model.cpp                   \
-       modules/base_main_module.cpp                    \
-       modules/bus_messages_module.cpp                 \
-       modules/filter_utils.cpp                        \
-       modules/gst_properties_module.cpp               \
-       modules/log_module.cpp                          \
-       modules/main_module.cpp                         \
-       modules/pad_data_modules.cpp                    \
-       modules/pad_path_control_module.cpp             \
-       modules/types_control_module.cpp                \
-       pipeline-drawer/graph_module.cpp                \
-       pipeline-drawer/gst_bin_to_dot_converter.cpp    \
-       ui_utils.cpp                                    \
-       $(gst_debugger_headers)
+       main.cpp \
+       main_window.cpp \
+       main_window.h \
+       controller/controller.cpp \
+       controller/controller.h \
+       controller/command_factory.cpp \
+       controller/command_factory.h \
+       ui_utils.cpp \
+       ui_utils.h \
+       gst-debugger-resources.c \
+       gst-debugger-resources.h \
+       controller/base_controller.h \
+       controller/tcp_client.cpp \
+       controller/tcp_client.h \
+       dialogs/connection_properties_dialog.cpp \
+       dialogs/connection_properties_dialog.h \
+       modules/base_main_module.cpp \
+       modules/base_main_module.h \
+       modules/log_module.cpp \
+       modules/log_module.h \
+       modules/main_module.cpp \
+       modules/main_module.h \
+       controller/iview.h \
+       controller/topology_controller.cpp \
+       controller/topology_controller.h \
+       common_model_columns.h \
+       modules/message_module.cpp \
+       modules/message_module.h \
+       models/gst_enum_model.h \
+       models/gst_factory_model.cpp \
+       models/gst_factory_model.h \
+       models/gst_pipeline_model.cpp \
+       models/gst_pipeline_model.h \
+       modules/event_module.cpp \
+       modules/event_module.h \
+       modules/query_module.cpp \
+       modules/query_module.h \
+       pipeline-drawer/graph_module.cpp \
+       pipeline-drawer/graph_module.h \
+       pipeline-drawer/gst_bin_to_dot_converter.cpp \
+       pipeline-drawer/gst_bin_to_dot_converter.h \
+       graphviz-plugin/graphviz-gstdebugger.h \
+       graphviz-plugin/gvdevice_gstdebugger.c \
+       graphviz-plugin/gvplugin_gstdebugger.c \
+       controller/element_path_processor.h \
+       modules/qe_control_module.h \
+       dialogs/enums_dialog.cpp \
+       dialogs/enums_dialog.h \
+       dialogs/factories_dialog.cpp \
+       dialogs/factories_dialog.h \
+       modules/gst_properties_module.cpp \
+       modules/gst_properties_module.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 d2a78c5..9882c9c 100644
--- a/src/gst-debugger/controller/command_factory.cpp
+++ b/src/gst-debugger/controller/command_factory.cpp
@@ -9,88 +9,125 @@
 #include "common/common.h"
 #include "common/serializer.h"
 
-void CommandFactory::send_pad_watch_command(bool enable, PadWatch_WatchType watch_type, const std::string 
&pad_path, int qe_type)
+void CommandFactory::send_property_request_command(const std::string &element_path, const std::string 
&property_name)
 {
-       Command cmd;
-       PadWatch *pad_watch = new PadWatch();
-       pad_watch->set_toggle(enable ? ENABLE : DISABLE);
-       pad_watch->set_watch_type(watch_type);
-       pad_watch->set_pad_path(pad_path);
-       pad_watch->set_qe_type(qe_type);
-       cmd.set_command_type(Command_CommandType_PAD_WATCH);
-       cmd.set_allocated_pad_watch(pad_watch);
+       GstDebugger::Command cmd;
+       GstDebugger::PropertyRequest *request = new GstDebugger::PropertyRequest();
+       request->set_object(element_path);
+       request->set_name(property_name);
+       cmd.set_allocated_property(request);
 
        client->send_command(cmd);
 }
 
-void CommandFactory::send_property_request_command(const std::string &element_path, const std::string 
&property_name)
+
+void CommandFactory::send_request_entire_topology_command()
 {
-       Command cmd;
-       Property *property = new Property();
-       property->set_element_path(element_path);
-       property->set_property_name(property_name);
-       cmd.set_command_type(Command_CommandType_PROPERTY);
-       cmd.set_allocated_property(property);
+       GstDebugger::Command cmd;
+       cmd.set_entire_topology(true);
+
+       client->send_command(cmd);
+}
+
+GstDebugger::PadWatchRequest* CommandFactory::create_pad_watch_request(bool enable, const std::string 
&pad_path)
+{
+       GstDebugger::PadWatchRequest *request = new GstDebugger::PadWatchRequest();
+       request->set_pad(pad_path);
+       request->set_action(enable ? GstDebugger::ADD : GstDebugger::REMOVE);
+       return request;
+}
+
+void CommandFactory::send_query_request_command(bool enable, const std::string &pad_path, int type)
+{
+       auto request = create_pad_watch_request(enable, pad_path);
+       GstDebugger::QueryWatchRequest *ev_request = new GstDebugger::QueryWatchRequest();
+       ev_request->set_type(type);
+       request->set_allocated_query(ev_request);
+       GstDebugger::Command cmd;
+       cmd.set_allocated_pad_watch(request);
+
+       client->send_command(cmd);
+}
+
+void CommandFactory::send_event_request_command(bool enable, const std::string &pad_path, int type)
+{
+       auto request = create_pad_watch_request(enable, pad_path);
+       GstDebugger::EventWatchRequest *ev_request = new GstDebugger::EventWatchRequest();
+       ev_request->set_type(type);
+       request->set_allocated_event(ev_request);
+       GstDebugger::Command cmd;
+       cmd.set_allocated_pad_watch(request);
+
        client->send_command(cmd);
 }
 
 void CommandFactory::send_message_request_command(int message_type, bool enable)
 {
-       MessageWatch *msg_watch = new MessageWatch();
-       msg_watch->set_message_type(message_type);
-       msg_watch->set_toggle(enable ? ENABLE : DISABLE);
-       Command cmd;
-       cmd.set_command_type(Command_CommandType_MESSAGE_WATCH);
-       cmd.set_allocated_message_watch(msg_watch);
+       GstDebugger::MessageRequest *request = new GstDebugger::MessageRequest();
+       request->set_type(message_type);
+       request->set_action(enable ? GstDebugger::ADD : GstDebugger::REMOVE);
+       GstDebugger::Command cmd;
+       cmd.set_allocated_message(request);
 
        client->send_command(cmd);
 }
 
 void CommandFactory::send_set_threshold_command(const std::string &threshold_list, bool overwrite)
 {
-       Command cmd;
-       LogThreshold *log_threshold = new LogThreshold();
-       log_threshold->set_list(threshold_list);
-       log_threshold->set_overwrite(overwrite);
-       cmd.set_command_type(Command_CommandType_LOG_THRESHOLD);
-       cmd.set_allocated_log_threshold(log_threshold);
+       GstDebugger::Command cmd;
+       // todo overwrite
+       cmd.set_log_threshold(threshold_list);
+       client->send_command(cmd);
+}
+
+void CommandFactory::send_set_log_watch_command(bool enable, const std::string &category, int log_level)
+{
+       GstDebugger::Command cmd;
+       GstDebugger::LogRequest *request = new GstDebugger::LogRequest();
+       request->set_level(log_level);
+       request->set_action(enable ? GstDebugger::ADD : GstDebugger::REMOVE);
+       request->set_category(category);
+       cmd.set_allocated_log(request);
 
        client->send_command(cmd);
 }
 
-void CommandFactory::send_set_log_watch_command(bool enable, int log_level)
+void CommandFactory::send_data_type_request_command(const std::string &type_name, 
GstDebugger::TypeDescriptionRequest_Type type)
 {
-       Command cmd;
-       LogWatch *log_watch = new LogWatch();
-       log_watch->set_toggle(enable ? ENABLE : DISABLE);
-       log_watch->set_log_level(log_level);
-       cmd.set_command_type(Command_CommandType_LOG_WATCH);
-       cmd.set_allocated_log_watch(log_watch);
+       GstDebugger::Command cmd;
+       GstDebugger::TypeDescriptionRequest *request = new GstDebugger::TypeDescriptionRequest();
+       request->set_type(type);
+       request->set_name(type_name);
+       cmd.set_allocated_type_description(request);
 
        client->send_command(cmd);
 }
 
 void CommandFactory::send_request_debug_categories_command()
 {
-       Command cmd;
-       cmd.set_command_type(Command_CommandType_DEBUG_CATEGORIES);
+       GstDebugger::Command cmd;
+       cmd.set_debug_categories_list(true);
 
        client->send_command(cmd);
 }
 
-void CommandFactory::send_request_topology_command()
+void CommandFactory::send_request_factory_command(const std::string &factory_name)
 {
-       Command cmd;
-       cmd.set_command_type(Command_CommandType_TOPOLOGY);
+       GstDebugger::Command cmd;
+       auto rq = new GstDebugger::TypeDescriptionRequest();
+       rq->set_type(GstDebugger::TypeDescriptionRequest_Type_FACTORY);
+       rq->set_name(factory_name);
+       cmd.set_allocated_type_description(rq);
 
        client->send_command(cmd);
 }
 
-void CommandFactory::send_enum_type_request_command(const std::string &enum_name)
+
+/*
+void CommandFactory::send_request_topology_command()
 {
        Command cmd;
-       cmd.set_command_type(Command_CommandType_ENUM_TYPE);
-       cmd.set_enum_name(enum_name);
+       cmd.set_command_type(Command_CommandType_TOPOLOGY);
 
        client->send_command(cmd);
 }
@@ -113,14 +150,6 @@ void CommandFactory::send_property_command(const std::string &path, const std::s
        client->send_command(cmd);
 }
 
-void CommandFactory::send_request_factory(const std::string &factory_name)
-{
-       Command cmd;
-       cmd.set_command_type(Command_CommandType_FACTORY);
-       cmd.set_factory_name(factory_name);
-       client->send_command(cmd);
-}
-
 void CommandFactory::send_request_pad_dynamic_info(const std::string &pad_path)
 {
        Command cmd;
@@ -128,3 +157,4 @@ void CommandFactory::send_request_pad_dynamic_info(const std::string &pad_path)
        cmd.set_pad_path(pad_path);
        client->send_command(cmd);
 }
+*/
diff --git a/src/gst-debugger/controller/command_factory.h b/src/gst-debugger/controller/command_factory.h
index fa6b1c2..62c71cf 100644
--- a/src/gst-debugger/controller/command_factory.h
+++ b/src/gst-debugger/controller/command_factory.h
@@ -12,20 +12,25 @@
 
 #include "common/gstdebugger.pb.h"
 
+#include <boost/optional/optional.hpp>
+
 class CommandFactory : public virtual BaseController
 {
+       static GstDebugger::PadWatchRequest* create_pad_watch_request(bool enable, const std::string 
&pad_path);
+
 public:
-       void send_pad_watch_command(bool enable, PadWatch_WatchType watch_type, const std::string &pad_path, 
int qe_type);
        void send_property_request_command(const std::string &element_path, const std::string &property_name);
+       void send_event_request_command(bool enable, const std::string &pad_path, int type);
+       void send_query_request_command(bool enable, const std::string &pad_path, int type);
        void send_message_request_command(int message_type, bool enable);
        void send_set_threshold_command(const std::string &threshold_list, bool overwrite);
-       void send_set_log_watch_command(bool enable, int log_level);
+       void send_set_log_watch_command(bool enable, const std::string &category, int log_level);
+       void send_data_type_request_command(const std::string &type_name, 
GstDebugger::TypeDescriptionRequest_Type type);
        void send_request_debug_categories_command();
-       void send_request_topology_command();
-       void send_enum_type_request_command(const std::string &enum_name);
-       void send_property_command(const std::string &path, const std::string &property_name, GValue *gvalue);
-       void send_request_factory(const std::string &factory_name);
-       void send_request_pad_dynamic_info(const std::string &pad_path);
+       void send_request_entire_topology_command();
+       void send_request_factory_command(const std::string &factory_name);
+       /*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);*/
 };
 
 #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 618b321..fe7b567 100644
--- a/src/gst-debugger/controller/controller.cpp
+++ b/src/gst-debugger/controller/controller.cpp
@@ -6,23 +6,25 @@
  */
 
 #include "controller.h"
-#include "element_path_processor.h"
-
 #include "ui_utils.h"
 
-#include "common/common.h"
-#include "common/deserializer.h"
-#include "common/serializer.h"
-
 #include <gtkmm.h>
 
-#include <boost/algorithm/string/split.hpp>
-
 Controller::Controller(IMainView *view)
  : view(view)
 {
        client->signal_frame_received.connect(sigc::mem_fun(*this, &Controller::process_frame));
-       client->signal_status_changed.connect([this](bool connected) { if (!connected) client_disconnected(); 
});
+       client->signal_status_changed.connect([this](bool connected) {
+               if (!connected) client_disconnected();
+               else
+               {
+                       send_data_type_request_command("GstMessageType", 
GstDebugger::TypeDescriptionRequest_Type_ENUM_FLAGS);
+                       send_data_type_request_command("GstEventType", 
GstDebugger::TypeDescriptionRequest_Type_ENUM_FLAGS);
+                       send_data_type_request_command("GstQueryType", 
GstDebugger::TypeDescriptionRequest_Type_ENUM_FLAGS);
+                       send_request_entire_topology_command();
+                       send_request_debug_categories_command();
+               }
+       });
 }
 
 int Controller::run(int &argc, char **&argv)
@@ -32,37 +34,40 @@ int Controller::run(int &argc, char **&argv)
        return app->run(*view);
 }
 
-void Controller::send_command(const Command& cmd)
+void Controller::process_frame(const GstDebugger::GStreamerData &data)
 {
-       client->send_command(cmd);
-}
+       on_frame_received(data);
 
-void Controller::process_frame(const GstreamerInfo &info)
-{
-       switch (info.info_type())
+       switch (data.info_type_case())
        {
-       case GstreamerInfo_InfoType_TOPOLOGY:
-               process(info.topology());
+       case GstDebugger::GStreamerData::kDebugCategories:
+               debug_categories.clear();
+               for (auto c : data.debug_categories().category())
+                       debug_categories.push_back(c);
+               on_debug_categories_changed();
+               break;
+       case GstDebugger::GStreamerData::kEnumFlagsType:
+               update_enum_model(data.enum_flags_type());
+               on_enum_list_changed(data.enum_flags_type().type_name(), true);
+               break;
+       case GstDebugger::GStreamerData::kConfirmation:
+               on_confirmation_received(data.confirmation());
+               break;
+       case GstDebugger::GStreamerData::kTopologyInfo:
+               process(data.topology_info());
                on_model_changed(current_model);
 
-               // todo get info from process??
-               if (info.topology().type() == Topology_ObjectType_ELEMENT)
+               if (data.topology_info().has_element() && 
!get_factory(data.topology_info().element().factory_name()))
                {
-                       send_request_factory(info.topology().element().factory_name());
+                       send_request_factory_command(data.topology_info().element().factory_name());
                }
-
                break;
-       case GstreamerInfo_InfoType_DEBUG_CATEGORIES:
-       {
-               boost::split(debug_categories, info.debug_categories().list(), [](char c) { return c == ';'; 
});
-               debug_categories.erase(std::remove_if(debug_categories.begin(), debug_categories.end(),
-                               [](const std::string &s){return s.empty();}), debug_categories.end());
-               on_debug_categories_changed();
+       case GstDebugger::GStreamerData::kFactory:
+               update_factory_model(data.factory());
+               on_factory_list_changed(data.factory().name(), true);
                break;
        }
-       case GstreamerInfo_InfoType_LOG:
-               on_log_received(info.log());
-               break;
+       /*
        case GstreamerInfo_InfoType_PROPERTY:
        {
                std::string name = info.property().type_name();
@@ -74,22 +79,6 @@ void Controller::process_frame(const GstreamerInfo &info)
                on_property_received(info.property());
                break;
        }
-       case GstreamerInfo_InfoType_BUFFER:
-       case GstreamerInfo_InfoType_EVENT:
-       case GstreamerInfo_InfoType_QUERY:
-       case GstreamerInfo_InfoType_MESSAGE:
-               on_qebm_received(info.qebm(), info.info_type());
-               break;
-       case GstreamerInfo_InfoType_PAD_WATCH_CONFIRMATION:
-               on_pad_watch_confirmation_received(info.confirmation(), info.confirmation().watch_type());
-               break;
-       case GstreamerInfo_InfoType_MESSAGE_CONFIRMATION:
-               on_message_confirmation_received(info.bus_msg_confirmation());
-               break;
-       case GstreamerInfo_InfoType_ENUM_TYPE:
-               update_enum_model(info.enum_type());
-               on_enum_list_changed(info.enum_type().type_name(), true);
-               break;
        case GstreamerInfo_InfoType_FACTORY:
                update_factory_model(info.factory_info());
                on_factory_list_changed(info.factory_info().name());
@@ -99,9 +88,33 @@ void Controller::process_frame(const GstreamerInfo &info)
                break;
        default:
                break;
-       }
+       }*/
+}
+
+template<typename T>
+boost::optional<T> get_from_container(const std::vector<T>& container, const std::string &name, 
std::function<std::string(const T& val)> get_t_name)
+{
+       auto it = std::find_if(container.begin(), container.end(), [name, get_t_name](const T& enum_type) {
+               return get_t_name(enum_type) == name;
+       });
+
+       if (it == container.end())
+               return boost::none;
+       else
+               return *it;
+}
+
+boost::optional<GstEnumType> Controller::get_enum_type(const std::string &name)
+{
+       return get_from_container<GstEnumType>(enum_container, name, [](const GstEnumType& enum_type) {return 
enum_type.get_name(); } );
 }
 
+boost::optional<FactoryModel> Controller::get_factory(const std::string &name)
+{
+       return get_from_container<FactoryModel>(factory_container, name, [](const FactoryModel& factory) 
{return factory.get_name(); } );
+}
+
+
 void Controller::model_up()
 {
        if (current_model == ElementModel::get_root())
@@ -150,22 +163,35 @@ void Controller::set_selected_object(const std::string &name)
 
                if (obj && is_pad)
                {
-                       send_request_pad_dynamic_info(ElementPathProcessor::get_object_path(obj));
+               //      send_request_pad_dynamic_info(ElementPathProcessor::get_object_path(obj));
                }
        }
 }
 
-void Controller::update_enum_model(const EnumType &enum_type)
+void Controller::update_enum_model(const GstDebugger::EnumFlagsType &enum_type)
 {
-       GstEnumType et(enum_type.type_name(), enum_type.base_gtype());
-       for (int i = 0; i < enum_type.entry_size(); i++)
+       GstEnumType et(enum_type.type_name(), G_TYPE_ENUM); // todo G_TYPE_FLAGS
+       for (int i = 0; i < enum_type.values_size(); i++)
+       {
+               et.add_value(enum_type.values(i).name(), enum_type.values(i).value(), 
enum_type.values(i).nick());
+       }
+
+       // todo copy & paste get_enum_type()
+       auto it = std::find_if(enum_container.begin(), enum_container.end(), [enum_type](const GstEnumType& 
type) {
+               return type.get_name() == enum_type.type_name();
+       });
+
+       if (it == enum_container.end())
+       {
+               enum_container.push_back(et);
+       }
+       else
        {
-               et.add_value(enum_type.entry(i).name(), enum_type.entry(i).value(), 
enum_type.entry(i).nick());
+               *it = et;
        }
-       enum_container.update_item(et);
 }
 
-void Controller::update_factory_model(const FactoryInfo &factory_info)
+void Controller::update_factory_model(const GstDebugger::FactoryType &factory_info)
 {
        FactoryModel model(factory_info.name());
 
@@ -174,14 +200,26 @@ void Controller::update_factory_model(const FactoryInfo &factory_info)
                model.append_template(protocol_template_to_gst_template(factory_info.templates(i)));
        }
 
-       for (int i = 0; i < factory_info.meta_entries_size(); i++)
+       for (int i = 0; i < factory_info.metadata_size(); i++)
        {
-               model.append_meta(factory_info.meta_entries(i).key(), factory_info.meta_entries(i).value());
+               model.append_meta(factory_info.metadata(i).key(), factory_info.metadata(i).value());
        }
 
-       factory_container.update_item(model);
-}
+       // todo copy & paste get_enum_type()
+       auto it = std::find_if(factory_container.begin(), factory_container.end(), [model](const 
FactoryModel& type) {
+               return type.get_name() == model.get_name();
+       });
 
+       if (it == factory_container.end())
+       {
+               factory_container.push_back(model);
+       }
+       else
+       {
+               *it = model;
+       }
+}
+/*
 void Controller::append_property(const Property& property)
 {
        GValue *value = new GValue;
@@ -195,19 +233,19 @@ void Controller::append_property(const Property& property)
                this->send_property_command(property.element_path(), property.property_name(), 
gvalue->get_gvalue());
        });
 }
-
+*/
 void Controller::log(const std::string &message)
 {
        // todo date/time?
        std::cerr << message << std::endl;
 
-       on_new_log_entry(message);
+       //on_new_log_entry(message);
 }
 
 void Controller::client_disconnected()
 {
 
-       auto root_model = ElementModel::get_root();
+/*     auto root_model = ElementModel::get_root();
        root_model->clean_model();
        on_model_changed(root_model);
 
@@ -228,9 +266,9 @@ void Controller::client_disconnected()
        }
 
        debug_categories.clear();
-       on_debug_categories_changed();
+       on_debug_categories_changed();*/
 }
-
+/*
 void Controller::update_pad_dynamic_info(const PadDynamicInfo &info)
 {
        auto pad = std::dynamic_pointer_cast<PadModel>(ElementPathProcessor(info.pad_path()).get_last_obj());
@@ -245,4 +283,5 @@ void Controller::update_pad_dynamic_info(const PadDynamicInfo &info)
        {
                on_selected_object_changed();
        }
-}
+}*/
+
diff --git a/src/gst-debugger/controller/controller.h b/src/gst-debugger/controller/controller.h
index 16ed7f2..7f9cc62 100644
--- a/src/gst-debugger/controller/controller.h
+++ b/src/gst-debugger/controller/controller.h
@@ -8,48 +8,50 @@
 #ifndef SRC_GST_DEBUGGER_CONTROLLER_CONTROLLER_H_
 #define SRC_GST_DEBUGGER_CONTROLLER_CONTROLLER_H_
 
-#include "command_factory.h"
 #include "iview.h"
 #include "connection_controller.h"
+#include "command_factory.h"
 #include "topology_controller.h"
+
 #include "models/gst_enum_model.h"
-#include "models/remote_data_container.h"
 #include "models/gst_factory_model.h"
-#include "common/gstdebugger.pb.h"
+
+#include <boost/optional/optional.hpp>
 
 class Controller :
                public std::enable_shared_from_this<Controller>,
-               public CommandFactory,
                public ConnectionController,
+               public CommandFactory,
                public TopologyController
 {
 private:
        IMainView *view;
 
+       std::vector<GstEnumType> enum_container;
+       std::vector<FactoryModel> factory_container;
+       std::vector<std::string> debug_categories;
+
        std::shared_ptr<ObjectModel> selected_object;
 
-       RemoteDataContainer<GstEnumType> enum_container;
-       RemoteDataContainer<FactoryModel> factory_container;
-       std::vector<std::string> debug_categories;
 
+       void process_frame(const GstDebugger::GStreamerData& info);
 
-       void process_frame(const GstreamerInfo& info);
+       void update_enum_model(const GstDebugger::EnumFlagsType &enum_type);
+       void update_factory_model(const GstDebugger::FactoryType &factory_info);
 
-       void update_enum_model(const EnumType &enum_type);
+       /*
 
-       void update_factory_model(const FactoryInfo &factory_info);
 
        void append_property(const Property& property);
 
-       void client_disconnected();
-
        void update_pad_dynamic_info(const PadDynamicInfo& info);
+*/
+
+       void client_disconnected();
 
 public:
        Controller(IMainView *view);
 
-       void send_command(const Command& cmd);
-
        int run(int &argc, char **&argv);
 
        void model_up();
@@ -57,25 +59,27 @@ public:
 
        void set_selected_object(const std::string &name);
 
-       const RemoteDataContainer<GstEnumType>& get_enum_container() const { return enum_container; }
-       const RemoteDataContainer<FactoryModel>& get_factory_container() const { return factory_container; }
        const std::vector<std::string>& get_debug_categories() const { return debug_categories; }
 
+       boost::optional<GstEnumType> get_enum_type(const std::string &name);
+       boost::optional<FactoryModel> get_factory(const std::string &name);
+
+       const std::vector<FactoryModel>& get_factories() const { return factory_container; }
+       const std::vector<GstEnumType> get_enums() const { return enum_container; }
+
        std::shared_ptr<ObjectModel> get_selected_object() const { return selected_object; }
 
        void log(const std::string &message);
 
-       sigc::signal<void, const GstreamerLog&> on_log_received;
        sigc::signal<void> on_debug_categories_changed;
-       sigc::signal<void, std::shared_ptr<ElementModel>> on_model_changed;
-       sigc::signal<void, const Property&> on_property_received;
-       sigc::signal<void, const GstreamerQEBM&, GstreamerInfo_InfoType> on_qebm_received;
-       sigc::signal<void, const MessageWatch&> on_message_confirmation_received;
-       sigc::signal<void, const PadWatch&, PadWatch_WatchType> on_pad_watch_confirmation_received;
+       sigc::signal<void, const GstDebugger::GStreamerData&> on_frame_received;
+       sigc::signal<void, const GstDebugger::Command&> on_confirmation_received;
        sigc::signal<void, const Glib::ustring&, bool> on_enum_list_changed; /* enum name, true - add, false 
- remove */
+       sigc::signal<void, const Glib::ustring&, bool> on_factory_list_changed;
+       sigc::signal<void, std::shared_ptr<ElementModel>> on_model_changed;
+       sigc::signal<void, const GstDebugger::PropertyInfo&> on_property_received;
        sigc::signal<void> on_selected_object_changed;
-       sigc::signal<void, const Glib::ustring&> on_factory_list_changed;
-       sigc::signal<void, const Glib::ustring&> on_new_log_entry;
+/*     sigc::signal<void, const Glib::ustring&> on_new_log_entry;*/
 };
 
 #endif /* SRC_GST_DEBUGGER_CONTROLLER_CONTROLLER_H_ */
diff --git a/src/gst-debugger/controller/tcp_client.cpp b/src/gst-debugger/controller/tcp_client.cpp
index e33d428..f4de69f 100644
--- a/src/gst-debugger/controller/tcp_client.cpp
+++ b/src/gst-debugger/controller/tcp_client.cpp
@@ -56,13 +56,14 @@ void TcpClient::read_data()
                        m_buff = buffer;
                }
                gst_debugger_protocol_utils_read_requested_size(input_stream->gobj(), size, m_buff, 
cancel->gobj());
-               GstreamerInfo info;
-               info.ParseFromArray(m_buff, size);
+
+               GstDebugger::GStreamerData data;
+               data.ParseFromArray(m_buff, size);
                if (m_buff != buffer)
                {
                        delete m_buff;
                }
-               signal_frame_received(info);
+               signal_frame_received(data);
        }
 
        connected = false;
@@ -84,7 +85,7 @@ void TcpClient::write_data(char *data, int size)
        stream->write(data, size);
 }
 
-void TcpClient::send_command(const Command &cmd)
+void TcpClient::send_command(const GstDebugger::Command &cmd)
 {
        if (!is_connected())
                throw Gio::Error(Gio::Error::FAILED, "No connection!");
diff --git a/src/gst-debugger/controller/tcp_client.h b/src/gst-debugger/controller/tcp_client.h
index 9d8fdb2..e460a56 100644
--- a/src/gst-debugger/controller/tcp_client.h
+++ b/src/gst-debugger/controller/tcp_client.h
@@ -19,7 +19,7 @@
 class TcpClient
 {
 public:
-       typedef sigc::signal1<void, const GstreamerInfo&> frame_received_slot;
+       typedef sigc::signal1<void, const GstDebugger::GStreamerData&> frame_received_slot;
 
 private:
        Glib::RefPtr<Gio::SocketClient> client;
@@ -36,12 +36,13 @@ public:
        bool connect(const std::string &address, int port);
        bool disconnect();
        void write_data(char *data, int size);
-       void send_command(const Command &cmd);
+       void send_command(const GstDebugger::Command &gst_data);
 
        bool is_connected() const { return connected; }
 
        sigc::signal1<void, bool> signal_status_changed;
        frame_received_slot signal_frame_received;
+
 };
 
 #endif /* SRC_GST_DEBUGGER_GST_DEBUGGER_TCP_CLIENT_H_ */
diff --git a/src/gst-debugger/controller/topology_controller.cpp 
b/src/gst-debugger/controller/topology_controller.cpp
index 4a75cb2..b5cfc1a 100644
--- a/src/gst-debugger/controller/topology_controller.cpp
+++ b/src/gst-debugger/controller/topology_controller.cpp
@@ -12,19 +12,19 @@
 
 #include <boost/algorithm/string/split.hpp>
 
-void TopologyController::process(const Topology& topology)
+void TopologyController::process(const GstDebugger::TopologyInfo& topology)
 {
        lock_topology();
 
-       switch (topology.type())
+       switch (topology.topology_type_case())
        {
-       case Topology_ObjectType_ELEMENT:
+       case GstDebugger::TopologyInfo::kElement:
                process_element(topology.element(), topology.action());
                break;
-       case Topology_ObjectType_PAD:
+       case GstDebugger::TopologyInfo::kPad:
                process_pad(topology.pad(), topology.action());
                break;
-       case Topology_ObjectType_LINK:
+       case GstDebugger::TopologyInfo::kLink:
                process_link(topology.link(), topology.action());
                break;
        default:
@@ -34,7 +34,7 @@ void TopologyController::process(const Topology& topology)
        unlock_topology();
 }
 
-void TopologyController::process_element(const TopologyElement &element, Topology_Action action)
+void TopologyController::process_element(const GstDebugger::TopologyElement &element, GstDebugger::Action 
action)
 {
        ElementPathProcessor path_processor(element.path());
        auto parent = path_processor.get_parent_element();
@@ -43,10 +43,10 @@ void TopologyController::process_element(const TopologyElement &element, Topolog
 
        switch (action)
        {
-       case Topology_Action_ADD:
+       case GstDebugger::ADD:
                parent->add_child(std::make_shared<ElementModel>(path_processor.get_last_obj_str(), 
element.type_name(), element.is_bin()));
                break;
-       case Topology_Action_REMOVE:
+       case GstDebugger::REMOVE:
                parent->remove_child(path_processor.get_last_obj_str());
                break;
        default:
@@ -54,7 +54,7 @@ void TopologyController::process_element(const TopologyElement &element, Topolog
        }
 }
 
-void TopologyController::process_pad(const TopologyPad &pad, Topology_Action action)
+void TopologyController::process_pad(const GstDebugger::TopologyPad &pad, GstDebugger::Action action)
 {
        ElementPathProcessor path_processor(pad.path());
        auto parent = path_processor.get_parent_element();
@@ -63,27 +63,27 @@ void TopologyController::process_pad(const TopologyPad &pad, Topology_Action act
 
        switch (action)
        {
-       case Topology_Action_ADD:
+       case GstDebugger::ADD:
                parent->add_pad(std::make_shared<PadModel>(path_processor.get_last_obj_str(),
                                protocol_template_to_gst_template(pad.template_()),
                                pad.is_ghostpad(), static_cast<Gst::PadDirection>(pad.direction()),
                                static_cast<Gst::PadPresence>(pad.presence())));
                break;
-       case Topology_Action_REMOVE:
+       case GstDebugger::REMOVE:
                parent->remove_pad(path_processor.get_last_obj_str());
                break;
        }
 }
 
-void TopologyController::process_link(const TopologyLink &link, Topology_Action action)
+void TopologyController::process_link(const GstDebugger::TopologyLink &link, GstDebugger::Action action)
 {
-       ElementPathProcessor src_processor(link.src_pad_path()), sink_processor(link.sink_pad_path());
+       ElementPathProcessor src_processor(link.src_pad()), sink_processor(link.sink_pad());
        std::shared_ptr<PadModel> src = std::dynamic_pointer_cast<PadModel>(src_processor.get_last_obj()),
                        sink = std::dynamic_pointer_cast<PadModel>(sink_processor.get_last_obj());
 
        switch (action)
        {
-       case Topology_Action_ADD:
+       case GstDebugger::ADD:
                if (src == nullptr || sink == nullptr)
                        return;
                src->set_peer(sink);
@@ -92,7 +92,7 @@ void TopologyController::process_link(const TopologyLink &link, Topology_Action
                        sink->set_peer(src);
                }
                break;
-       case Topology_Action_REMOVE:
+       case GstDebugger::REMOVE:
        {
                std::shared_ptr<PadModel> empty;
                if (src != nullptr)
diff --git a/src/gst-debugger/controller/topology_controller.h 
b/src/gst-debugger/controller/topology_controller.h
index f932550..6c8f657 100644
--- a/src/gst-debugger/controller/topology_controller.h
+++ b/src/gst-debugger/controller/topology_controller.h
@@ -18,14 +18,14 @@ class TopologyController : public virtual BaseController
 {
        std::mutex m_topology;
 
-       void process_element(const TopologyElement &element, Topology_Action action);
-       void process_pad(const TopologyPad &pad, Topology_Action action);
-       void process_link(const TopologyLink &link, Topology_Action action);
+       void process_element(const GstDebugger::TopologyElement &element, GstDebugger::Action action);
+       void process_pad(const GstDebugger::TopologyPad &pad, GstDebugger::Action action);
+       void process_link(const GstDebugger::TopologyLink &link, GstDebugger::Action action);
 
 public:
        void lock_topology() { m_topology.lock(); }
        void unlock_topology() { m_topology.unlock(); }
-       void process(const Topology &topology);
+       void process(const GstDebugger::TopologyInfo &topology);
 };
 
 #endif /* SRC_GST_DEBUGGER_CONTROLLER_TOPOLOGY_CONTROLLER_H_ */
diff --git a/src/gst-debugger/dialogs/enums_dialog.cpp b/src/gst-debugger/dialogs/enums_dialog.cpp
index 9148d78..6407a73 100644
--- a/src/gst-debugger/dialogs/enums_dialog.cpp
+++ b/src/gst-debugger/dialogs/enums_dialog.cpp
@@ -34,7 +34,7 @@ void EnumsDialog::reload_list(const Glib::ustring& enum_name, bool add)
 {
        tree_model->clear();
 
-       for (auto enum_type : controller->get_enum_container())
+       for (auto enum_type : controller->get_enums())
        {
                auto row = *(tree_model->append());
                row[enums_columns.m_col_name] = enum_type.get_name();
diff --git a/src/gst-debugger/dialogs/factories_dialog.cpp b/src/gst-debugger/dialogs/factories_dialog.cpp
index 8ce9412..c397fbf 100644
--- a/src/gst-debugger/dialogs/factories_dialog.cpp
+++ b/src/gst-debugger/dialogs/factories_dialog.cpp
@@ -25,11 +25,13 @@ void FactoriesDialog::set_controller(const std::shared_ptr<Controller> &controll
 {
        IBaseView::set_controller(controller);
        controller->on_factory_list_changed.connect(sigc::mem_fun(*this, &FactoriesDialog::reload_list));
-       reload_list("");
+       reload_list("", true);
 }
 
-void FactoriesDialog::reload_list(const Glib::ustring &factory_name)
+void FactoriesDialog::reload_list(const Glib::ustring &factory_name, bool add)
 {
+       // todo if (add)
+
        tree_model->clear();
 
 #define APPEND_SUB_ROW(name, value, parent) \
@@ -40,7 +42,7 @@ void FactoriesDialog::reload_list(const Glib::ustring &factory_name)
                return childrow; \
        } ()
 
-       for (auto factory : controller->get_factory_container())
+       for (auto factory : controller->get_factories())
        {
                auto row = *(tree_model->append());
                row[factories_columns.m_col_name] = factory.get_name();
diff --git a/src/gst-debugger/dialogs/factories_dialog.h b/src/gst-debugger/dialogs/factories_dialog.h
index 1f7730b..344aaf9 100644
--- a/src/gst-debugger/dialogs/factories_dialog.h
+++ b/src/gst-debugger/dialogs/factories_dialog.h
@@ -29,7 +29,7 @@ class FactoriesDialog : public RemoteDataDialog
        FactoryModelColumns factories_columns;
        Glib::RefPtr<Gtk::TreeStore> factories_tree_model;
 
-       void reload_list(const Glib::ustring &factory_name);
+       void reload_list(const Glib::ustring &factory_name, bool add);
 
 public:
        FactoriesDialog(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& builder);
diff --git a/src/gst-debugger/main.cpp b/src/gst-debugger/main.cpp
index 3d6fc53..b8e7839 100644
--- a/src/gst-debugger/main.cpp
+++ b/src/gst-debugger/main.cpp
@@ -12,8 +12,6 @@
 #include <gtkmm.h>
 #include <gstreamermm.h>
 
-#include "filter-parser/parser.h"
-
 int main(int argc, char** argv)
 {
        Gst::init(argc, argv);
@@ -22,7 +20,7 @@ int main(int argc, char** argv)
        MainWindow* wnd_handler;
        builder->get_widget_derived("mainWindow", wnd_handler);
 
-        std::shared_ptr<Controller> controller(new Controller(wnd_handler));
+       std::shared_ptr<Controller> controller(new Controller(wnd_handler));
 
        controller->run(argc, argv);
 
diff --git a/src/gst-debugger/main_window.cpp b/src/gst-debugger/main_window.cpp
index c810c9f..3f0e5a3 100644
--- a/src/gst-debugger/main_window.cpp
+++ b/src/gst-debugger/main_window.cpp
@@ -19,10 +19,9 @@ MainWindow::MainWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>
   builder(builder),
   dispatcher(std::make_shared<Glib::Dispatcher>()),
   main_module(std::make_shared<MainModule>(builder)),
+  graph_module(std::make_shared<GraphModule>(builder)),
   properties_module(std::make_shared<GstPropertiesModule>(builder))
 {
-       graph_module = std::make_shared<GraphModule>(builder);
-
        builder->get_widget("connectionPropertiesMenuItem", connection_properties);
        connection_properties->signal_activate().connect(sigc::mem_fun(*this, 
&MainWindow::connectionPropertiesMenuItem_activate_cb));
 
@@ -77,7 +76,6 @@ void MainWindow::set_controller(const std::shared_ptr<Controller> &controller)
 
        main_module->set_controller(controller);
        graph_module->set_controller(controller);
-       properties_module->set_controller(controller);
 
        enums_dialog->set_controller(controller);
        enums_dialog->set_transient_for(*this);
@@ -85,6 +83,8 @@ void MainWindow::set_controller(const std::shared_ptr<Controller> &controller)
        factories_dialog->set_controller(controller);
        factories_dialog->set_transient_for(*this);
 
+       properties_module->set_controller(controller);
+
        connection_properties_dialog->set_transient_for(*this);
 }
 
@@ -117,4 +117,3 @@ void MainWindow::connection_status_changed(bool connected)
                ((Gtk::Label*)connect_menu_item->get_child())->set_text("Connect");
        }
 }
-
diff --git a/src/gst-debugger/main_window.h b/src/gst-debugger/main_window.h
index a813a07..44ca02b 100644
--- a/src/gst-debugger/main_window.h
+++ b/src/gst-debugger/main_window.h
@@ -8,18 +8,16 @@
 #ifndef SRC_GST_DEBUGGER_MAIN_WINDOW_H_
 #define SRC_GST_DEBUGGER_MAIN_WINDOW_H_
 
-#include "controller/tcp_client.h"
 #include "dialogs/connection_properties_dialog.h"
 #include "dialogs/enums_dialog.h"
 #include "dialogs/factories_dialog.h"
-#include "modules/gst_properties_module.h"
 #include "modules/main_module.h"
+#include "modules/gst_properties_module.h"
 #include "pipeline-drawer/graph_module.h"
 
-#include <gtkmm.h>
-
 #include "controller/iview.h"
-#include "models/gst_enum_model.h"
+
+#include <gtkmm.h>
 
 #include <map>
 
@@ -37,19 +35,18 @@ class MainWindow : public IMainView
        Gtk::MenuItem *about_menu_item;
        Gtk::MenuItem *quit_menu_item;
 
+       Gtk::AboutDialog *about_dialog;
+       Gtk::Statusbar *main_statusbar;
+
        ConnectionPropertiesDialog *connection_properties_dialog;
        EnumsDialog *enums_dialog;
        FactoriesDialog *factories_dialog;
-       Gtk::AboutDialog *about_dialog;
-       Gtk::Statusbar *main_statusbar;
 
        std::shared_ptr<Glib::Dispatcher> dispatcher;
        std::shared_ptr<MainModule> main_module;
        std::shared_ptr<GraphModule> graph_module;
        std::shared_ptr<GstPropertiesModule> properties_module;
 
-       GstreamerInfo info;
-
 public:
        MainWindow(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& builder);
        virtual ~MainWindow() {}
diff --git a/src/gst-debugger/models/gst_pipeline_model.cpp b/src/gst-debugger/models/gst_pipeline_model.cpp
index f2488cd..017b2d2 100644
--- a/src/gst-debugger/models/gst_pipeline_model.cpp
+++ b/src/gst-debugger/models/gst_pipeline_model.cpp
@@ -70,7 +70,7 @@ 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)
+/*void ElementModel::add_property(const std::string &name, const std::shared_ptr<GValueBase>& gvalue)
 {
        if (properties.find(name) == properties.end())
        {
@@ -81,7 +81,7 @@ void ElementModel::add_property(const std::string &name, const std::shared_ptr<G
                gvalue->update_gvalue(gvalue);
        }
 }
-
+*/
 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 803a9e7..3d233dd 100644
--- a/src/gst-debugger/models/gst_pipeline_model.h
+++ b/src/gst-debugger/models/gst_pipeline_model.h
@@ -111,7 +111,7 @@ 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);
+       //void add_property(const std::string &name, const std::shared_ptr<GValueBase>& gvalue);
 
        static std::shared_ptr<ElementModel> get_parent_element_from_path(const std::string &path);
 
diff --git a/src/gst-debugger/modules/base_main_module.cpp b/src/gst-debugger/modules/base_main_module.cpp
index 896433b..123d7e2 100644
--- a/src/gst-debugger/modules/base_main_module.cpp
+++ b/src/gst-debugger/modules/base_main_module.cpp
@@ -7,34 +7,50 @@
 
 #include "base_main_module.h"
 
+#include "controller/controller.h"
+
 DetailsModelColumns BaseMainModule::detail_columns;
 
-BaseMainModule::BaseMainModule()
-{
-       details_model = Gtk::ListStore::create(detail_columns);
-}
+inline void free_data(GstDebugger::GStreamerData* data) { delete data; }
 
-void BaseMainModule::configure_main_list_view(Gtk::TreeView *view)
+BaseMainModule::BaseMainModule(GstDebugger::GStreamerData::InfoTypeCase info_type, const std::string 
&module_name)
+: supported_info_type(info_type),
+  model(Gtk::ListStore::create(columns)),
+  details_model(Gtk::ListStore::create(detail_columns)),
+  module_name(module_name)
 {
-       view->remove_all_columns();
+       create_dispatcher("new-data", sigc::mem_fun(*this, &BaseMainModule::data_received_), 
(GDestroyNotify)free_data);
 
        filter = Gtk::TreeModelFilter::create(model);
        filter->set_visible_func([this](const Gtk::TreeModel::const_iterator& it){
                return filter_function(it);
        });
+}
 
+void BaseMainModule::configure_main_list_view(Gtk::TreeView *view)
+{
+       view->remove_all_columns();
        view->set_model(filter);
+       view->append_column(module_name, columns.header);
 }
 
 void BaseMainModule::load_details(Gtk::TreeView *view, const Gtk::TreeModel::Path &path)
 {
        details_model->clear();
        view->set_model(details_model);
+
+       Gtk::TreeModel::iterator iter = filter->get_iter(path);
+       if (!iter)
+       {
+               return;
+       }
+
+       load_details((*iter)[columns.data]);
 }
 
 void BaseMainModule::update_filter_expression(const std::string &expr)
 {
-       Parser p;
+/*     Parser p;
        auto prev = filter_expression;
        try
        {
@@ -45,7 +61,7 @@ void BaseMainModule::update_filter_expression(const std::string &expr)
        if (prev != filter_expression)
        {
                filter->refilter();
-       }
+       }*/
 }
 
 void BaseMainModule::configure_details_view(Gtk::TreeView *view)
@@ -72,14 +88,35 @@ void BaseMainModule::append_details_from_structure(Gst::Structure& structure)
                *tmp_val = G_VALUE_INIT;
                g_value_init(tmp_val, value.gobj()->g_type);
                g_value_copy(value.gobj(), tmp_val);
-               auto gvalue = GValueBase::build_gvalue(tmp_val);
-               if (gvalue == nullptr)
+               //auto gvalue = GValueBase::build_gvalue(tmp_val);
+               //if (gvalue == nullptr)
                        append_details_row(name, std::string("<unsupported type ") + 
g_type_name(G_VALUE_TYPE(value.gobj())) + ">");
-               else
-               {
-                       append_details_row(name, gvalue->to_string());
-                       delete gvalue;
-               }
+               //else
+               //{
+               //      append_details_row(name, gvalue->to_string());
+               //      delete gvalue;
+               //}
                return true;
        });
 }
+
+void BaseMainModule::data_received_()
+{
+       auto msg = gui_pop<GstDebugger::GStreamerData*>("new-data");
+       Gtk::TreeModel::Row row = *(model->append());
+       data_received(row, msg);
+       delete msg;
+}
+
+void BaseMainModule::set_controller(const std::shared_ptr<Controller> &controller)
+{
+       IBaseView::set_controller(controller);
+
+       controller->on_frame_received.connect([this] (const GstDebugger::GStreamerData &data) {
+               if (data.info_type_case() != supported_info_type)
+                       return;
+
+               gui_push("new-data", new GstDebugger::GStreamerData(data));
+               gui_emit("new-data");
+       });
+}
diff --git a/src/gst-debugger/modules/base_main_module.h b/src/gst-debugger/modules/base_main_module.h
index 6912f56..c7432a6 100644
--- a/src/gst-debugger/modules/base_main_module.h
+++ b/src/gst-debugger/modules/base_main_module.h
@@ -8,18 +8,37 @@
 #ifndef SRC_GST_DEBUGGER_MODULES_BASE_MAIN_MODULE_H_
 #define SRC_GST_DEBUGGER_MODULES_BASE_MAIN_MODULE_H_
 
-#include "controller/iview.h"
 #include "common_model_columns.h"
-#include "filter-parser/parser.h"
+
+#include "controller/iview.h"
+
+#include "common/gstdebugger.pb.h"
 
 #include <gtkmm/liststore.h>
 #include <gtkmm/treeview.h>
 #include <gtkmm/treemodel.h>
 
+class MainModuleModelColumns : public Gtk::TreeModel::ColumnRecord
+{
+public:
+       MainModuleModelColumns() {
+               add(header); add(data);
+       }
+
+       Gtk::TreeModelColumn<Glib::ustring> header;
+       Gtk::TreeModelColumn<gpointer> data;
+};
+
+
 class BaseMainModule : public IBaseView
 {
+       void data_received_();
+
+       GstDebugger::GStreamerData::InfoTypeCase supported_info_type;
+       std::string module_name;
+
 protected:
-       std::shared_ptr<Expression> filter_expression;
+       MainModuleModelColumns columns;
 
        static DetailsModelColumns detail_columns;
 
@@ -30,14 +49,17 @@ protected:
        void append_details_row(const std::string &name, const std::string &value);
        void append_details_from_structure(Gst::Structure& structure);
 
+       virtual void data_received(const Gtk::TreeModel::Row& row, GstDebugger::GStreamerData *data) = 0;
        virtual bool filter_function(const Gtk::TreeModel::const_iterator& it) { return true; }
 
+       virtual void load_details(gpointer data) = 0;
+
 public:
-       BaseMainModule();
+       BaseMainModule(GstDebugger::GStreamerData::InfoTypeCase info_type, const std::string &module_name);
        virtual ~BaseMainModule() {}
 
-       virtual void configure_main_list_view(Gtk::TreeView *view) = 0;
-       virtual void load_details(Gtk::TreeView *view, const Gtk::TreeModel::Path &path) = 0;
+       void configure_main_list_view(Gtk::TreeView *view);
+       void load_details(Gtk::TreeView *view, const Gtk::TreeModel::Path &path);
        virtual void details_activated(const Gtk::TreeModel::Path &path) {}
 
        static void configure_details_view(Gtk::TreeView *view);
@@ -45,6 +67,8 @@ public:
        void update_filter_expression(const std::string &expr);
 
        Glib::RefPtr<Gtk::ListStore> get_model() const { return model; }
+
+       void set_controller(const std::shared_ptr<Controller> &controller) override;
 };
 
 #endif /* SRC_GST_DEBUGGER_MODULES_BASE_MAIN_MODULE_H_ */
diff --git a/src/gst-debugger/modules/control_module.h b/src/gst-debugger/modules/control_module.h
index 465505b..2e9b8aa 100644
--- a/src/gst-debugger/modules/control_module.h
+++ b/src/gst-debugger/modules/control_module.h
@@ -15,111 +15,107 @@
 
 #include <gtkmm/widget.h>
 
-class ControlModule : public IBaseView
-{
-public:
-       virtual ~ControlModule() {};
-
-       virtual Gtk::Widget* get_widget() = 0;
-};
-
 class HooksModelColumns : public Gtk::TreeModel::ColumnRecord
 {
 public:
        HooksModelColumns() {
-               add(pad_path); add(qe_type_name); add(qe_type);
+               add(str1); add(str2); add(int1); add(int2);
        }
 
-       Gtk::TreeModelColumn<Glib::ustring> pad_path;
-       Gtk::TreeModelColumn<Glib::ustring> qe_type_name;
-       Gtk::TreeModelColumn<gint> qe_type;
+       Gtk::TreeModelColumn<Glib::ustring> str1;
+       Gtk::TreeModelColumn<Glib::ustring> str2;
+       Gtk::TreeModelColumn<gint> int1;
+       Gtk::TreeModelColumn<gint> int2;
 };
 
+inline void free_confirmation(GstDebugger::Command *cmd) { delete cmd; }
 
-class HooksControlModule : public ControlModule
+class ControlModule : public IBaseView
 {
-       Gtk::ScrolledWindow *wnd;
-
 protected:
-       PadWatch_WatchType watch_type;
-
        Glib::RefPtr<Gtk::ListStore> hooks_model;
        HooksModelColumns hooks_model_columns;
 
+       Gtk::Box *main_box;
+       Gtk::Button *add_watch_button;
+       Gtk::Button *remove_watch_button;
        Gtk::TreeView *hooks_tree_view;
-       Gtk::Box *main_box = nullptr;
-       Gtk::Button *remove_hook_button;
-       Gtk::Button *add_hook_button;
+       Gtk::ScrolledWindow *wnd;
 
-       void append_hook_widgets()
+       void confirmation_()
        {
-               main_box->pack_start(*add_hook_button, false, true);
-               main_box->pack_start(*Gtk::manage(new Gtk::Label("Existing hooks:")), false, true);
-
-               main_box->pack_start(*wnd, true, true);
-               main_box->pack_start(*remove_hook_button, false, true);
-
-               update_add_hook();
+               auto confirmation = gui_pop<GstDebugger::Command*>("confirmation");
+               confirmation_received(confirmation);
+               delete confirmation;
        }
 
-       virtual bool add_hook_unlocked() { return true; }
-
-       void update_add_hook()
+       template<typename T>
+       void remove_hook(const T& confirmation)
        {
-               add_hook_button->set_sensitive(add_hook_unlocked());
+               for (auto iter = hooks_model->children().begin();
+                               iter != hooks_model->children().end(); ++iter)
+               {
+                       if (hook_is_the_same(*iter, &confirmation))
+                       {
+                               hooks_model->erase(iter);
+                               break;
+                       }
+               }
        }
 
-       virtual int get_type() const { return -1; }
-       virtual std::string get_pad_path() const { return std::string(); }
+       virtual bool hook_is_the_same(const Gtk::TreeModel::Row& row, gconstpointer confirmation) = 0;
+       virtual void add_watch() {}
+       virtual void remove_watch(const Gtk::TreeModel::Row& row) {}
+       virtual void confirmation_received(GstDebugger::Command* cmd) {}
 
 public:
-       HooksControlModule(PadWatch_WatchType w_type)
-       : watch_type(w_type)
+       ControlModule()
        {
-               add_hook_button = Gtk::manage(new Gtk::Button("Add hook"));
-               add_hook_button->signal_clicked().connect([this]{
-                       if ((int)watch_type == -1)  // todo it has to be fixed on design protocol level
-                               controller->send_message_request_command(get_type(), true);
-                       else
-                               controller->send_pad_watch_command(true, watch_type, get_pad_path(), 
get_type());
-               });
+               main_box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
 
-               wnd = Gtk::manage(new Gtk::ScrolledWindow);
+               add_watch_button = Gtk::manage(new Gtk::Button("Add watch"));
+               add_watch_button->signal_clicked().connect([this] {
+                       add_watch();
+               });
+               main_box->pack_start(*add_watch_button, false, true);
 
                hooks_tree_view = Gtk::manage(new Gtk::TreeView());
+               wnd = Gtk::manage(new Gtk::ScrolledWindow);
                wnd->add(*hooks_tree_view);
+               main_box->pack_start(*wnd, true, true);
                hooks_model = Gtk::ListStore::create(hooks_model_columns);
                hooks_tree_view->set_model(hooks_model);
 
-               remove_hook_button = Gtk::manage(new Gtk::Button("Remove selected hook"));
-               remove_hook_button->signal_clicked().connect([this]{
+               remove_watch_button = Gtk::manage(new Gtk::Button("Remove watch"));
+               main_box->pack_start(*remove_watch_button, false, true);
+               remove_watch_button->signal_clicked().connect([this]{
                        auto selection = hooks_tree_view->get_selection();
                        if (!selection) return;
                        auto iter = selection->get_selected();
                        if (!iter) return;
-                       Gtk::TreeModel::Row row = *iter;
-                       auto type = row[hooks_model_columns.qe_type];
-                       auto pad_path = (Glib::ustring)row[hooks_model_columns.pad_path];
-
-                       if ((int)watch_type == -1)  // todo
-                               controller->send_message_request_command(type, false);
-                       else
-                               controller->send_pad_watch_command(false, watch_type, pad_path, type);
+                       remove_watch(*iter);
                });
+
+               create_dispatcher("confirmation", sigc::mem_fun(*this, &ControlModule::confirmation_), 
(GDestroyNotify)free_confirmation);
        }
 
-       virtual ~HooksControlModule() {}
+       virtual ~ControlModule() {};
 
-       Gtk::Widget* get_widget() override
+       Gtk::Widget* get_widget()
        {
-               if (main_box == nullptr)
-               {
-                       main_box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL)); // todo possible 
memleak
-
-                       append_hook_widgets();
-               }
                return main_box;
        }
+
+       void set_controller(const std::shared_ptr<Controller> &controller)
+       {
+               IBaseView::set_controller(controller);
+
+                       controller->on_confirmation_received.connect([this](const GstDebugger::Command& 
command) {
+
+                       gui_push("confirmation", new GstDebugger::Command(command));
+                       gui_emit("confirmation");
+               });
+       }
 };
 
 #endif /* SRC_GST_DEBUGGER_MODULES_CONTROL_MODULE_H_ */
diff --git a/src/gst-debugger/modules/event_module.cpp b/src/gst-debugger/modules/event_module.cpp
new file mode 100644
index 0000000..c8ceaad
--- /dev/null
+++ b/src/gst-debugger/modules/event_module.cpp
@@ -0,0 +1,79 @@
+/*
+ * event_module.cpp
+ *
+ *  Created on: Sep 29, 2015
+ *      Author: loganek
+ */
+
+#include "event_module.h"
+
+#include "controller/controller.h"
+
+EventModule::EventModule()
+: BaseMainModule(GstDebugger::GStreamerData::kEventInfo, "Events")
+{
+}
+
+void EventModule::load_details(gpointer data)
+{
+       auto evt_info = (GstDebugger::EventInfo*)data;
+
+       append_details_row("event type", Gst::Enums::get_name((Gst::EventType)evt_info->type()));
+       {
+               gchar buffer[20];
+               snprintf(buffer, 20, "%" GST_TIME_FORMAT, GST_TIME_ARGS(evt_info->timestamp()));
+               append_details_row("event timestamp", buffer);
+       }
+       append_details_row("event sequence number", std::to_string(evt_info->seqnum()));
+       append_details_row("sent from pad", evt_info->pad());
+
+       auto structure = Glib::wrap(gst_structure_from_string(evt_info->structure_data().c_str(), NULL), 
false);
+       append_details_from_structure(structure);
+}
+
+void EventModule::data_received(const Gtk::TreeModel::Row& row, GstDebugger::GStreamerData *data)
+{
+       row[columns.header] = "Event of type: " + 
Gst::Enums::get_name((Gst::EventType)data->event_info().type());
+       row[columns.data] = new GstDebugger::EventInfo(data->event_info());
+}
+
+EventControlModule::EventControlModule()
+: ControlModule(),
+  QEControlModule("GstEventType")
+{
+}
+
+void EventControlModule::add_watch()
+{
+       auto it = types_combobox->get_active();
+       if (it)
+       {
+               Gtk::TreeModel::Row row = *it;
+               controller->send_event_request_command(true, get_pad_path(), 
row[types_model_columns.type_id]);
+       }
+}
+
+void EventControlModule::remove_watch(const Gtk::TreeModel::Row& row)
+{
+       Glib::ustring pad = row[hooks_model_columns.str2];
+       controller->send_event_request_command(false, pad, row[hooks_model_columns.int1]);
+}
+
+void EventControlModule::confirmation_received(GstDebugger::Command* cmd)
+{
+       if (!cmd->has_pad_watch() || !cmd->pad_watch().has_event())
+               return;
+
+       auto confirmation = cmd->pad_watch();
+       if (confirmation.action() == GstDebugger::ADD)
+       {
+               Gtk::TreeModel::Row row = *(hooks_model->append());
+               row[hooks_model_columns.str1] = 
Gst::Enums::get_name(static_cast<Gst::EventType>(confirmation.event().type()));
+               row[hooks_model_columns.str2] = confirmation.pad();
+               row[hooks_model_columns.int1] = confirmation.event().type();
+       }
+       else
+       {
+               remove_hook(confirmation);
+       }
+}
diff --git a/src/gst-debugger/modules/event_module.h b/src/gst-debugger/modules/event_module.h
new file mode 100644
index 0000000..8cb7cc9
--- /dev/null
+++ b/src/gst-debugger/modules/event_module.h
@@ -0,0 +1,37 @@
+/*
+ * event_module.h
+ *
+ *  Created on: Sep 29, 2015
+ *      Author: loganek
+ */
+
+#ifndef SRC_GST_DEBUGGER_MODULES_EVENT_MODULE_H_
+#define SRC_GST_DEBUGGER_MODULES_EVENT_MODULE_H_
+
+#include "base_main_module.h"
+#include "control_module.h"
+#include "qe_control_module.h"
+
+class EventModule : public BaseMainModule
+{
+       void data_received(const Gtk::TreeModel::Row& row, GstDebugger::GStreamerData *data) override;
+       void load_details(gpointer data) override;
+
+public:
+       EventModule();
+       virtual ~EventModule() {}
+};
+
+class EventControlModule : virtual public ControlModule, public QEControlModule
+{
+       void confirmation_received(GstDebugger::Command* cmd) override;
+
+       void add_watch() override;
+       void remove_watch(const Gtk::TreeModel::Row& row) override;
+
+public:
+       EventControlModule();
+       virtual ~EventControlModule() {}
+};
+
+#endif /* SRC_GST_DEBUGGER_MODULES_EVENT_MODULE_H_ */
diff --git a/src/gst-debugger/modules/gst_properties_module.cpp 
b/src/gst-debugger/modules/gst_properties_module.cpp
index 8950424..9a995d2 100644
--- a/src/gst-debugger/modules/gst_properties_module.cpp
+++ b/src/gst-debugger/modules/gst_properties_module.cpp
@@ -6,7 +6,6 @@
  */
 
 #include "gst_properties_module.h"
-#include "gvalue-converter/gvalue_enum.h"
 #include "common/deserializer.h"
 #include "controller/command_factory.h"
 #include "controller/controller.h"
@@ -15,7 +14,7 @@
 
 #include <gst/gst.h>
 
-static void free_properties(Property *property) { delete property; }
+static void free_properties(GstDebugger::PropertyInfo *property) { delete property; }
 
 GstPropertiesModule::GstPropertiesModule(const Glib::RefPtr<Gtk::Builder>& builder)
 {
@@ -35,9 +34,9 @@ void GstPropertiesModule::set_controller(const std::shared_ptr<Controller> &cont
        controller->on_selected_object_changed.connect(sigc::mem_fun(*this, 
&GstPropertiesModule::selected_object_changed));
 }
 
-void GstPropertiesModule::new_property(const Property &property)
+void GstPropertiesModule::new_property(const GstDebugger::PropertyInfo &property)
 {
-       gui_push("property", new Property (property));
+       gui_push("property", new GstDebugger::PropertyInfo(property));
        gui_emit("property");
 }
 
@@ -66,15 +65,15 @@ void GstPropertiesModule::showPropertiesButton_clicked_cb()
 
 void GstPropertiesModule::new_property_()
 {
-       auto property = gui_pop<Property*>("property");
+       auto property = gui_pop<GstDebugger::PropertyInfo*>("property");
 
-       auto element = 
std::dynamic_pointer_cast<ElementModel>(ElementPathProcessor(property->element_path()).get_last_obj());
+       auto element = 
std::dynamic_pointer_cast<ElementModel>(ElementPathProcessor(property->object()).get_last_obj());
        if (!element)
        {
                return;
        }
 
-       std::shared_ptr<GValueBase> value_base = element->get_property(property->property_name());
+       /* 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);
 
        auto& container = const_cast<RemoteDataContainer<GstEnumType>&>(controller->get_enum_container());
@@ -86,11 +85,11 @@ void GstPropertiesModule::new_property_()
        if (!update_property(value_base, property))
        {
                append_property(value_base, property);
-       }
+       }*/
        delete property;
 }
 
-bool GstPropertiesModule::update_property(const std::shared_ptr<GValueBase>& value_base, Property *property)
+/*bool GstPropertiesModule::update_property(const std::shared_ptr<GValueBase>& value_base, 
GstDebugger::PropertyInfo *property)
 {
        for (auto internal_box : properties_box->get_children())
        {
@@ -107,7 +106,7 @@ bool GstPropertiesModule::update_property(const std::shared_ptr<GValueBase>& val
                {
                        if (label == nullptr && (label = dynamic_cast<Gtk::Label*>(cd)) != nullptr)
                        {
-                               if (label->get_text() != property->property_name())
+                               if (label->get_text() != property->name())
                                {
                                        label = nullptr;
                                        break;
@@ -133,15 +132,15 @@ bool GstPropertiesModule::update_property(const std::shared_ptr<GValueBase>& val
        }
 
        return false;
-}
-
-void GstPropertiesModule::append_property(const std::shared_ptr<GValueBase>& value_base, Property *property)
+}*/
+/*
+void GstPropertiesModule::append_property(const std::shared_ptr<GValueBase>& value_base, 
GstDebugger::PropertyInfo *property)
 {
        Gtk::Box *hbox = new Gtk::Box (Gtk::ORIENTATION_HORIZONTAL, 0);
        hbox->show();
-       auto prop_name = property->property_name();
+       auto prop_name = property->name();
        Gtk::Label *lbl = Gtk::manage(new Gtk::Label(prop_name));
-       lbl->set_tooltip_text(property->description());
+       lbl->set_tooltip_text(property->blurb());
        lbl->show();
        Gtk::Button *btn = Gtk::manage(new Gtk::Button("Refresh"));
        btn->signal_clicked().connect([this, prop_name] {request_selected_element_property(prop_name);});
@@ -154,7 +153,7 @@ void GstPropertiesModule::append_property(const std::shared_ptr<GValueBase>& val
        hbox->pack_start(*btn, false, false);
        properties_box->pack_start(*hbox);
 }
-
+*/
 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 1ee25eb..9b72ca7 100644
--- a/src/gst-debugger/modules/gst_properties_module.h
+++ b/src/gst-debugger/modules/gst_properties_module.h
@@ -25,13 +25,13 @@ private:
 
        std::string previous_element_path;
 
-       void append_property(const std::shared_ptr<GValueBase>& value_base, Property *property);
-       bool update_property(const std::shared_ptr<GValueBase>& value_base, Property *property);
+//     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 request_selected_element_property(const std::string &property_name);
 
        void show_pad_properties();
 
-       void new_property(const Property& property);
+       void new_property(const GstDebugger::PropertyInfo& property);
        void new_property_();
 
        void selected_object_changed();
diff --git a/src/gst-debugger/modules/log_module.cpp b/src/gst-debugger/modules/log_module.cpp
index a6b101e..b6cab95 100644
--- a/src/gst-debugger/modules/log_module.cpp
+++ b/src/gst-debugger/modules/log_module.cpp
@@ -9,64 +9,33 @@
 
 #include "controller/controller.h"
 
-static void free_log(GstreamerLog *log) { delete log; }
-
 LogModule::LogModule()
+: BaseMainModule(GstDebugger::GStreamerData::kLogInfo, "logs")
 {
-       model = Gtk::ListStore::create(columns);
-
-       create_dispatcher("new-log", sigc::mem_fun(*this, &LogModule::log_received_), 
(GDestroyNotify)free_log);
-}
-
-void LogModule::configure_main_list_view(Gtk::TreeView *view)
-{
-       BaseMainModule::configure_main_list_view(view);
-       view->append_column("Logs", columns.header);
 }
 
-void LogModule::load_details(Gtk::TreeView *view, const Gtk::TreeModel::Path &path)
+void LogModule::load_details(gpointer data)
 {
-       BaseMainModule::load_details(view, path);
-
-       Gtk::TreeModel::iterator iter = filter->get_iter(path);
-       if (!iter)
-       {
-               return;
-       }
-
-       Gtk::TreeModel::Row row = *iter;
-       auto log_info = (GstreamerLog*)row[columns.log];
+       auto log_info = (GstDebugger::LogInfo*)data;
 
        append_details_row("Level", std::to_string(log_info->level()));
-       append_details_row("Category name", log_info->category_name());
+       append_details_row("Category name", log_info->category());
        append_details_row("File", log_info->file());
        append_details_row("Function", log_info->function());
        append_details_row("Line", std::to_string(log_info->line()));
-       append_details_row("Object path", log_info->object_path());
+       append_details_row("Object path", log_info->object());
        append_details_row("Message", log_info->message());
 }
 
-void LogModule::set_controller(const std::shared_ptr<Controller> &controller)
+void LogModule::data_received(const Gtk::TreeModel::Row& row, GstDebugger::GStreamerData *data)
 {
-       BaseMainModule::set_controller(controller);
-
-       controller->on_log_received.connect([this] (const GstreamerLog &log) {
-               gui_push("new-log", new GstreamerLog (log));
-               gui_emit("new-log");
-       });
-}
-
-void LogModule::log_received_()
-{
-       auto log = gui_pop<GstreamerLog*>("new-log");
-       Gtk::TreeModel::Row row = *(model->append());
-       row[columns.header] = log->function();
-       row[columns.log] = log;
+       row[columns.header] = data->log_info().function();
+       row[columns.data] = new GstDebugger::LogInfo(data->log_info());
 }
 
 bool LogModule::filter_function(const Gtk::TreeModel::const_iterator& it)
 {
-       if (!filter_expression)
+/*     if (!filter_expression)
                return true;
 
        auto log = it->get_value(columns.log);
@@ -102,22 +71,24 @@ bool LogModule::filter_function(const Gtk::TreeModel::const_iterator& it)
        MAKE_FIELD_FILTER("function", function, TokenString);
        MAKE_FIELD_FILTER("object_path", object_path, TokenString);
        MAKE_FIELD_FILTER("message", message, TokenString);
-
+*/
        return true;
 }
 
 LogControlModule::LogControlModule()
+: ControlModule()
 {
-       main_box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
+       auto lbl = Gtk::manage(new Gtk::Label("Debug categories"));
+       main_box->pack_start(*lbl, false, true);
+       main_box->reorder_child(*lbl, 0);
 
-       set_watch_button = Gtk::manage(new Gtk::CheckButton("Watch log messages"));
-       set_watch_button->signal_toggled().connect([this] {
-               controller->send_set_log_watch_command(set_watch_button->get_active(), 10); // todo log level
-       });
-       main_box->pack_start(*set_watch_button, false, true);
+       debug_categories_combobox = Gtk::manage(new Gtk::ComboBoxText());
+       main_box->pack_start(*debug_categories_combobox, false, true);
+       main_box->reorder_child(*debug_categories_combobox, 1);
 
-       main_box->pack_start(*Gtk::manage(new Gtk::Label("Debug categories")), false, true);
-       main_box->pack_start(*Gtk::manage(new Gtk::ComboBox()), false, true);
+       log_level_entry = Gtk::manage(new Gtk::Entry());
+       main_box->pack_start(*log_level_entry, false, true);
+       main_box->reorder_child(*log_level_entry, 0);
 
        main_box->pack_start(*Gtk::manage(new Gtk::Label("Log threshold:")), false, true);
 
@@ -133,9 +104,54 @@ LogControlModule::LogControlModule()
                        overwrite_threshold_check_button->get_active());
        });
        main_box->pack_start(*set_threshold_button, false, true);
+
+       hooks_tree_view->append_column("Level", hooks_model_columns.str1);
+       hooks_tree_view->append_column("Category", hooks_model_columns.str2);
 }
 
-Gtk::Widget* LogControlModule::get_widget()
+void LogControlModule::set_controller(const std::shared_ptr<Controller> &controller)
 {
-       return main_box;
+       ControlModule::set_controller(controller);
+
+       controller->on_debug_categories_changed.connect([this] {
+               debug_categories_combobox->remove_all();
+               for (auto c : this->controller->get_debug_categories())
+               {
+                       debug_categories_combobox->append(c);
+               }
+               if (!this->controller->get_debug_categories().empty())
+                       debug_categories_combobox->set_active(0);
+       });
+}
+
+void LogControlModule::add_watch()
+{
+       controller->send_set_log_watch_command(true, debug_categories_combobox->get_active_text(),
+                       atoi(log_level_entry->get_text().c_str()));
+}
+
+void LogControlModule::remove_watch(const Gtk::TreeModel::Row& row)
+{
+       Glib::ustring category = row[hooks_model_columns.str2];
+       int level = row[hooks_model_columns.int1];
+       controller->send_set_log_watch_command(false, category, level);
+}
+
+void LogControlModule::confirmation_received(GstDebugger::Command* cmd)
+{
+       if (!cmd->has_log())
+               return;
+
+       auto confirmation = cmd->log();
+       if (confirmation.action() == GstDebugger::ADD)
+       {
+               Gtk::TreeModel::Row row = *(hooks_model->append());
+               row[hooks_model_columns.str1] = gst_debug_level_get_name 
(static_cast<GstDebugLevel>(confirmation.level()));
+               row[hooks_model_columns.int1] = confirmation.level();
+               row[hooks_model_columns.str2] = confirmation.category();
+       }
+       else
+       {
+               remove_hook(confirmation);
+       }
 }
diff --git a/src/gst-debugger/modules/log_module.h b/src/gst-debugger/modules/log_module.h
index 048bacb..7c39163 100644
--- a/src/gst-debugger/modules/log_module.h
+++ b/src/gst-debugger/modules/log_module.h
@@ -11,24 +11,10 @@
 #include "base_main_module.h"
 #include "control_module.h"
 
-class GstreamerLog;
-
-class LogModelColumns : public Gtk::TreeModel::ColumnRecord
-{
-public:
-       LogModelColumns() {
-               add(header); add(log);
-       }
-
-       Gtk::TreeModelColumn<Glib::ustring> header;
-       Gtk::TreeModelColumn<GstreamerLog*> log;
-};
-
 class LogModule : public BaseMainModule
 {
-       void log_received_();
-
-       LogModelColumns columns;
+       void data_received(const Gtk::TreeModel::Row& row, GstDebugger::GStreamerData *data) override;
+       void load_details(gpointer data) override;
 
 protected:
        bool filter_function(const Gtk::TreeModel::const_iterator& it) override;
@@ -36,26 +22,32 @@ protected:
 public:
        LogModule();
        virtual ~LogModule() {}
-
-       void configure_main_list_view(Gtk::TreeView *view) override;
-       void load_details(Gtk::TreeView *view, const Gtk::TreeModel::Path &path) override;
-
-       void set_controller(const std::shared_ptr<Controller> &controller) override;
 };
 
 class LogControlModule : public ControlModule
 {
-       Gtk::Box *main_box;
-       Gtk::CheckButton *set_watch_button;
        Gtk::CheckButton *overwrite_threshold_check_button;
+       Gtk::Entry *log_level_entry;
+       Gtk::ComboBoxText *debug_categories_combobox;
        Gtk::Button *set_threshold_button;
        Gtk::Entry *threshold_entry;
 
+       void add_watch() override;
+       void remove_watch(const Gtk::TreeModel::Row& row) override;
+       void confirmation_received(GstDebugger::Command* cmd) override;
+
+       bool hook_is_the_same(const Gtk::TreeModel::Row& row, gconstpointer confirmation) override
+       {
+               auto log = reinterpret_cast<const GstDebugger::LogRequest*>(confirmation);
+               return row[hooks_model_columns.int1] == log->level() &&
+                       row[hooks_model_columns.str2] == log->category();
+       }
+
 public:
        LogControlModule();
        virtual ~LogControlModule() {}
 
-       Gtk::Widget* get_widget() override;
+       void set_controller(const std::shared_ptr<Controller> &controller) override;
 };
 
 #endif /* SRC_GST_DEBUGGER_MODULES_LOG_MODULE_H_ */
diff --git a/src/gst-debugger/modules/main_module.cpp b/src/gst-debugger/modules/main_module.cpp
index 93a1901..d90eabd 100644
--- a/src/gst-debugger/modules/main_module.cpp
+++ b/src/gst-debugger/modules/main_module.cpp
@@ -7,10 +7,12 @@
 
 #include "main_module.h"
 
-#include "pad_data_modules.h"
+//#include "pad_data_modules.h"
 #include "log_module.h"
-#include "bus_messages_module.h"
-#include "pad_path_types_control_module.h"
+#include "message_module.h"
+#include "event_module.h"
+#include "query_module.h"
+//#include "pad_path_types_control_module.h"
 
 #include "controller/controller.h"
 #include "controller/element_path_processor.h"
@@ -40,16 +42,16 @@ void MainModule::load_submodules(const Glib::RefPtr<Gtk::Builder>& builder)
        submodules["logMessages"].control_module = std::make_shared<LogControlModule>();
 
        submodules["queries"].display_module = std::make_shared<QueryModule>();
-       submodules["queries"].control_module = std::make_shared<PadPathTypesControlModule>("GstQueryType", 
PadWatch_WatchType_QUERY);
+       submodules["queries"].control_module = std::make_shared<QueryControlModule>();
 
-       submodules["busMessages"].display_module = std::make_shared<BusMessagesModule>();
-       submodules["busMessages"].control_module = std::make_shared<TypesControlModule>("GstMessageType", 
(PadWatch_WatchType)-1);
+       submodules["busMessages"].display_module = std::make_shared<MessageModule>();
+       submodules["busMessages"].control_module = std::make_shared<MessageControlModule>();
 
-       submodules["buffers"].display_module = std::make_shared<BufferModule>();
+       /*submodules["buffers"].display_module = std::make_shared<BufferModule>();
        submodules["buffers"].control_module = 
std::make_shared<PadPathControlModule>(PadWatch_WatchType_BUFFER);
-
+*/
        submodules["events"].display_module = std::make_shared<EventModule>();
-       submodules["events"].control_module = std::make_shared<PadPathTypesControlModule>("GstEventType", 
PadWatch_WatchType_EVENT);
+       submodules["events"].control_module = std::make_shared<EventControlModule>();
 
        for (auto m : submodules)
        {
@@ -69,7 +71,7 @@ void MainModule::set_controller(const std::shared_ptr<Controller> &controller)
 {
        IBaseView::set_controller(controller);
 
-       controller->on_selected_object_changed.connect([this]{gui_emit("selected-object");});
+       //controller->on_selected_object_changed.connect([this]{gui_emit("selected-object");});
 
        for (auto m : submodules)
        {
diff --git a/src/gst-debugger/modules/message_module.cpp b/src/gst-debugger/modules/message_module.cpp
new file mode 100644
index 0000000..c0e8a8a
--- /dev/null
+++ b/src/gst-debugger/modules/message_module.cpp
@@ -0,0 +1,113 @@
+/*
+ * message_module.cpp
+ *
+ *  Created on: Sep 27, 2015
+ *      Author: loganek
+ */
+
+#include "message_module.h"
+
+#include "controller/controller.h"
+
+MessageModule::MessageModule()
+: BaseMainModule(GstDebugger::GStreamerData::kMessageInfo, "Messages")
+{
+}
+
+void MessageModule::load_details(gpointer data)
+{
+       auto msg_info = (GstDebugger::MessageInfo*)data;
+
+       append_details_row("message type", Gst::Enums::get_name((Gst::MessageType)msg_info->type()));
+       {
+               gchar buffer[20];
+               snprintf(buffer, 20, "%" GST_TIME_FORMAT, GST_TIME_ARGS(msg_info->timestamp()));
+               append_details_row("message timestamp", buffer);
+       }
+       append_details_row("message sequence number", std::to_string(msg_info->seqnum()));
+       append_details_row("object", "todo"); // todo
+
+       auto structure = Glib::wrap(gst_structure_from_string(msg_info->structure_data().c_str(), NULL), 
false);
+       append_details_from_structure(structure);
+}
+
+void MessageModule::data_received(const Gtk::TreeModel::Row& row, GstDebugger::GStreamerData *data)
+{
+       row[columns.header] = "Message of type: " + 
Gst::Enums::get_name((Gst::MessageType)data->message_info().type());
+       row[columns.data] = new GstDebugger::MessageInfo(data->message_info());
+}
+
+
+MessageControlModule::MessageControlModule()
+: ControlModule()
+{
+       types_combobox = Gtk::manage(new Gtk::ComboBox());
+       types_model = Gtk::ListStore::create(types_model_columns);
+       types_combobox->set_model(types_model);
+       types_combobox->pack_start(types_model_columns.type_name);
+
+       main_box->pack_start(*types_combobox, false, true);
+       main_box->reorder_child(*types_combobox, 0);
+
+       hooks_tree_view->append_column("Type", hooks_model_columns.str1);
+}
+
+void MessageControlModule::add_watch()
+{
+       auto it = types_combobox->get_active();
+       if (it)
+       {
+               Gtk::TreeModel::Row row = *it;
+               controller->send_message_request_command(row[types_model_columns.type_id], true);
+       }
+}
+
+void MessageControlModule::remove_watch(const Gtk::TreeModel::Row& row)
+{
+       controller->send_message_request_command(row[hooks_model_columns.int1], false);
+}
+
+void MessageControlModule::set_controller(const std::shared_ptr<Controller> &controller)
+{
+       ControlModule::set_controller(controller);
+
+       controller->on_enum_list_changed.connect([this](const Glib::ustring& name, bool add) {
+               if (name != "GstMessageType")
+                       return;
+               types_model->clear();
+               if (add)
+               {
+                       boost::optional<GstEnumType> type = this->controller->get_enum_type(name);
+                       if (!type)
+                               return;
+
+                       for (auto t : type.get().get_values())
+                       {
+                               Gtk::TreeModel::Row row = *(types_model->append());
+                               row[types_model_columns.type_id] = t.first;
+                               row[types_model_columns.type_name] = t.second.name;
+                       }
+
+                       if (!type.get().get_values().empty())
+                               types_combobox->set_active(0);
+               }
+       });
+}
+
+void MessageControlModule::confirmation_received(GstDebugger::Command* cmd)
+{
+       if (!cmd->has_message())
+               return;
+
+       auto confirmation = cmd->message();
+       if (confirmation.action() == GstDebugger::ADD)
+       {
+               Gtk::TreeModel::Row row = *(hooks_model->append());
+               row[hooks_model_columns.str1] = 
Gst::Enums::get_name(static_cast<Gst::MessageType>(confirmation.type()));
+               row[hooks_model_columns.int1] = confirmation.type();
+       }
+       else
+       {
+               remove_hook(confirmation);
+       }
+}
diff --git a/src/gst-debugger/modules/message_module.h b/src/gst-debugger/modules/message_module.h
new file mode 100644
index 0000000..71c5f23
--- /dev/null
+++ b/src/gst-debugger/modules/message_module.h
@@ -0,0 +1,50 @@
+/*
+ * message_module.h
+ *
+ *  Created on: Sep 27, 2015
+ *      Author: loganek
+ */
+
+#ifndef SRC_GST_DEBUGGER_MODULES_MESSAGE_MODULE_H_
+#define SRC_GST_DEBUGGER_MODULES_MESSAGE_MODULE_H_
+
+#include "base_main_module.h"
+#include "control_module.h"
+
+class MessageModule : public BaseMainModule
+{
+       void data_received(const Gtk::TreeModel::Row& row, GstDebugger::GStreamerData *data) override;
+       void load_details(gpointer data) override;
+
+public:
+       MessageModule();
+       virtual ~MessageModule() {}
+};
+
+class MessageControlModule : public ControlModule
+{
+       TypesModelColumns types_model_columns;
+       Glib::RefPtr<Gtk::ListStore> types_model;
+       std::string type_name;
+
+       Gtk::ComboBox *types_combobox;
+
+       void confirmation_received(GstDebugger::Command* cmd) override;
+
+       void add_watch() override;
+       void remove_watch(const Gtk::TreeModel::Row& row) override;
+
+       bool hook_is_the_same(const Gtk::TreeModel::Row& row, gconstpointer confirmation) override
+       {
+               auto message = reinterpret_cast<const GstDebugger::MessageRequest*>(confirmation);
+               return row[hooks_model_columns.int1] == message->type();
+       }
+
+public:
+       MessageControlModule();
+       virtual ~MessageControlModule() {}
+
+       void set_controller(const std::shared_ptr<Controller> &controller) override;
+};
+
+#endif /* SRC_GST_DEBUGGER_MODULES_MESSAGE_MODULE_H_ */
diff --git a/src/gst-debugger/modules/qe_control_module.h b/src/gst-debugger/modules/qe_control_module.h
new file mode 100644
index 0000000..6f153cd
--- /dev/null
+++ b/src/gst-debugger/modules/qe_control_module.h
@@ -0,0 +1,99 @@
+/*
+ * qe_control_module.h
+ *
+ *  Created on: Sep 29, 2015
+ *      Author: loganek
+ */
+
+#ifndef SRC_GST_DEBUGGER_MODULES_QE_CONTROL_MODULE_H_
+#define SRC_GST_DEBUGGER_MODULES_QE_CONTROL_MODULE_H_
+
+#include "control_module.h"
+
+#include "controller/element_path_processor.h"
+
+class QEControlModule : virtual public ControlModule
+{
+       const std::string enum_name;
+
+protected:
+       TypesModelColumns types_model_columns;
+       Glib::RefPtr<Gtk::ListStore> types_model;
+
+       Gtk::Label *pad_path_label;
+       Gtk::ComboBox *types_combobox;
+
+       std::string get_pad_path() const
+       {
+               auto obj = controller->get_selected_object();
+
+               return (obj && std::dynamic_pointer_cast<PadModel>(obj)) ?
+                               ElementPathProcessor::get_object_path(obj) :
+                               std::string();
+       }
+
+       bool hook_is_the_same(const Gtk::TreeModel::Row& row, gconstpointer confirmation) override
+       {
+               auto pad = reinterpret_cast<const GstDebugger::PadWatchRequest*>(confirmation);
+               return row[hooks_model_columns.int1] == pad->event().type() && row[hooks_model_columns.str2] 
== pad->pad();
+       }
+
+public:
+       QEControlModule(const std::string& enum_name)
+       : enum_name(enum_name)
+       {
+               pad_path_label = Gtk::manage(new Gtk::Label());
+               main_box->pack_start(*pad_path_label, false, true);
+               main_box->reorder_child(*pad_path_label, 0);
+
+               types_combobox = Gtk::manage(new Gtk::ComboBox());
+               types_model = Gtk::ListStore::create(types_model_columns);
+               types_combobox->set_model(types_model);
+               types_combobox->pack_start(types_model_columns.type_name);
+               main_box->pack_start(*types_combobox, false, true);
+               main_box->reorder_child(*types_combobox, 0);
+
+               hooks_tree_view->append_column("Type", hooks_model_columns.str1);
+               hooks_tree_view->append_column("Pad", hooks_model_columns.str2);
+
+               create_dispatcher("selected-object", [this] {
+                       auto pad_path = get_pad_path();
+                       if (pad_path.empty())
+                               pad_path = "none (any path)";
+                       pad_path_label->set_text(pad_path);
+               }, nullptr);
+       }
+
+       void set_controller(const std::shared_ptr<Controller> &controller) override
+       {
+               ControlModule::set_controller(controller);
+
+               controller->on_selected_object_changed.connect([this](){
+                       gui_emit("selected-object");
+               });
+
+               controller->on_enum_list_changed.connect([this](const Glib::ustring& name, bool add) {
+                       if (name != enum_name)
+                               return;
+                       types_model->clear();
+                       if (add)
+                       {
+                               boost::optional<GstEnumType> type = this->controller->get_enum_type(name);
+                               if (!type)
+                                       return;
+
+                               for (auto t : type.get().get_values())
+                               {
+                                       Gtk::TreeModel::Row row = *(types_model->append());
+                                       row[types_model_columns.type_id] = t.first;
+                                       row[types_model_columns.type_name] = t.second.name;
+                               }
+
+                               if (!type.get().get_values().empty())
+                                       types_combobox->set_active(0);
+                       }
+               });
+       }
+};
+
+#endif /* SRC_GST_DEBUGGER_MODULES_QE_CONTROL_MODULE_H_ */
diff --git a/src/gst-debugger/modules/query_module.cpp b/src/gst-debugger/modules/query_module.cpp
new file mode 100644
index 0000000..1c83ce2
--- /dev/null
+++ b/src/gst-debugger/modules/query_module.cpp
@@ -0,0 +1,73 @@
+/*
+ * query_module.cpp
+ *
+ *  Created on: Sep 29, 2015
+ *      Author: loganek
+ */
+
+#include "query_module.h"
+
+#include "controller/controller.h"
+
+QueryModule::QueryModule()
+: BaseMainModule(GstDebugger::GStreamerData::kQueryInfo, "Queries")
+{
+}
+
+void QueryModule::load_details(gpointer data)
+{
+       auto query_info = (GstDebugger::QueryInfo*)data;
+
+       append_details_row("query type", Gst::Enums::get_name((Gst::QueryType)query_info->type()));
+       append_details_row("sent from pad", query_info->pad());
+
+       auto structure = Glib::wrap(gst_structure_from_string(query_info->structure_data().c_str(), NULL), 
false);
+       append_details_from_structure(structure);
+}
+
+void QueryModule::data_received(const Gtk::TreeModel::Row& row, GstDebugger::GStreamerData *data)
+{
+       row[columns.header] = "Query of type: " + 
Gst::Enums::get_name((Gst::QueryType)data->query_info().type());
+       row[columns.data] = new GstDebugger::QueryInfo(data->query_info());
+}
+
+QueryControlModule::QueryControlModule()
+: ControlModule(),
+  QEControlModule("GstQueryType")
+{
+}
+
+void QueryControlModule::add_watch()
+{
+       auto it = types_combobox->get_active();
+       if (it)
+       {
+               Gtk::TreeModel::Row row = *it;
+               controller->send_query_request_command(true, get_pad_path(), 
row[types_model_columns.type_id]);
+       }
+}
+
+void QueryControlModule::remove_watch(const Gtk::TreeModel::Row& row)
+{
+       Glib::ustring pad = row[hooks_model_columns.str2];
+       controller->send_query_request_command(false, pad, row[hooks_model_columns.int1]);
+}
+
+void QueryControlModule::confirmation_received(GstDebugger::Command* cmd)
+{
+       if (!cmd->has_pad_watch() || !cmd->pad_watch().has_query())
+               return;
+
+       auto confirmation = cmd->pad_watch();
+       if (confirmation.action() == GstDebugger::ADD)
+       {
+               Gtk::TreeModel::Row row = *(hooks_model->append());
+               row[hooks_model_columns.str1] = 
Gst::Enums::get_name(static_cast<Gst::QueryType>(confirmation.query().type()));
+               row[hooks_model_columns.str2] = confirmation.pad();
+               row[hooks_model_columns.int1] = confirmation.query().type();
+       }
+       else
+       {
+               remove_hook(confirmation);
+       }
+}
diff --git a/src/gst-debugger/modules/query_module.h b/src/gst-debugger/modules/query_module.h
new file mode 100644
index 0000000..35c698a
--- /dev/null
+++ b/src/gst-debugger/modules/query_module.h
@@ -0,0 +1,37 @@
+/*
+ * query_module.h
+ *
+ *  Created on: Sep 29, 2015
+ *      Author: loganek
+ */
+
+#ifndef SRC_GST_DEBUGGER_MODULES_QUERY_MODULE_H_
+#define SRC_GST_DEBUGGER_MODULES_QUERY_MODULE_H_
+
+#include "base_main_module.h"
+#include "control_module.h"
+#include "qe_control_module.h"
+
+class QueryModule : public BaseMainModule
+{
+       void data_received(const Gtk::TreeModel::Row& row, GstDebugger::GStreamerData *data) override;
+       void load_details(gpointer data) override;
+
+public:
+       QueryModule();
+       virtual ~QueryModule() {}
+};
+
+class QueryControlModule : virtual public ControlModule, public QEControlModule
+{
+       void confirmation_received(GstDebugger::Command* cmd) override;
+
+       void add_watch() override;
+       void remove_watch(const Gtk::TreeModel::Row& row) override;
+
+public:
+       QueryControlModule();
+       virtual ~QueryControlModule() {}
+};
+
+#endif /* SRC_GST_DEBUGGER_MODULES_QUERY_MODULE_H_ */
diff --git a/src/gst-debugger/pipeline-drawer/graph_module.cpp 
b/src/gst-debugger/pipeline-drawer/graph_module.cpp
index 37cb5d2..56a7586 100644
--- a/src/gst-debugger/pipeline-drawer/graph_module.cpp
+++ b/src/gst-debugger/pipeline-drawer/graph_module.cpp
@@ -300,5 +300,5 @@ void GraphModule::update_model_()
 
 void GraphModule::refreshGraphButton_clicked_cb()
 {
-       controller->send_request_topology_command();
+       controller->send_request_entire_topology_command();
 }
diff --git a/src/gst-debugger/ui/gst-debugger.glade b/src/gst-debugger/ui/gst-debugger.glade
index 65c746a..8ab3e52 100644
--- a/src/gst-debugger/ui/gst-debugger.glade
+++ b/src/gst-debugger/ui/gst-debugger.glade
@@ -303,16 +303,13 @@
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
                     <property name="label_xalign">0</property>
+                    <property name="label_yalign">0</property>
                     <property name="shadow_type">none</property>
                     <child>
                       <placeholder/>
                     </child>
-                    <child type="label">
-                      <object class="GtkLabel" id="label1">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label" translatable="yes">Controller</property>
-                      </object>
+                    <child type="label_item">
+                      <placeholder/>
                     </child>
                   </object>
                   <packing>
diff --git a/src/gst-debugger/ui_utils.cpp b/src/gst-debugger/ui_utils.cpp
index d2d6144..02f3579 100644
--- a/src/gst-debugger/ui_utils.cpp
+++ b/src/gst-debugger/ui_utils.cpp
@@ -98,7 +98,7 @@ void display_caps(const Glib::RefPtr<Gst::Caps> &caps,
 
 #undef APPEND_SUB_ROW
 
-Glib::RefPtr<Gst::PadTemplate> protocol_template_to_gst_template(const TopologyTemplate &tpl)
+Glib::RefPtr<Gst::PadTemplate> protocol_template_to_gst_template(const GstDebugger::PadTemplate &tpl)
 {
        return Gst::PadTemplate::create(tpl.name_template(),
                        static_cast<Gst::PadDirection>(tpl.direction()),
diff --git a/src/gst-debugger/ui_utils.h b/src/gst-debugger/ui_utils.h
index 0a7f76d..e763a43 100644
--- a/src/gst-debugger/ui_utils.h
+++ b/src/gst-debugger/ui_utils.h
@@ -36,7 +36,7 @@ void display_caps(const Glib::RefPtr<Gst::Caps> &caps,
                const Glib::RefPtr<Gtk::TreeStore> &model, const Gtk::TreeModelColumn<Glib::ustring> 
&col_name,
                const Gtk::TreeModelColumn<Glib::ustring> &col_value, const Gtk::TreeModel::Row& parent_row);
 
-Glib::RefPtr<Gst::PadTemplate> protocol_template_to_gst_template(const TopologyTemplate &tpl);
+Glib::RefPtr<Gst::PadTemplate> protocol_template_to_gst_template(const GstDebugger::PadTemplate &tpl);
 
 std::string flags_value_to_string(guint value);
 


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