File tsclient-dmxsupport.diff of Package tsclient

diff --git a/data/tsclient.glade b/data/tsclient.glade
index edf8a49..7851642 100644
--- a/data/tsclient.glade
+++ b/data/tsclient.glade
@@ -1662,4 +1662,286 @@ LAN</property>
       </widget>
     </child>
   </widget>
+  <widget class="GtkDialog" id="dmx_edit_dialog">
+    <property name="visible">True</property>
+    <property name="title" translatable="yes">Edit Connection</property>
+    <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+    <child internal-child="vbox">
+      <widget class="GtkVBox" id="dialog-vbox12">
+        <property name="visible">True</property>
+        <child>
+          <widget class="GtkVBox" id="dmx_edit_dialog_content">
+            <property name="visible">True</property>
+            <property name="border_width">6</property>
+            <property name="spacing">6</property>
+            <child>
+              <widget class="GtkFrame" id="frame3">
+                <property name="visible">True</property>
+                <property name="label_xalign">0</property>
+                <property name="shadow_type">GTK_SHADOW_NONE</property>
+                <child>
+                  <widget class="GtkAlignment" id="alignment11">
+                    <property name="visible">True</property>
+                    <property name="left_padding">12</property>
+                    <child>
+                      <widget class="GtkTable" id="table9">
+                        <property name="visible">True</property>
+                        <property name="n_rows">7</property>
+                        <property name="n_columns">2</property>
+                        <property name="column_spacing">6</property>
+                        <property name="row_spacing">6</property>
+                        <child>
+                          <widget class="GtkCheckButton" id="dmx_compress_checkbox">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="tooltip" translatable="yes">Allows you to share the desktop with other clients already using it.</property>
+                            <property name="label" translatable="yes">Compress</property>
+                            <property name="use_underline">True</property>
+                            <property name="response_id">0</property>
+                            <property name="draw_indicator">True</property>
+                          </widget>
+                          <packing>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">4</property>
+                            <property name="bottom_attach">5</property>
+                            <property name="x_options">GTK_FILL</property>
+                            <property name="y_options"></property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkLabel" id="label43">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">Host:</property>
+                          </widget>
+                          <packing>
+                            <property name="x_options">GTK_FILL</property>
+                            <property name="y_options"></property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkEntry" id="dmx_host_entry">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="activates_default">True</property>
+                          </widget>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="y_options"></property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkLabel" id="label42">
+                            <property name="visible">True</property>
+                            <property name="xalign">0</property>
+                            <property name="label" translatable="yes">User:</property>
+                          </widget>
+                          <packing>
+                            <property name="top_attach">1</property>
+                            <property name="bottom_attach">2</property>
+                            <property name="x_options">GTK_FILL</property>
+                            <property name="y_options"></property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkEntry" id="dmx_user_entry">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="activates_default">True</property>
+                          </widget>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">1</property>
+                            <property name="bottom_attach">2</property>
+                            <property name="y_options"></property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkCheckButton" id="dmx_viewonly_checkbox">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="tooltip" translatable="yes">Do not send mouse or keyboard actions</property>
+                            <property name="label" translatable="yes">View only</property>
+                            <property name="use_underline">True</property>
+                            <property name="response_id">0</property>
+                            <property name="draw_indicator">True</property>
+                          </widget>
+                          <packing>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">5</property>
+                            <property name="bottom_attach">6</property>
+                            <property name="x_options">GTK_FILL</property>
+                            <property name="y_options"></property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkRadioButton" id="dmx_fullscreen_radio">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="label" translatable="yes">Fullscreen Window</property>
+                            <property name="use_underline">True</property>
+                            <property name="response_id">0</property>
+                            <property name="draw_indicator">True</property>
+                          </widget>
+                          <packing>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">2</property>
+                            <property name="bottom_attach">3</property>
+                            <property name="x_options">GTK_FILL</property>
+                            <property name="y_options"></property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkRadioButton" id="dmx_custom_window_radio">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="label" translatable="yes">Custom Window Size:</property>
+                            <property name="use_underline">True</property>
+                            <property name="response_id">0</property>
+                            <property name="draw_indicator">True</property>
+                            <property name="group">dmx_fullscreen_radio</property>
+                          </widget>
+                          <packing>
+                            <property name="top_attach">3</property>
+                            <property name="bottom_attach">4</property>
+                            <property name="x_options">GTK_FILL</property>
+                            <property name="y_options"></property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkHBox" id="dmx_custom_window_box">
+                            <property name="visible">True</property>
+                            <property name="spacing">6</property>
+                            <child>
+                              <widget class="GtkSpinButton" id="dmx_width_spin">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="adjustment">1 1 1920 1 10 10</property>
+                                <property name="climb_rate">1</property>
+                                <property name="numeric">True</property>
+                              </widget>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <widget class="GtkLabel" id="label40">
+                                <property name="visible">True</property>
+                                <property name="label" translatable="yes">x</property>
+                              </widget>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">1</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <widget class="GtkSpinButton" id="dmx_height_spin">
+                                <property name="visible">True</property>
+                                <property name="can_focus">True</property>
+                                <property name="adjustment">1 0 1680 1 10 10</property>
+                                <property name="climb_rate">1</property>
+                              </widget>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">False</property>
+                                <property name="position">2</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <widget class="GtkLabel" id="label41">
+                                <property name="visible">True</property>
+                              </widget>
+                              <packing>
+                                <property name="position">3</property>
+                              </packing>
+                            </child>
+                          </widget>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">3</property>
+                            <property name="bottom_attach">4</property>
+                            <property name="x_options">GTK_FILL</property>
+                            <property name="y_options">GTK_FILL</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <widget class="GtkCheckButton" id="dmx_direct_checkbox">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="tooltip" translatable="yes">Connect directly to the remote X server.</property>
+                            <property name="label" translatable="yes">Direct</property>
+                            <property name="use_underline">True</property>
+                            <property name="response_id">0</property>
+                            <property name="draw_indicator">True</property>
+                          </widget>
+                          <packing>
+                            <property name="right_attach">2</property>
+                            <property name="top_attach">6</property>
+                            <property name="bottom_attach">7</property>
+                            <property name="x_options">GTK_FILL</property>
+                            <property name="y_options"></property>
+                          </packing>
+                        </child>
+                      </widget>
+                    </child>
+                  </widget>
+                </child>
+                <child>
+                  <widget class="GtkLabel" id="label44">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">&lt;b&gt;Details&lt;/b&gt;</property>
+                    <property name="use_markup">True</property>
+                  </widget>
+                  <packing>
+                    <property name="type">label_item</property>
+                  </packing>
+                </child>
+              </widget>
+            </child>
+          </widget>
+          <packing>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <widget class="GtkHButtonBox" id="dialog-action_area12">
+            <property name="visible">True</property>
+            <property name="layout_style">GTK_BUTTONBOX_END</property>
+            <child>
+              <widget class="GtkButton" id="button13">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="label">gtk-cancel</property>
+                <property name="use_stock">True</property>
+                <property name="response_id">-6</property>
+              </widget>
+            </child>
+            <child>
+              <widget class="GtkButton" id="button14">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="label">gtk-ok</property>
+                <property name="use_stock">True</property>
+                <property name="response_id">-5</property>
+              </widget>
+              <packing>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">GTK_PACK_END</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
 </glade-interface>
diff --git a/src/plugins/default/Makefile.am b/src/plugins/default/Makefile.am
index 765391e..a95f12c 100644
--- a/src/plugins/default/Makefile.am
+++ b/src/plugins/default/Makefile.am
@@ -57,6 +57,12 @@ libtsc_default_la_SOURCES =		\
 	tsc-web-edit-dialog.h		\
 	tsc-web-provider.c			\
 	tsc-web-provider.h			\
+	tsc-dmx-connection.c		\
+	tsc-dmx-connection.h		\
+	tsc-dmx-edit-dialog.c		\
+	tsc-dmx-edit-dialog.h		\
+	tsc-dmx-provider.c		\
+	tsc-dmx-provider.h              \
 	tsc-vnc-connection.c		\
 	tsc-vnc-connection.h		\
 	tsc-vnc-edit-dialog.c		\
diff --git a/src/plugins/default/tsc-default.c b/src/plugins/default/tsc-default.c
index 06ebfe7..ea5616a 100644
--- a/src/plugins/default/tsc-default.c
+++ b/src/plugins/default/tsc-default.c
@@ -7,6 +7,7 @@
 #include "tsc-ica-provider.h"
 #include "tsc-mainframe-provider.h"
 #include "tsc-ssh-provider.h"
+#include "tsc-dmx-provider.h"
 #include "tsc-xdmcp-provider.h"
 #include "tsc-web-provider.h"
 #include "tsc-web-connection.h"
@@ -33,6 +34,7 @@ tsc_init_plugin (TSCManager *manager)
 	tsc_manager_register_provider (manager, TSC_PROVIDER (tsc_web_provider_new ()));
 
 	tsc_manager_register_provider (manager, TSC_PROVIDER (tsc_ssh_provider_new ()));
+	tsc_manager_register_provider (manager, TSC_PROVIDER (tsc_dmx_provider_new ()));
 	tsc_manager_register_provider (manager, TSC_PROVIDER (tsc_xdmcp_provider_new ()));
 	tsc_manager_register_provider (manager, TSC_PROVIDER (tsc_generic_provider_new ()));
 }
diff --git a/src/plugins/default/tsc-dmx-connection.c b/src/plugins/default/tsc-dmx-connection.c
new file mode 100644
index 0000000..bdafd1f
--- /dev/null
+++ b/src/plugins/default/tsc-dmx-connection.c
@@ -0,0 +1,283 @@
+
+#include <config.h>
+#include "string.h"
+#include <unistd.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <libnotify/notify.h>
+#include "tsc-dmx-connection.h"
+#include "tsc-util.h"
+#include "tsc-connection.h"
+
+#define DMX_CONFIG_GROUP "DMX"
+#define DMX_KEY_HOST "host"
+#define DMX_KEY_USER "user"
+#define DMX_KEY_COMPRESS "compress"
+#define DMX_KEY_VIEWONLY "viewonly"
+#define DMX_KEY_FULLSCREEN "fullscreen"
+#define DMX_KEY_WIDTH "width"
+#define DMX_KEY_HEIGHT "height"
+// stolen from SSH
+#define TSC_SSH_ASKPASS LIBDIR "/tsclient/tsc-ssh-askpass"
+
+#define DMX_FULLSCREEN_NOTIFY_DELAY 5000
+
+static GObjectClass *parent_class;
+
+static gboolean
+notify_fullscreen_cb (TSCDmxConnection *connection)
+{
+	NotifyNotification *n;
+	char *summary;
+	char *body;
+
+	if (!tsc_connection_is_connected (TSC_CONNECTION (connection)))
+		return FALSE;
+	
+	if (!notify_is_initted ()) {
+		notify_init (PACKAGE);
+	}
+
+	summary = g_strdup_printf (_("Connected to '%s'"),
+				   tsc_connection_get_name (TSC_CONNECTION (connection)));
+	body = g_strdup_printf (_("You are connected to '%s' in fullscreen mode.  Use F8 to switch to and from windowed mode."), tsc_connection_get_name (TSC_CONNECTION (connection)));
+
+	n = notify_notification_new (summary, body, GTK_STOCK_DIALOG_INFO, NULL);
+	g_free (summary);
+	g_free (body);
+	
+	notify_notification_show (n, NULL);
+	g_object_unref (n);
+
+	return FALSE;
+}
+
+static void
+notify_fullscreen (TSCDmxConnection *connection)
+{
+	g_timeout_add (DMX_FULLSCREEN_NOTIFY_DELAY,
+		       (GSourceFunc) notify_fullscreen_cb,
+		       connection);
+}
+
+static void
+tsc_dmx_connection_stopped_cb (TSCSpawn *spawn, TSCDmxConnection *connection)
+{
+	GError *error = NULL;
+
+	error = tsc_spawn_get_error (spawn);
+	
+	g_object_unref (connection->spawn);
+	connection->spawn = NULL;
+	
+	g_signal_emit_by_name (connection, "ended", error, NULL);
+	
+	if (error) {
+		g_error_free (error);
+	}
+}
+
+static void
+tsc_dmx_connection_setup (gpointer user_data)
+{
+	TSCConnection *con = TSC_CONNECTION (user_data);
+	
+	setsid ();
+	
+	if (g_file_test (TSC_SSH_ASKPASS, G_FILE_TEST_EXISTS)) {
+		g_setenv ("OLD_SSH_ASKPASS", g_getenv ("SSH_ASKPASS"), TRUE);
+		g_setenv ("TSC_USER", g_get_user_name (), TRUE);
+		g_setenv ("TSC_CONNECTION_FILE", tsc_connection_get_filename (con), TRUE);
+		g_setenv ("SSH_ASKPASS", TSC_SSH_ASKPASS, TRUE);
+	}
+}
+
+
+static gboolean
+tsc_dmx_connection_start (TSCConnection *con, GError **error)
+{
+	TSCDmxConnection *connection = TSC_DMX_CONNECTION (con);
+
+	if (connection->spawn) {
+		g_object_unref (connection->spawn);
+	}
+
+	connection->spawn = tsc_spawn_new ();
+	g_signal_connect (connection->spawn, "stopped",
+			  G_CALLBACK (tsc_dmx_connection_stopped_cb),
+			  connection);
+
+	tsc_spawn_set_args (connection->spawn, "dmxviewer", NULL);
+
+	if (connection->compress) {
+		tsc_spawn_append_args (connection->spawn, "-compress", NULL);
+	} 
+
+	if (connection->viewonly) {
+		tsc_spawn_append_args (connection->spawn, "-viewonly", NULL);
+	}
+
+	if (connection->direct) {
+		tsc_spawn_append_args (connection->spawn, "-direct", NULL);
+	}
+
+	if (connection->fullscreen) {
+		tsc_spawn_append_args (connection->spawn, "-fullscreen", NULL);
+	} else {
+#if 0
+		char *geometry = g_strdup_printf ("%dx%d", connection->width,
+						  connection->height);
+
+		tsc_spawn_append_args (connection->spawn, "-geometry", geometry, NULL);
+		g_free (geometry);
+#endif
+	}
+
+	if (connection->user) {
+		tsc_spawn_append_args (connection->spawn, "-user", connection->user, NULL);
+	}
+
+	if (connection->host) {
+		tsc_spawn_append_args (connection->spawn, connection->host, NULL);
+	}
+	
+	if (!tsc_spawn_start_with_setup (connection->spawn,
+						  tsc_dmx_connection_setup, connection,
+						  error)) {
+		return FALSE;
+	}
+
+#if 0
+	if (connection->password) {
+		char *password = g_strdup_printf ("%s\n", connection->password);
+
+		g_io_channel_write_chars (tsc_spawn_get_stdin (connection->spawn), password,
+					  strlen (password), NULL, NULL);
+		g_io_channel_flush (tsc_spawn_get_stdin (connection->spawn), NULL);
+		g_free (password);
+	}
+#endif
+
+	g_signal_emit_by_name (connection, "started", NULL);
+
+	if (connection->fullscreen) {
+		notify_fullscreen (connection);
+	}
+	
+	return TRUE;
+}
+
+static void
+tsc_dmx_connection_save (TSCConnection *con, GKeyFile *keys)
+{
+	TSCDmxConnection *connection = TSC_DMX_CONNECTION (con);
+
+	if (connection->host) {
+		g_key_file_set_string (keys, DMX_CONFIG_GROUP,
+				       DMX_KEY_HOST, connection->host);
+	}
+
+	if (connection->user) {
+		g_key_file_set_string (keys, DMX_CONFIG_GROUP,
+				       DMX_KEY_USER, connection->user);
+	}
+
+	g_key_file_set_boolean (keys, DMX_CONFIG_GROUP,
+				DMX_KEY_COMPRESS, connection->compress);
+	g_key_file_set_boolean (keys, DMX_CONFIG_GROUP,
+				DMX_KEY_VIEWONLY, connection->viewonly);
+	g_key_file_set_boolean (keys, DMX_CONFIG_GROUP,
+				DMX_KEY_FULLSCREEN, connection->fullscreen);
+
+	if (connection->width > 0) {
+		g_key_file_set_integer (keys, DMX_CONFIG_GROUP,
+					DMX_KEY_WIDTH, connection->width);
+	}
+
+	if (connection->height > 0) {
+		g_key_file_set_integer (keys, DMX_CONFIG_GROUP,
+					DMX_KEY_HEIGHT, connection->height);
+	}
+}
+
+static void
+tsc_dmx_connection_restore (TSCConnection *con, GKeyFile *keys)
+{
+	TSCDmxConnection *connection = TSC_DMX_CONNECTION (con);
+	connection->host = g_key_file_get_string (keys, DMX_CONFIG_GROUP,
+						  DMX_KEY_HOST, NULL);
+	connection->user = g_key_file_get_string (keys, DMX_CONFIG_GROUP,
+						      DMX_KEY_USER, NULL);
+
+	connection->compress = g_key_file_get_boolean (keys, DMX_CONFIG_GROUP,
+						     DMX_KEY_COMPRESS, NULL);
+	connection->viewonly = g_key_file_get_boolean (keys, DMX_CONFIG_GROUP,
+						       DMX_KEY_VIEWONLY, NULL);
+	connection->fullscreen = g_key_file_get_boolean (keys, DMX_CONFIG_GROUP,
+							 DMX_KEY_FULLSCREEN, NULL);
+
+	connection->width = g_key_file_get_integer (keys, DMX_CONFIG_GROUP,
+						    DMX_KEY_WIDTH, NULL);
+	connection->height = g_key_file_get_integer (keys, DMX_CONFIG_GROUP,
+						     DMX_KEY_HEIGHT, NULL);
+}
+
+static void
+tsc_dmx_connection_finalize (GObject *obj)
+{
+	TSCDmxConnection *connection = TSC_DMX_CONNECTION (obj);
+
+	g_free (connection->host);
+	g_free (connection->user);
+
+	if (parent_class->finalize) {
+		parent_class->finalize (obj);
+	}
+}
+
+static void
+tsc_dmx_connection_class_init (TSCDmxConnectionClass *klass)
+{
+	GObjectClass *object_class = (GObjectClass *) klass;
+
+	parent_class = g_type_class_peek_parent (klass);
+	object_class->finalize = tsc_dmx_connection_finalize;
+	
+	TSC_CONNECTION_CLASS (klass)->start = tsc_dmx_connection_start;
+	TSC_CONNECTION_CLASS (klass)->save_config = tsc_dmx_connection_save;
+	TSC_CONNECTION_CLASS (klass)->restore_config = tsc_dmx_connection_restore;
+}
+
+static void
+tsc_dmx_connection_init (TSCDmxConnection *connection)
+{
+	connection->compress = FALSE;
+	connection->viewonly = FALSE;
+	connection->fullscreen = TRUE;
+	connection->direct = FALSE;
+}
+
+GType
+tsc_dmx_connection_get_type (void)
+{
+	static GType type = 0;
+
+	if (!type) {
+		static GTypeInfo type_info = {
+			sizeof (TSCDmxConnectionClass),
+			NULL, NULL,
+			(GClassInitFunc) tsc_dmx_connection_class_init,
+			NULL, NULL,
+			sizeof (TSCDmxConnection),
+			0,
+			(GInstanceInitFunc) tsc_dmx_connection_init
+		};
+		
+		type = g_type_register_static (TSC_TYPE_CONNECTION,
+					       "TSCDmxConnection",
+					       &type_info, 0);
+	}
+	
+	return type;
+
+}
diff --git a/src/plugins/default/tsc-dmx-connection.h b/src/plugins/default/tsc-dmx-connection.h
new file mode 100644
index 0000000..c3e5080
--- /dev/null
+++ b/src/plugins/default/tsc-dmx-connection.h
@@ -0,0 +1,41 @@
+
+#ifndef __TSC_DMX_CONNECTION__
+#define __TSC_DMX_CONNECTION__
+
+#include <glib.h>
+#include <glib-object.h>
+#include "tsc-connection.h"
+#include "tsc-spawn.h"
+
+#define TSC_TYPE_DMX_CONNECTION                   (tsc_dmx_connection_get_type ())
+#define TSC_DMX_CONNECTION(connection)            (G_TYPE_CHECK_INSTANCE_CAST ((connection), TSC_TYPE_DMX_CONNECTION, TSCDmxConnection))
+#define TSC_DMX_CONNECTION_CLASS(klass)           (G_TYPE_CHECK_CLASS_CAST ((klass), TSC_TYPE_DMX_CONNECTION, TSCDmxConnectionClass))
+#define TSC_IS_DMX_CONNECTION(connection)         (G_TYPE_CHECK_INSTANCE_TYPE ((connection), TSC_TYPE_DMX_CONNECTION))
+#define TSC_IS_DMX_CONNECTION_CLASS(klass)        (G_TYPE_CHECK_CLASS_TYPE ((klass), TSC_TYPE_DMX_CONNECTION))
+#define TSC_DMX_CONNECTION_GET_CLASS(obj)         (G_TYPE_INSTANCE_GET_CLASS ((obj), TSC_TYPE_DMX_CONNECTION, TSCDmxConnectionClass))
+
+typedef struct _TSCDmxConnection {
+	TSCConnection parent;
+
+	char *host;
+	char *user;
+
+	gboolean compress;
+	gboolean viewonly;
+	gboolean fullscreen;
+	gboolean direct;
+	
+	int width;
+	int height;
+
+	TSCSpawn *spawn;
+} TSCDmxConnection;
+
+typedef struct _TSCDmxConnectionClass {
+	TSCConnectionClass parent_class;
+} TSCDmxConnectionClass;
+
+
+GType       tsc_dmx_connection_get_type        (void);
+
+#endif
diff --git a/src/plugins/default/tsc-dmx-edit-dialog.c b/src/plugins/default/tsc-dmx-edit-dialog.c
new file mode 100644
index 0000000..0115df4
--- /dev/null
+++ b/src/plugins/default/tsc-dmx-edit-dialog.c
@@ -0,0 +1,222 @@
+
+#include <config.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include "tsc-dmx-edit-dialog.h"
+#include "tsc-dmx-connection.h"
+#include "tsc-util.h"
+
+static TSCEditDialogClass *parent_class;
+
+static void
+tsc_dmx_edit_dialog_finalize (GObject *obj)
+{
+	TSCDmxEditDialog *dialog = TSC_DMX_EDIT_DIALOG (obj);
+
+	if (dialog->xml) {
+		g_object_unref (dialog->xml);
+	}
+
+	if (G_OBJECT_CLASS (parent_class)->finalize) {
+		G_OBJECT_CLASS (parent_class)->finalize (obj);
+	}
+}
+
+static void
+custom_window_toggle_cb (GtkToggleButton  *button,
+			 TSCDmxEditDialog *dialog)
+{
+	gtk_widget_set_sensitive (glade_xml_get_widget (dialog->xml,
+							"dmx_custom_window_box"),
+				  gtk_toggle_button_get_active (button));
+}
+
+static void
+tsc_dmx_edit_dialog_load (TSCEditDialog *edit_dialog)
+{
+	TSCDmxEditDialog *dialog;
+	TSCDmxConnection *connection;
+	GdkScreen *screen;
+	int width, height;
+	
+	dialog = TSC_DMX_EDIT_DIALOG (edit_dialog);
+	connection = TSC_DMX_CONNECTION (edit_dialog->connection);
+
+	if (connection->host) {
+		gtk_entry_set_text (GTK_ENTRY (glade_xml_get_widget (dialog->xml, "dmx_host_entry")),
+				    connection->host);
+	}
+
+	if (connection->user) {
+		gtk_entry_set_text (GTK_ENTRY (glade_xml_get_widget (dialog->xml, "dmx_user_entry")),
+				    connection->user);
+	}
+
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (dialog->xml,
+									       "dmx_compress_checkbox")),
+				      connection->compress);
+	
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (dialog->xml,
+									       "dmx_viewonly_checkbox")),
+				      connection->viewonly);
+
+	if (connection->fullscreen ) {
+		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (dialog->xml,
+										       "dmx_fullscreen_radio")),
+					      TRUE);
+	} else {
+		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (dialog->xml,
+										       "dmx_custom_window_radio")),
+					      TRUE);
+	}
+
+	/* ugh, why isn't this triggered when we do _set_active above? */
+	custom_window_toggle_cb (GTK_TOGGLE_BUTTON (glade_xml_get_widget (dialog->xml,
+									  "dmx_custom_window_radio")),
+				 dialog);
+
+	/* setup ranges for width/height spin buttons */
+	screen = gtk_widget_get_screen (GTK_WIDGET (dialog));
+	gtk_spin_button_set_range (GTK_SPIN_BUTTON (glade_xml_get_widget (dialog->xml,
+									  "dmx_width_spin")),
+				   1, gdk_screen_get_width (screen));
+	gtk_spin_button_set_range (GTK_SPIN_BUTTON (glade_xml_get_widget (dialog->xml,
+									  "dmx_height_spin")),
+				   1, gdk_screen_get_height (screen));
+
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (glade_xml_get_widget (dialog->xml,
+										   "dmx_direct_checkbox")),
+								  connection->direct);
+
+
+	if (connection->width <= 0 || connection->width > gdk_screen_get_width (screen)) {
+		width = gdk_screen_get_width (screen);
+	} else {
+		width = connection->width;
+	}
+
+	if (connection->height <= 0 || connection->height > gdk_screen_get_height (screen)) {
+		height = gdk_screen_get_height (screen);
+	} else {
+		height = connection->height;
+	}
+
+	gtk_spin_button_set_value (GTK_SPIN_BUTTON (glade_xml_get_widget (dialog->xml,
+									  "dmx_width_spin")),
+				   (gdouble) width);
+	
+	gtk_spin_button_set_value (GTK_SPIN_BUTTON (glade_xml_get_widget (dialog->xml,
+									  "dmx_height_spin")),
+				   (gdouble) height);
+}
+
+static void
+tsc_dmx_edit_dialog_save (TSCEditDialog *edit_dialog)
+{
+
+	TSCDmxEditDialog *dialog;
+	TSCDmxConnection *connection;
+
+	dialog = TSC_DMX_EDIT_DIALOG (edit_dialog);
+	connection = TSC_DMX_CONNECTION (edit_dialog->connection);
+
+	g_free (connection->host);
+	connection->host = g_strdup (gtk_entry_get_text (GTK_ENTRY (glade_xml_get_widget (dialog->xml,
+											  "dmx_host_entry"))));
+	g_free (connection->user);
+	connection->user = g_strdup (gtk_entry_get_text (GTK_ENTRY (glade_xml_get_widget (dialog->xml,
+											  "dmx_user_entry"))));
+	NULLIFY_IF_EMPTY (connection->user);
+
+	connection->compress = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (
+								   glade_xml_get_widget (dialog->xml,
+											 "dmx_compress_checkbox")));
+	connection->viewonly = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (
+								     glade_xml_get_widget (dialog->xml,
+											   "dmx_viewonly_checkbox")));
+	connection->fullscreen = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (
+								       glade_xml_get_widget (dialog->xml,
+											     "dmx_fullscreen_radio")));
+	connection->width = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (
+								      glade_xml_get_widget (dialog->xml,
+											    "dmx_width_spin")));
+	connection->height = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (
+								       glade_xml_get_widget (dialog->xml,
+											     "dmx_height_spin")));
+	connection->direct = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (
+								     glade_xml_get_widget (dialog->xml,
+											   "dmx_direct_checkbox")));
+}
+
+static gboolean
+tsc_dmx_edit_dialog_verify (TSCEditDialog *edit_dialog, gchar **reason)
+{
+	TSCDmxEditDialog *dialog = TSC_DMX_EDIT_DIALOG (edit_dialog);
+	GtkEntry *host_entry = GTK_ENTRY (glade_xml_get_widget (dialog->xml, "dmx_host_entry"));
+	
+	if (!g_ascii_strcasecmp ("", gtk_entry_get_text (host_entry))) {
+		*reason = g_strdup (_("Host is a required field"));
+		 return FALSE;
+	} 
+	
+	return TRUE;
+}
+
+static void
+tsc_dmx_edit_dialog_class_init (TSCDmxEditDialogClass *klass)
+{
+	GObjectClass *object_class = (GObjectClass *) klass;
+	TSCEditDialogClass *edit_dialog_class = (TSCEditDialogClass *) klass;
+	
+	parent_class = g_type_class_peek_parent (klass);
+	object_class->finalize = tsc_dmx_edit_dialog_finalize;
+	edit_dialog_class->load = tsc_dmx_edit_dialog_load;
+	edit_dialog_class->save = tsc_dmx_edit_dialog_save;
+	edit_dialog_class->verify = tsc_dmx_edit_dialog_verify;
+}
+
+static void
+tsc_dmx_edit_dialog_init (TSCDmxEditDialog *dialog)
+{
+	GtkWidget *content;
+
+	dialog->xml = glade_xml_new (GLADEFILE,
+				     "dmx_edit_dialog_content",
+				     PACKAGE);
+
+	g_signal_connect (glade_xml_get_widget (dialog->xml,
+						"dmx_custom_window_radio"),
+			  "toggled",
+			  G_CALLBACK (custom_window_toggle_cb),
+			  dialog);
+	
+	content = glade_xml_get_widget (dialog->xml, "dmx_edit_dialog_content");
+	gtk_widget_show_all (content);
+	
+	gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), content);
+}
+
+GType
+tsc_dmx_edit_dialog_get_type (void)
+{
+	static GType type = 0;
+
+	if (!type) {
+		static GTypeInfo type_info = {
+			sizeof (TSCDmxEditDialogClass),
+			NULL, NULL,
+			(GClassInitFunc) tsc_dmx_edit_dialog_class_init,
+			NULL, NULL,
+			sizeof (TSCDmxEditDialog),
+			0,
+			(GInstanceInitFunc) tsc_dmx_edit_dialog_init
+		};
+		
+		type = g_type_register_static (TSC_TYPE_EDIT_DIALOG,
+					       "TSCDmxEditDialog",
+					       &type_info, 0);
+	}
+	
+	return type;
+
+}
diff --git a/src/plugins/default/tsc-dmx-edit-dialog.h b/src/plugins/default/tsc-dmx-edit-dialog.h
new file mode 100644
index 0000000..0c5ffaf
--- /dev/null
+++ b/src/plugins/default/tsc-dmx-edit-dialog.h
@@ -0,0 +1,31 @@
+
+#ifndef __TSC_DMX_EDIT_DIALOG__
+#define __TSC_DMX_EDIT_DIALOG__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <glade/glade.h>
+#include "tsc-edit-dialog.h"
+
+#define TSC_TYPE_DMX_EDIT_DIALOG                   (tsc_dmx_edit_dialog_get_type ())
+#define TSC_DMX_EDIT_DIALOG(dialog )               (G_TYPE_CHECK_INSTANCE_CAST ((dialog), TSC_TYPE_DMX_EDIT_DIALOG, TSCDmxEditDialog))
+#define TSC_DMX_EDIT_DIALOG_CLASS(klass)           (G_TYPE_CHECK_CLASS_CAST ((klass), TSC_TYPE_DMX_EDIT_DIALOG, TSCDmxEditDialogClass))
+#define TSC_IS_DMX_EDIT_DIALOG(dialog)             (G_TYPE_CHECK_INSTANCE_TYPE ((dialog), TSC_TYPE_DMX_EDIT_DIALOG))
+#define TSC_IS_DMX_EDIT_DIALOG_CLASS(klass)        (G_TYPE_CHECK_CLASS_TYPE ((klass), TSC_TYPE_DMX_EDIT_DIALOG))
+#define TSC_DMX_EDIT_DIALOG_GET_CLASS(obj)         (G_TYPE_INSTANCE_GET_CLASS ((obj), TSC_TYPE_DMX_EDIT_DIALOG, TSCDmxEditDialogClass))
+
+typedef struct _TSCDmxEditDialog {
+	TSCEditDialog parent;
+
+	GladeXML *xml;
+} TSCDmxEditDialog;
+
+typedef struct _TSCDmxEditDialogClass {
+	TSCEditDialogClass parent_class;
+} TSCDmxEditDialogClass;
+
+
+GType          tsc_dmx_edit_dialog_get_type        (void);
+
+#endif
diff --git a/src/plugins/default/tsc-dmx-provider.c b/src/plugins/default/tsc-dmx-provider.c
new file mode 100644
index 0000000..1749806
--- /dev/null
+++ b/src/plugins/default/tsc-dmx-provider.c
@@ -0,0 +1,100 @@
+
+#include <config.h>
+#include <glib/gi18n.h>
+#include "tsc-util.h"
+#include "tsc-dmx-provider.h"
+#include "tsc-dmx-connection.h"
+#include "tsc-dmx-edit-dialog.h"
+
+#define TSC_DMX_URI_SCHEME "dmx://"
+
+static TSCConnection *
+tsc_dmx_provider_create_connection (TSCProvider *provider)
+{
+	return TSC_CONNECTION (g_object_new (TSC_TYPE_DMX_CONNECTION, NULL));
+}
+
+static TSCConnection *
+tsc_dmx_provider_create_from_uri (TSCProvider *provider, const char *uri)
+{
+	TSCConnection *connection = NULL;
+	char *host;
+	
+	if (!tsc_util_check_uri_scheme (uri, TSC_DMX_URI_SCHEME)) {
+		return NULL;
+	}
+
+	host = tsc_util_get_uri_host (uri);
+	if (!host) {
+		return NULL;
+	}
+
+	connection = TSC_CONNECTION (g_object_new (TSC_TYPE_DMX_CONNECTION, NULL));
+	TSC_DMX_CONNECTION (connection)->host = host;
+
+	g_free (connection->name);
+	connection->name = g_strdup_printf (_("DMX on %s"),
+					    TSC_DMX_CONNECTION (connection)->host);
+	
+	return connection;
+}
+
+
+static TSCEditDialog *
+tsc_dmx_provider_create_edit_dialog (TSCProvider *provider,
+					 TSCConnection *connection)
+{
+	return TSC_EDIT_DIALOG (g_object_new (TSC_TYPE_DMX_EDIT_DIALOG,
+					      "connection", connection, NULL));
+}
+
+static void
+tsc_dmx_provider_class_init (TSCDmxProviderClass *klass)
+{
+	TSC_PROVIDER_CLASS (klass)->create_connection = tsc_dmx_provider_create_connection;
+	TSC_PROVIDER_CLASS (klass)->create_from_uri = tsc_dmx_provider_create_from_uri;
+	TSC_PROVIDER_CLASS (klass)->create_edit_dialog = tsc_dmx_provider_create_edit_dialog;
+}
+
+static void
+tsc_dmx_provider_init (TSCDmxProvider *provider)
+{
+	TSCProvider *parent = TSC_PROVIDER (provider);
+
+	parent->name = "DMX";
+	parent->display_name = _("DMX");
+	parent->description = _("Create a DMX connection");
+	parent->icon_name = "gnome-remote-desktop";
+	parent->enabled = tsc_util_program_exists ("dmxviewer");
+}
+
+GType
+tsc_dmx_provider_get_type (void)
+{
+	static GType type = 0;
+
+	if (!type) {
+		static GTypeInfo type_info = {
+			sizeof (TSCDmxProviderClass),
+			NULL, NULL,
+			(GClassInitFunc) tsc_dmx_provider_class_init,
+			NULL, NULL,
+			sizeof (TSCDmxProvider),
+			0,
+			(GInstanceInitFunc) tsc_dmx_provider_init
+		};
+		
+		type = g_type_register_static (TSC_TYPE_PROVIDER,
+					       "TSCDmxProvider",
+					       &type_info, 0);
+	}
+	
+	return type;
+
+}
+
+TSCDmxProvider *
+tsc_dmx_provider_new (void)
+{
+	return g_object_new (TSC_TYPE_DMX_PROVIDER, NULL);
+}
diff --git a/src/plugins/default/tsc-dmx-provider.h b/src/plugins/default/tsc-dmx-provider.h
new file mode 100644
index 0000000..6759f65
--- /dev/null
+++ b/src/plugins/default/tsc-dmx-provider.h
@@ -0,0 +1,28 @@
+
+#ifndef __TSC_DMX_PROVIDER__
+#define __TSC_DMX_PROVIDER__
+
+#include <glib.h>
+#include <glib-object.h>
+#include "tsc-provider.h"
+
+#define TSC_TYPE_DMX_PROVIDER                   (tsc_dmx_provider_get_type ())
+#define TSC_DMX_PROVIDER(generic_provider)      (G_TYPE_CHECK_INSTANCE_CAST ((generic_provider), TSC_TYPE_DMX_PROVIDER, TSCDmxProvider))
+#define TSC_DMX_PROVIDER_CLASS(klass)           (G_TYPE_CHECK_CLASS_CAST ((klass), TSC_TYPE_DMX_PROVIDER, TSCDmxProviderClass))
+#define TSC_IS_DMX_PROVIDER(generic_provider)   (G_TYPE_CHECK_INSTANCE_TYPE ((generic_provider), TSC_TYPE_DMX_PROVIDER))
+#define TSC_IS_DMX_PROVIDER_CLASS(klass)        (G_TYPE_CHECK_CLASS_TYPE ((klass), TSC_TYPE_DMX_PROVIDER))
+#define TSC_DMX_PROVIDER_GET_CLASS(obj)         (G_TYPE_INSTANCE_GET_CLASS ((obj), TSC_TYPE_DMX_PROVIDER, TSCDmxProviderClass))
+
+
+typedef struct _TSCDmxProvider {
+	TSCProvider parent;
+} TSCDmxProvider;
+
+typedef struct _TSCDmxProviderClass {
+	TSCProviderClass parent_class;
+} TSCDmxProviderClass;
+
+GType               tsc_dmx_provider_get_type      (void);
+TSCDmxProvider *tsc_dmx_provider_new           (void);
+
+#endif
openSUSE Build Service is sponsored by