--- /dev/null
+#
+# Version $Id$
+#
+@MCOMMON@
+
+srcdir = .
+VPATH = .
+.PATH: .
+
+# one up
+basedir = ..
+# top dir
+topdir = ../..
+# this dir relative to top dir
+thisdir = src/tray-monitor
+
+DEBUG=@DEBUG@
+
+first_rule: all
+dummy:
+
+#
+MONITORSRCS = tray-monitor.c tray_conf.c authenticate.c eggmarshalers.c eggstatusicon.c eggtrayicon.c
+MONITOROBJS = tray-monitor.o tray_conf.o authenticate.o eggmarshalers.o eggstatusicon.o eggtrayicon.o
+
+# these are the objects that are changed by the .configure process
+EXTRAOBJS = @OBJLIST@
+
+MONITOR_CPPFLAGS=@TRAY_MONITOR_CPPFLAGS@
+MONITOR_LDFLAGS=@TRAY_MONITOR_LDFLAGS@
+
+.SUFFIXES: .c .o
+.PHONY:
+.DONTCARE:
+
+# inference rules
+.c.o:
+ $(CXX) $(DEFS) $(DEBUG) -c $(CPPFLAGS) $(MONITOR_CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) $<
+#-------------------------------------------------------------------------
+all: Makefile bacula-tray-monitor @STATIC_CONS@
+ @echo "==== Make of bacula-tray-monitor is good ===="
+ @echo " "
+
+bacula-tray-monitor: $(MONITOROBJS) ../lib/libbac.a
+ $(CXX) $(LDFLAGS) $(MONITOR_LDFLAGS) -L../lib -L../cats -o $@ $(MONITOROBJS) \
+ $(DLIB) -lbac -lm $(LIBS)
+
+
+Makefile: $(srcdir)/Makefile.in $(topdir)/config.status
+ cd $(topdir) \
+ && CONFIG_FILES=$(thisdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+clean:
+ @$(RMF) bacula-tray-monitor core core.* a.out *.o *.bak *~ *.intpro *.extpro 1 2 3
+
+realclean: clean
+ @$(RMF) tags tray-monitor.conf
+
+distclean: realclean
+ if test $(srcdir) = .; then $(MAKE) realclean; fi
+ (cd $(srcdir); $(RMF) Makefile; $(RMF) -r CVS)
+
+devclean: realclean
+ if test $(srcdir) = .; then $(MAKE) realclean; fi
+ (cd $(srcdir); $(RMF) Makefile)
+
+install: all
+ $(INSTALL_PROGRAM) bacula-tray-monitor $(DESTDIR)$(sbindir)/bacula-tray-monitor
+ @srcconf=tray-monitor.conf; \
+ if test -f ${DESTDIR}${sysconfdir}/$$srcconf; then \
+ destconf=$$srcconf.new; \
+ echo " ==> Found existing $$srcconf, installing new conf file as $$destconf"; \
+ else \
+ destconf=$$srcconf; \
+ fi; \
+ echo "${INSTALL_CONFIG} $$srcconf ${DESTDIR}${sysconfdir}/$$destconf"; \
+ ${INSTALL_CONFIG} $$srcconf ${DESTDIR}${sysconfdir}/$$destconf
+
+uninstall:
+ (cd $(DESTDIR)$(sbindir); $(RMF) bacula-tray-monitor)
+ (cd $(DESTDIR)$(sysconfdir); $(RMF) tray-monitor.conf)
+
+
+
+# Semi-automatic generation of dependencies:
+# Use gcc -MM because X11 `makedepend' doesn't work on all systems
+# and it also includes system headers.
+# `semi'-automatic since dependencies are generated at distribution time.
+
+depend:
+ @$(MV) Makefile Makefile.bak
+ @$(SED) "/^# DO NOT DELETE:/,$$ d" Makefile.bak > Makefile
+ @$(ECHO) "# DO NOT DELETE: nice dependency list follows" >> Makefile
+ @$(CC) -S -M $(CPPFLAGS) $(CONS_INC) -I$(srcdir) -I$(basedir) *.c >> Makefile
+ @if test -f Makefile ; then \
+ $(RMF) Makefile.bak; \
+ else \
+ $(MV) Makefile.bak Makefile; \
+ echo -e "Something went wrong\n\a"; \
+ fi
+
+# -----------------------------------------------------------------------
+# DO NOT DELETE: nice dependency list follows
--- /dev/null
+/*
+ *
+ * Bacula UA authentication. Provides authentication with
+ * the Director.
+ *
+ * Kern Sibbald, June MMI
+ *
+ * This routine runs as a thread and must be thread reentrant.
+ *
+ * Basic tasks done here:
+ *
+ */
+/*
+ Copyright (C) 2001-2004 Kern Sibbald and John Walker
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+ */
+
+#include "bacula.h"
+#include "tray-monitor.h"
+#include "jcr.h"
+
+void senditf(const char *fmt, ...);
+void sendit(const char *buf);
+
+/* Commands sent to Storage daemon and File daemon and received
+ * from the User Agent */
+static char hello[] = "Hello Director %s calling\n";
+
+/* Response from FD */
+static char FDOKhello[] = "2000 OK Hello\n";
+
+/* Forward referenced functions */
+
+/*
+ * Authenticate File daemon connection
+ */
+int authenticate_file_daemon(JCR *jcr, MONITOR *monitor, CLIENT* client)
+{
+ BSOCK *fd = jcr->file_bsock;
+ char dirname[MAX_NAME_LENGTH];
+ int ssl_need = BNET_SSL_NONE;
+
+ /*
+ * Send my name to the File daemon then do authentication
+ */
+ bstrncpy(dirname, monitor->hdr.name, sizeof(dirname));
+ bash_spaces(dirname);
+ /* Timeout Hello after 5 mins */
+ btimer_t *tid = start_bsock_timer(fd, 60 * 5);
+ if (!bnet_fsend(fd, hello, dirname)) {
+ stop_bsock_timer(tid);
+ Jmsg(jcr, M_FATAL, 0, _("Error sending Hello to File daemon. ERR=%s\n"), bnet_strerror(fd));
+ return 0;
+ }
+ if (!cram_md5_get_auth(fd, client->password, ssl_need) ||
+ !cram_md5_auth(fd, client->password, ssl_need)) {
+ stop_bsock_timer(tid);
+ Jmsg(jcr, M_FATAL, 0, _("Director and File daemon passwords or names not the same.\n"
+ "Please see http://www.bacula.org/html-manual/faq.html#AuthorizationErrors for help.\n"));
+ return 0;
+ }
+ Dmsg1(116, ">filed: %s", fd->msg);
+ if (bnet_recv(fd) <= 0) {
+ stop_bsock_timer(tid);
+ Jmsg(jcr, M_FATAL, 0, _("Bad response from File daemon to Hello command: ERR=%s\n"),
+ bnet_strerror(fd));
+ return 0;
+ }
+ Dmsg1(110, "<stored: %s", fd->msg);
+ stop_bsock_timer(tid);
+ if (strncmp(fd->msg, FDOKhello, sizeof(FDOKhello)) != 0) {
+ Jmsg(jcr, M_FATAL, 0, _("File daemon rejected Hello command\n"));
+ return 0;
+ }
+ return 1;
+}
--- /dev/null
+
+extern "C" {
+
+#include <glib-object.h>
+
+
+#ifdef G_ENABLE_DEBUG
+#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)
+#define g_marshal_value_peek_char(v) g_value_get_char (v)
+#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)
+#define g_marshal_value_peek_int(v) g_value_get_int (v)
+#define g_marshal_value_peek_uint(v) g_value_get_uint (v)
+#define g_marshal_value_peek_long(v) g_value_get_long (v)
+#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)
+#define g_marshal_value_peek_int64(v) g_value_get_int64 (v)
+#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)
+#define g_marshal_value_peek_enum(v) g_value_get_enum (v)
+#define g_marshal_value_peek_flags(v) g_value_get_flags (v)
+#define g_marshal_value_peek_float(v) g_value_get_float (v)
+#define g_marshal_value_peek_double(v) g_value_get_double (v)
+#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)
+#define g_marshal_value_peek_param(v) g_value_get_param (v)
+#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)
+#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)
+#define g_marshal_value_peek_object(v) g_value_get_object (v)
+#else /* !G_ENABLE_DEBUG */
+/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
+ * Do not access GValues directly in your code. Instead, use the
+ * g_value_get_*() functions
+ */
+#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int
+#define g_marshal_value_peek_char(v) (v)->data[0].v_int
+#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint
+#define g_marshal_value_peek_int(v) (v)->data[0].v_int
+#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint
+#define g_marshal_value_peek_long(v) (v)->data[0].v_long
+#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong
+#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64
+#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64
+#define g_marshal_value_peek_enum(v) (v)->data[0].v_int
+#define g_marshal_value_peek_flags(v) (v)->data[0].v_uint
+#define g_marshal_value_peek_float(v) (v)->data[0].v_float
+#define g_marshal_value_peek_double(v) (v)->data[0].v_double
+#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer
+#endif /* !G_ENABLE_DEBUG */
+
+
+/* VOID:OBJECT,OBJECT (eggmarshalers.list:1) */
+void
+_egg_marshal_VOID__OBJECT_OBJECT (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef void (*GMarshalFunc_VOID__OBJECT_OBJECT) (gpointer data1,
+ gpointer arg_1,
+ gpointer arg_2,
+ gpointer data2);
+ register GMarshalFunc_VOID__OBJECT_OBJECT callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+
+ g_return_if_fail (n_param_values == 3);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__OBJECT_OBJECT) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ g_marshal_value_peek_object (param_values + 1),
+ g_marshal_value_peek_object (param_values + 2),
+ data2);
+}
+
+/* VOID:OBJECT,STRING,LONG,LONG (eggmarshalers.list:2) */
+void
+_egg_marshal_VOID__OBJECT_STRING_LONG_LONG (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef void (*GMarshalFunc_VOID__OBJECT_STRING_LONG_LONG) (gpointer data1,
+ gpointer arg_1,
+ gpointer arg_2,
+ glong arg_3,
+ glong arg_4,
+ gpointer data2);
+ register GMarshalFunc_VOID__OBJECT_STRING_LONG_LONG callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+
+ g_return_if_fail (n_param_values == 5);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__OBJECT_STRING_LONG_LONG) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ g_marshal_value_peek_object (param_values + 1),
+ g_marshal_value_peek_string (param_values + 2),
+ g_marshal_value_peek_long (param_values + 3),
+ g_marshal_value_peek_long (param_values + 4),
+ data2);
+}
+
+/* VOID:OBJECT,LONG (eggmarshalers.list:3) */
+void
+_egg_marshal_VOID__OBJECT_LONG (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef void (*GMarshalFunc_VOID__OBJECT_LONG) (gpointer data1,
+ gpointer arg_1,
+ glong arg_2,
+ gpointer data2);
+ register GMarshalFunc_VOID__OBJECT_LONG callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+
+ g_return_if_fail (n_param_values == 3);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__OBJECT_LONG) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ g_marshal_value_peek_object (param_values + 1),
+ g_marshal_value_peek_long (param_values + 2),
+ data2);
+}
+
+/* VOID:OBJECT,STRING,STRING (eggmarshalers.list:4) */
+void
+_egg_marshal_VOID__OBJECT_STRING_STRING (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef void (*GMarshalFunc_VOID__OBJECT_STRING_STRING) (gpointer data1,
+ gpointer arg_1,
+ gpointer arg_2,
+ gpointer arg_3,
+ gpointer data2);
+ register GMarshalFunc_VOID__OBJECT_STRING_STRING callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+
+ g_return_if_fail (n_param_values == 4);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__OBJECT_STRING_STRING) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ g_marshal_value_peek_object (param_values + 1),
+ g_marshal_value_peek_string (param_values + 2),
+ g_marshal_value_peek_string (param_values + 3),
+ data2);
+}
+
+/* VOID:UINT,UINT (eggmarshalers.list:5) */
+void
+_egg_marshal_VOID__UINT_UINT (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef void (*GMarshalFunc_VOID__UINT_UINT) (gpointer data1,
+ guint arg_1,
+ guint arg_2,
+ gpointer data2);
+ register GMarshalFunc_VOID__UINT_UINT callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+
+ g_return_if_fail (n_param_values == 3);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__UINT_UINT) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ g_marshal_value_peek_uint (param_values + 1),
+ g_marshal_value_peek_uint (param_values + 2),
+ data2);
+}
+
+/* BOOLEAN:INT (eggmarshalers.list:6) */
+void
+_egg_marshal_BOOLEAN__INT (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef gboolean (*GMarshalFunc_BOOLEAN__INT) (gpointer data1,
+ gint arg_1,
+ gpointer data2);
+ register GMarshalFunc_BOOLEAN__INT callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+ gboolean v_return;
+
+ g_return_if_fail (return_value != NULL);
+ g_return_if_fail (n_param_values == 2);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_BOOLEAN__INT) (marshal_data ? marshal_data : cc->callback);
+
+ v_return = callback (data1,
+ g_marshal_value_peek_int (param_values + 1),
+ data2);
+
+ g_value_set_boolean (return_value, v_return);
+}
+
+/* BOOLEAN:ENUM (eggmarshalers.list:7) */
+void
+_egg_marshal_BOOLEAN__ENUM (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef gboolean (*GMarshalFunc_BOOLEAN__ENUM) (gpointer data1,
+ gint arg_1,
+ gpointer data2);
+ register GMarshalFunc_BOOLEAN__ENUM callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+ gboolean v_return;
+
+ g_return_if_fail (return_value != NULL);
+ g_return_if_fail (n_param_values == 2);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_BOOLEAN__ENUM) (marshal_data ? marshal_data : cc->callback);
+
+ v_return = callback (data1,
+ g_marshal_value_peek_enum (param_values + 1),
+ data2);
+
+ g_value_set_boolean (return_value, v_return);
+}
+
+/* BOOLEAN:VOID (eggmarshalers.list:8) */
+void
+_egg_marshal_BOOLEAN__VOID (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef gboolean (*GMarshalFunc_BOOLEAN__VOID) (gpointer data1,
+ gpointer data2);
+ register GMarshalFunc_BOOLEAN__VOID callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+ gboolean v_return;
+
+ g_return_if_fail (return_value != NULL);
+ g_return_if_fail (n_param_values == 1);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_BOOLEAN__VOID) (marshal_data ? marshal_data : cc->callback);
+
+ v_return = callback (data1,
+ data2);
+
+ g_value_set_boolean (return_value, v_return);
+}
+
+/* OBJECT:VOID (eggmarshalers.list:9) */
+void
+_egg_marshal_OBJECT__VOID (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef GObject* (*GMarshalFunc_OBJECT__VOID) (gpointer data1,
+ gpointer data2);
+ register GMarshalFunc_OBJECT__VOID callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+ GObject* v_return;
+
+ g_return_if_fail (return_value != NULL);
+ g_return_if_fail (n_param_values == 1);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_OBJECT__VOID) (marshal_data ? marshal_data : cc->callback);
+
+ v_return = callback (data1,
+ data2);
+
+ g_value_set_object_take_ownership (return_value, v_return);
+}
+
+/* VOID:VOID (eggmarshalers.list:10) */
+
+/* VOID:INT,INT (eggmarshalers.list:11) */
+void
+_egg_marshal_VOID__INT_INT (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef void (*GMarshalFunc_VOID__INT_INT) (gpointer data1,
+ gint arg_1,
+ gint arg_2,
+ gpointer data2);
+ register GMarshalFunc_VOID__INT_INT callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+
+ g_return_if_fail (n_param_values == 3);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__INT_INT) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ g_marshal_value_peek_int (param_values + 1),
+ g_marshal_value_peek_int (param_values + 2),
+ data2);
+}
+
+/* VOID:UINT,UINT (eggmarshalers.list:12) */
+
+/* VOID:BOOLEAN (eggmarshalers.list:13) */
+
+/* VOID:OBJECT,ENUM,BOXED (eggmarshalers.list:14) */
+void
+_egg_marshal_VOID__OBJECT_ENUM_BOXED (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef void (*GMarshalFunc_VOID__OBJECT_ENUM_BOXED) (gpointer data1,
+ gpointer arg_1,
+ gint arg_2,
+ gpointer arg_3,
+ gpointer data2);
+ register GMarshalFunc_VOID__OBJECT_ENUM_BOXED callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+
+ g_return_if_fail (n_param_values == 4);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__OBJECT_ENUM_BOXED) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ g_marshal_value_peek_object (param_values + 1),
+ g_marshal_value_peek_enum (param_values + 2),
+ g_marshal_value_peek_boxed (param_values + 3),
+ data2);
+}
+
+/* VOID:BOXED (eggmarshalers.list:15) */
+
+/* BOOLEAN:BOOLEAN (eggmarshalers.list:16) */
+void
+_egg_marshal_BOOLEAN__BOOLEAN (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef gboolean (*GMarshalFunc_BOOLEAN__BOOLEAN) (gpointer data1,
+ gboolean arg_1,
+ gpointer data2);
+ register GMarshalFunc_BOOLEAN__BOOLEAN callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+ gboolean v_return;
+
+ g_return_if_fail (return_value != NULL);
+ g_return_if_fail (n_param_values == 2);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_BOOLEAN__BOOLEAN) (marshal_data ? marshal_data : cc->callback);
+
+ v_return = callback (data1,
+ g_marshal_value_peek_boolean (param_values + 1),
+ data2);
+
+ g_value_set_boolean (return_value, v_return);
+}
+
+/* BOOLEAN:OBJECT,STRING,STRING (eggmarshalers.list:17) */
+void
+_egg_marshal_BOOLEAN__OBJECT_STRING_STRING (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef gboolean (*GMarshalFunc_BOOLEAN__OBJECT_STRING_STRING) (gpointer data1,
+ gpointer arg_1,
+ gpointer arg_2,
+ gpointer arg_3,
+ gpointer data2);
+ register GMarshalFunc_BOOLEAN__OBJECT_STRING_STRING callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+ gboolean v_return;
+
+ g_return_if_fail (return_value != NULL);
+ g_return_if_fail (n_param_values == 4);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_BOOLEAN__OBJECT_STRING_STRING) (marshal_data ? marshal_data : cc->callback);
+
+ v_return = callback (data1,
+ g_marshal_value_peek_object (param_values + 1),
+ g_marshal_value_peek_string (param_values + 2),
+ g_marshal_value_peek_string (param_values + 3),
+ data2);
+
+ g_value_set_boolean (return_value, v_return);
+}
+
+} // extern "C"
--- /dev/null
+
+#ifndef ___egg_marshal_MARSHAL_H__
+#define ___egg_marshal_MARSHAL_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/* VOID:OBJECT,OBJECT (eggmarshalers.list:1) */
+extern void _egg_marshal_VOID__OBJECT_OBJECT (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+/* VOID:OBJECT,STRING,LONG,LONG (eggmarshalers.list:2) */
+extern void _egg_marshal_VOID__OBJECT_STRING_LONG_LONG (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+/* VOID:OBJECT,LONG (eggmarshalers.list:3) */
+extern void _egg_marshal_VOID__OBJECT_LONG (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+/* VOID:OBJECT,STRING,STRING (eggmarshalers.list:4) */
+extern void _egg_marshal_VOID__OBJECT_STRING_STRING (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+/* VOID:UINT,UINT (eggmarshalers.list:5) */
+extern void _egg_marshal_VOID__UINT_UINT (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+/* BOOLEAN:INT (eggmarshalers.list:6) */
+extern void _egg_marshal_BOOLEAN__INT (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+/* BOOLEAN:ENUM (eggmarshalers.list:7) */
+extern void _egg_marshal_BOOLEAN__ENUM (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+/* BOOLEAN:VOID (eggmarshalers.list:8) */
+extern void _egg_marshal_BOOLEAN__VOID (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+/* OBJECT:VOID (eggmarshalers.list:9) */
+extern void _egg_marshal_OBJECT__VOID (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+/* VOID:VOID (eggmarshalers.list:10) */
+#define _egg_marshal_VOID__VOID g_cclosure_marshal_VOID__VOID
+
+/* VOID:INT,INT (eggmarshalers.list:11) */
+extern void _egg_marshal_VOID__INT_INT (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+/* VOID:UINT,UINT (eggmarshalers.list:12) */
+
+/* VOID:BOOLEAN (eggmarshalers.list:13) */
+#define _egg_marshal_VOID__BOOLEAN g_cclosure_marshal_VOID__BOOLEAN
+
+/* VOID:OBJECT,ENUM,BOXED (eggmarshalers.list:14) */
+extern void _egg_marshal_VOID__OBJECT_ENUM_BOXED (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+/* VOID:BOXED (eggmarshalers.list:15) */
+#define _egg_marshal_VOID__BOXED g_cclosure_marshal_VOID__BOXED
+
+/* BOOLEAN:BOOLEAN (eggmarshalers.list:16) */
+extern void _egg_marshal_BOOLEAN__BOOLEAN (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+/* BOOLEAN:OBJECT,STRING,STRING (eggmarshalers.list:17) */
+extern void _egg_marshal_BOOLEAN__OBJECT_STRING_STRING (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+G_END_DECLS
+
+#endif /* ___egg_marshal_MARSHAL_H__ */
+
--- /dev/null
+VOID:OBJECT,OBJECT
+VOID:OBJECT,STRING,LONG,LONG
+VOID:OBJECT,LONG
+VOID:OBJECT,STRING,STRING
+VOID:UINT,UINT
+BOOLEAN:INT
+BOOLEAN:ENUM
+BOOLEAN:VOID
+OBJECT:VOID
+VOID:VOID
+VOID:INT,INT
+VOID:UINT,UINT
+VOID:BOOLEAN
+VOID:OBJECT,ENUM,BOXED
+VOID:BOXED
+BOOLEAN:BOOLEAN
+BOOLEAN:OBJECT,STRING,STRING
--- /dev/null
+/* eggstatusicon.c:
+ *
+ * Copyright (C) 2003 Sun Microsystems, Inc.
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ * Mark McLoughlin <mark@skynet.ie>
+ */
+
+#include <string.h>
+#include <libintl.h>
+
+#include "eggstatusicon.h"
+
+#include <gtk/gtk.h>
+#include "eggmarshalers.h"
+
+#ifndef EGG_COMPILATION
+#ifndef _
+#define _(x) dgettext (GETTEXT_PACKAGE, x)
+#define N_(x) x
+#endif
+#else
+#define _(x) x
+#define N_(x) x
+#endif
+
+enum{
+ PROP_0,
+ PROP_PIXBUF,
+ PROP_FILE,
+ PROP_STOCK,
+ PROP_PIXBUF_ANIMATION,
+ PROP_STORAGE_TYPE,
+ PROP_SIZE,
+ PROP_BLINKING
+};
+
+enum {
+ ACTIVATE_SIGNAL,
+ POPUP_MENU_SIGNAL,
+ SIZE_CHANGED_SIGNAL,
+ LAST_SIGNAL
+};
+
+struct _EggStatusIconPrivate
+{
+ GtkWidget *tray_icon;
+ GtkWidget *image;
+ gint size;
+
+ GtkTooltips *tooltips;
+
+ GtkImageType image_type;
+
+ union
+ {
+ GdkPixbuf *pixbuf;
+ const gchar *stock_id;
+ GdkPixbufAnimation *animimation;
+ } image_data;
+
+ GdkPixbuf *blank_icon;
+ guint blinking_timeout;
+
+ guint blinking : 1;
+ guint blink_off : 1;
+};
+
+static void egg_status_icon_class_init (EggStatusIconClass *klass);
+static void egg_status_icon_init (EggStatusIcon *status_icon);
+
+static void egg_status_icon_finalize (GObject *object);
+static void egg_status_icon_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void egg_status_icon_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+static void egg_status_icon_size_allocate (EggStatusIcon *status_icon,
+ GtkAllocation *allocation);
+static gboolean egg_status_icon_button_release (EggStatusIcon *status_icon,
+ GdkEventButton *event);
+static void egg_status_icon_disable_blinking (EggStatusIcon *status_icon);
+static void egg_status_icon_reset_image_data (EggStatusIcon *status_icon);
+
+
+static GObjectClass *parent_class = NULL;
+static guint status_icon_signals [LAST_SIGNAL] = { 0 };
+
+GType
+egg_status_icon_get_type (void)
+{
+ static GType status_icon_type = 0;
+
+ if (!status_icon_type)
+ {
+ static const GTypeInfo status_icon_info =
+ {
+ sizeof (EggStatusIconClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) egg_status_icon_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (EggStatusIcon),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) egg_status_icon_init,
+ };
+
+ status_icon_type = g_type_register_static (G_TYPE_OBJECT,
+ "EggStatusIcon",
+ &status_icon_info, (GTypeFlags)0);
+ }
+
+ return status_icon_type;
+}
+
+static void
+egg_status_icon_class_init (EggStatusIconClass *klass)
+{
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+
+ parent_class = (GObjectClass*)g_type_class_peek_parent (klass);
+
+ gobject_class->finalize = egg_status_icon_finalize;
+ gobject_class->set_property = egg_status_icon_set_property;
+ gobject_class->get_property = egg_status_icon_get_property;
+
+ g_object_class_install_property (gobject_class,
+ PROP_PIXBUF,
+ g_param_spec_object ("pixbuf",
+ "Pixbuf",
+ "A GdkPixbuf to display",
+ GDK_TYPE_PIXBUF,
+ (GParamFlags)G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_FILE,
+ g_param_spec_string ("file",
+ "Filename",
+ "Filename to load and display",
+ NULL,
+ G_PARAM_WRITABLE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_STOCK,
+ g_param_spec_string ("stock",
+ "Stock ID",
+ "Stock ID for a stock image to display",
+ NULL,
+ (GParamFlags)G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_PIXBUF_ANIMATION,
+ g_param_spec_object ("pixbuf-animation",
+ "Animation",
+ "GdkPixbufAnimation to display",
+ GDK_TYPE_PIXBUF_ANIMATION,
+ (GParamFlags)G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_STORAGE_TYPE,
+ g_param_spec_enum ("image-type",
+ "Image type",
+ "The representation being used for image data",
+ GTK_TYPE_IMAGE_TYPE,
+ GTK_IMAGE_EMPTY,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_SIZE,
+ g_param_spec_int ("size",
+ "Size",
+ "The size of the icon",
+ G_MININT,
+ G_MAXINT,
+ 0,
+ G_PARAM_READABLE));
+
+ g_object_class_install_property (gobject_class,
+ PROP_BLINKING,
+ g_param_spec_boolean ("blinking",
+ "Blinking",
+ "Whether or not the status icon is blinking",
+ FALSE,
+ (GParamFlags)G_PARAM_READWRITE));
+
+ status_icon_signals [ACTIVATE_SIGNAL] =
+ g_signal_new ("activate",
+ G_TYPE_FROM_CLASS (gobject_class),
+ (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
+ G_STRUCT_OFFSET (EggStatusIconClass, activate),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ status_icon_signals [POPUP_MENU_SIGNAL] =
+ g_signal_new ("popup-menu",
+ G_TYPE_FROM_CLASS (gobject_class),
+ (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
+ G_STRUCT_OFFSET (EggStatusIconClass, popup_menu),
+ NULL,
+ NULL,
+ _egg_marshal_VOID__UINT_UINT,
+ G_TYPE_NONE,
+ 2,
+ G_TYPE_UINT,
+ G_TYPE_UINT);
+
+ status_icon_signals [SIZE_CHANGED_SIGNAL] =
+ g_signal_new ("size-changed",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (EggStatusIconClass, size_changed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__INT,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_INT);
+}
+
+static void
+egg_status_icon_init (EggStatusIcon *status_icon)
+{
+ status_icon->priv = g_new0 (EggStatusIconPrivate, 1);
+
+ status_icon->priv->image_type = GTK_IMAGE_EMPTY;
+ status_icon->priv->size = G_MAXINT;
+
+ status_icon->priv->tray_icon = GTK_WIDGET (egg_tray_icon_new (NULL));
+
+ gtk_widget_add_events (GTK_WIDGET (status_icon->priv->tray_icon),
+ GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
+
+ g_signal_connect_swapped (status_icon->priv->tray_icon, "button-release-event",
+ G_CALLBACK (egg_status_icon_button_release), status_icon);
+
+ status_icon->priv->image = gtk_image_new ();
+ gtk_container_add (GTK_CONTAINER (status_icon->priv->tray_icon),
+ status_icon->priv->image);
+
+ g_signal_connect_swapped (status_icon->priv->image, "size-allocate",
+ G_CALLBACK (egg_status_icon_size_allocate), status_icon);
+
+ gtk_widget_show (status_icon->priv->image);
+ gtk_widget_show (status_icon->priv->tray_icon);
+
+ status_icon->priv->tooltips = gtk_tooltips_new ();
+ g_object_ref (status_icon->priv->tooltips);
+ gtk_object_sink (GTK_OBJECT (status_icon->priv->tooltips));
+}
+
+static void
+egg_status_icon_finalize (GObject *object)
+{
+ EggStatusIcon *status_icon = EGG_STATUS_ICON (object);
+
+ egg_status_icon_disable_blinking (status_icon);
+
+ egg_status_icon_reset_image_data (status_icon);
+
+ if (status_icon->priv->blank_icon)
+ g_object_unref (status_icon->priv->blank_icon);
+ status_icon->priv->blank_icon = NULL;
+
+ if (status_icon->priv->tooltips)
+ g_object_unref (status_icon->priv->tooltips);
+ status_icon->priv->tooltips = NULL;
+
+ gtk_widget_destroy (status_icon->priv->tray_icon);
+
+ g_free (status_icon->priv);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+egg_status_icon_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EggStatusIcon *status_icon = EGG_STATUS_ICON (object);
+
+ switch (prop_id)
+ {
+ case PROP_PIXBUF:
+ egg_status_icon_set_from_pixbuf (status_icon, (GdkPixbuf*)g_value_get_object (value));
+ break;
+ case PROP_FILE:
+ egg_status_icon_set_from_file (status_icon, g_value_get_string (value));
+ break;
+ case PROP_STOCK:
+ egg_status_icon_set_from_stock (status_icon, g_value_get_string (value));
+ break;
+ case PROP_PIXBUF_ANIMATION:
+ egg_status_icon_set_from_animation (status_icon, (GdkPixbufAnimation*)g_value_get_object (value));
+ break;
+ case PROP_BLINKING:
+ egg_status_icon_set_is_blinking (status_icon, g_value_get_boolean (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+egg_status_icon_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EggStatusIcon *status_icon = EGG_STATUS_ICON (object);
+
+ switch (prop_id)
+ {
+ case PROP_PIXBUF:
+ g_value_set_object (value, egg_status_icon_get_pixbuf (status_icon));
+ break;
+ case PROP_STOCK:
+ g_value_set_string (value, egg_status_icon_get_stock (status_icon));
+ break;
+ case PROP_PIXBUF_ANIMATION:
+ g_value_set_object (value, egg_status_icon_get_animation (status_icon));
+ break;
+ case PROP_STORAGE_TYPE:
+ g_value_set_enum (value, egg_status_icon_get_image_type (status_icon));
+ break;
+ case PROP_SIZE:
+ g_value_set_int (value, status_icon->priv->size);
+ break;
+ case PROP_BLINKING:
+ g_value_set_boolean (value, status_icon->priv->blinking);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+EggStatusIcon *
+egg_status_icon_new (void)
+{
+ return (EggStatusIcon*)g_object_new (EGG_TYPE_STATUS_ICON, NULL);
+}
+
+EggStatusIcon *
+egg_status_icon_new_from_pixbuf (GdkPixbuf *pixbuf)
+{
+ return (EggStatusIcon*)g_object_new (EGG_TYPE_STATUS_ICON,
+ "pixbuf", pixbuf,
+ NULL);
+}
+
+EggStatusIcon *
+egg_status_icon_new_from_file (const gchar *filename)
+{
+ return (EggStatusIcon*)g_object_new (EGG_TYPE_STATUS_ICON,
+ "file", filename,
+ NULL);
+}
+
+EggStatusIcon *
+egg_status_icon_new_from_stock (const gchar *stock_id)
+{
+ return (EggStatusIcon*)g_object_new (EGG_TYPE_STATUS_ICON,
+ "stock", stock_id,
+ NULL);
+}
+
+EggStatusIcon *
+egg_status_icon_new_from_animation (GdkPixbufAnimation *animation)
+{
+ return (EggStatusIcon*)g_object_new (EGG_TYPE_STATUS_ICON,
+ "pixbuf_animation", animation,
+ NULL);
+}
+
+static void
+emit_activate_signal (EggStatusIcon *status_icon)
+{
+ g_signal_emit (status_icon,
+ status_icon_signals [ACTIVATE_SIGNAL], 0);
+}
+
+static void
+emit_popup_menu_signal (EggStatusIcon *status_icon,
+ guint button,
+ guint32 activate_time)
+{
+ g_signal_emit (status_icon,
+ status_icon_signals [POPUP_MENU_SIGNAL], 0,
+ button,
+ activate_time);
+}
+
+static gboolean
+emit_size_changed_signal (EggStatusIcon *status_icon,
+ gint size)
+{
+ gboolean handled = FALSE;
+
+ g_signal_emit (status_icon,
+ status_icon_signals [SIZE_CHANGED_SIGNAL], 0,
+ size,
+ &handled);
+
+ return handled;
+}
+
+static GdkPixbuf *
+egg_status_icon_blank_icon (EggStatusIcon *status_icon)
+{
+ if (status_icon->priv->blank_icon)
+ {
+ gint width, height;
+
+ width = gdk_pixbuf_get_width (status_icon->priv->blank_icon);
+ height = gdk_pixbuf_get_width (status_icon->priv->blank_icon);
+
+ if (width == status_icon->priv->size &&
+ height == status_icon->priv->size)
+ {
+ return status_icon->priv->blank_icon;
+ }
+ else
+ {
+ g_object_unref (status_icon->priv->blank_icon);
+ status_icon->priv->blank_icon = NULL;
+ }
+ }
+
+ status_icon->priv->blank_icon = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
+ status_icon->priv->size,
+ status_icon->priv->size);
+ if (status_icon->priv->blank_icon)
+ gdk_pixbuf_fill (status_icon->priv->blank_icon, 0);
+
+ return status_icon->priv->blank_icon;
+}
+
+static void
+egg_status_icon_update_image (EggStatusIcon *status_icon)
+{
+ if (status_icon->priv->blink_off)
+ {
+ gtk_image_set_from_pixbuf (GTK_IMAGE (status_icon->priv->image),
+ egg_status_icon_blank_icon (status_icon));
+ return;
+ }
+
+ switch (status_icon->priv->image_type)
+ {
+ case GTK_IMAGE_PIXBUF:
+ {
+ GdkPixbuf *pixbuf;
+
+ pixbuf = status_icon->priv->image_data.pixbuf;
+
+ if (pixbuf)
+ {
+ GdkPixbuf *scaled;
+ gint size;
+ gint width;
+ gint height;
+
+ size = status_icon->priv->size;
+
+ width = gdk_pixbuf_get_width (pixbuf);
+ height = gdk_pixbuf_get_height (pixbuf);
+
+ if (width > size || height > size)
+ {
+ scaled = gdk_pixbuf_scale_simple (pixbuf,
+ MIN (size, width),
+ MIN (size, height),
+ GDK_INTERP_BILINEAR);
+ }
+ else
+ {
+ scaled = (GdkPixbuf*)g_object_ref (pixbuf);
+ }
+
+ gtk_image_set_from_pixbuf (GTK_IMAGE (status_icon->priv->image), scaled);
+
+ g_object_unref (scaled);
+ }
+ else
+ {
+ gtk_image_set_from_pixbuf (GTK_IMAGE (status_icon->priv->image), NULL);
+ }
+ }
+ break;
+ case GTK_IMAGE_STOCK:
+ case GTK_IMAGE_ANIMATION:
+ case GTK_IMAGE_EMPTY:
+ gtk_image_set_from_pixbuf (GTK_IMAGE (status_icon->priv->image), NULL);
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+static void
+egg_status_icon_size_allocate (EggStatusIcon *status_icon,
+ GtkAllocation *allocation)
+{
+ GtkOrientation orientation;
+ gint size;
+
+ orientation = egg_tray_icon_get_orientation (EGG_TRAY_ICON (status_icon->priv->tray_icon));
+
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ size = allocation->height;
+ else
+ size = allocation->width;
+
+ if (status_icon->priv->size != size)
+ {
+ status_icon->priv->size = size;
+
+ g_object_notify (G_OBJECT (status_icon), "size");
+
+ if (!emit_size_changed_signal (status_icon, size))
+ {
+ egg_status_icon_update_image (status_icon);
+ }
+ }
+}
+
+static gboolean
+egg_status_icon_button_release (EggStatusIcon *status_icon,
+ GdkEventButton *event)
+{
+ if (event->button == 1)
+ {
+ emit_activate_signal (status_icon);
+ return TRUE;
+ }
+ if (event->button == 3)
+ {
+ emit_popup_menu_signal (status_icon, event->button, event->time);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+egg_status_icon_reset_image_data (EggStatusIcon *status_icon)
+{
+ switch (status_icon->priv->image_type)
+ {
+ case GTK_IMAGE_PIXBUF:
+ status_icon->priv->image_type = GTK_IMAGE_EMPTY;
+
+ if (status_icon->priv->image_data.pixbuf)
+ g_object_unref (status_icon->priv->image_data.pixbuf);
+ status_icon->priv->image_data.pixbuf = NULL;
+
+ g_object_notify (G_OBJECT (status_icon), "image-type");
+ g_object_notify (G_OBJECT (status_icon), "pixbuf");
+ break;
+ case GTK_IMAGE_STOCK:
+ case GTK_IMAGE_ANIMATION:
+ case GTK_IMAGE_EMPTY:
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+void
+egg_status_icon_set_from_pixbuf (EggStatusIcon *status_icon,
+ GdkPixbuf *pixbuf)
+{
+ g_return_if_fail (EGG_IS_STATUS_ICON (status_icon));
+ g_return_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf));
+
+ if (pixbuf)
+ g_object_ref (pixbuf);
+
+ g_object_freeze_notify (G_OBJECT (status_icon));
+
+ egg_status_icon_reset_image_data (status_icon);
+
+ status_icon->priv->image_type = GTK_IMAGE_PIXBUF;
+ status_icon->priv->image_data.pixbuf = pixbuf;
+
+ g_object_notify (G_OBJECT (status_icon), "image-type");
+ g_object_notify (G_OBJECT (status_icon), "pixbuf");
+
+ g_object_thaw_notify (G_OBJECT (status_icon));
+
+ egg_status_icon_update_image (status_icon);
+}
+
+void
+egg_status_icon_set_from_file (EggStatusIcon *status_icon,
+ const gchar *filename)
+{
+ g_return_if_fail (EGG_IS_STATUS_ICON (status_icon));
+}
+
+void
+egg_status_icon_set_from_stock (EggStatusIcon *status_icon,
+ const gchar *stock_id)
+{
+ g_return_if_fail (EGG_IS_STATUS_ICON (status_icon));
+}
+
+void
+egg_status_icon_set_from_animation (EggStatusIcon *status_icon,
+ GdkPixbufAnimation *animation)
+{
+ g_return_if_fail (EGG_IS_STATUS_ICON (status_icon));
+ g_return_if_fail (animation == NULL || GDK_IS_PIXBUF_ANIMATION (animation));
+}
+
+GtkImageType
+egg_status_icon_get_image_type (EggStatusIcon *status_icon)
+{
+ g_return_val_if_fail (EGG_IS_STATUS_ICON (status_icon), GTK_IMAGE_EMPTY);
+
+ return status_icon->priv->image_type;
+}
+
+GdkPixbuf *
+egg_status_icon_get_pixbuf (EggStatusIcon *status_icon)
+{
+ g_return_val_if_fail (EGG_IS_STATUS_ICON (status_icon), NULL);
+ g_return_val_if_fail (status_icon->priv->image_type == GTK_IMAGE_PIXBUF ||
+ status_icon->priv->image_type == GTK_IMAGE_EMPTY, NULL);
+
+ if (status_icon->priv->image_type == GTK_IMAGE_EMPTY)
+ status_icon->priv->image_data.pixbuf = NULL;
+
+ return status_icon->priv->image_data.pixbuf;
+}
+
+G_CONST_RETURN gchar *
+egg_status_icon_get_stock (EggStatusIcon *status_icon)
+{
+ g_return_val_if_fail (EGG_IS_STATUS_ICON (status_icon), NULL);
+
+ return NULL;
+}
+
+GdkPixbufAnimation *
+egg_status_icon_get_animation (EggStatusIcon *status_icon)
+{
+ g_return_val_if_fail (EGG_IS_STATUS_ICON (status_icon), NULL);
+
+ return NULL;
+}
+
+gint
+egg_status_icon_get_size (EggStatusIcon *status_icon)
+{
+ g_return_val_if_fail (EGG_IS_STATUS_ICON (status_icon), -1);
+
+ return status_icon->priv->size;
+}
+
+void
+egg_status_icon_set_tooltip (EggStatusIcon *status_icon,
+ const gchar *tooltip_text,
+ const gchar *tooltip_private)
+{
+ g_return_if_fail (EGG_IS_STATUS_ICON (status_icon));
+
+ gtk_tooltips_set_tip (status_icon->priv->tooltips,
+ status_icon->priv->tray_icon,
+ tooltip_text,
+ tooltip_private);
+}
+
+void
+egg_status_icon_set_balloon_text (EggStatusIcon *status_icon,
+ const gchar *text)
+{
+ g_return_if_fail (EGG_IS_STATUS_ICON (status_icon));
+}
+
+G_CONST_RETURN gchar *
+egg_status_icon_get_balloon_text (EggStatusIcon *status_icon)
+{
+ g_return_val_if_fail (EGG_IS_STATUS_ICON (status_icon), NULL);
+
+ return NULL;
+}
+
+static gboolean
+egg_status_icon_blinker (EggStatusIcon *status_icon)
+{
+ status_icon->priv->blink_off = !status_icon->priv->blink_off;
+
+ egg_status_icon_update_image (status_icon);
+
+ return TRUE;
+}
+
+static void
+egg_status_icon_enable_blinking (EggStatusIcon *status_icon)
+{
+ if (!status_icon->priv->blinking_timeout)
+ {
+ egg_status_icon_blinker (status_icon);
+
+ status_icon->priv->blinking_timeout =
+ g_timeout_add (500, (GSourceFunc) egg_status_icon_blinker, status_icon);
+ }
+}
+
+static void
+egg_status_icon_disable_blinking (EggStatusIcon *status_icon)
+{
+ if (status_icon->priv->blinking_timeout)
+ {
+ g_source_remove (status_icon->priv->blinking_timeout);
+ status_icon->priv->blinking_timeout = 0;
+ status_icon->priv->blink_off = FALSE;
+
+ egg_status_icon_update_image (status_icon);
+ }
+}
+
+void
+egg_status_icon_set_is_blinking (EggStatusIcon *status_icon,
+ gboolean is_blinking)
+{
+ g_return_if_fail (EGG_IS_STATUS_ICON (status_icon));
+
+ is_blinking = is_blinking != FALSE;
+
+ if (status_icon->priv->blinking != is_blinking)
+ {
+ status_icon->priv->blinking = is_blinking;
+
+ if (is_blinking)
+ egg_status_icon_enable_blinking (status_icon);
+ else
+ egg_status_icon_disable_blinking (status_icon);
+
+ g_object_notify (G_OBJECT (status_icon), "blinking");
+ }
+}
+
+gboolean
+egg_status_icon_get_is_blinking (EggStatusIcon *status_icon)
+{
+ g_return_val_if_fail (EGG_IS_STATUS_ICON (status_icon), FALSE);
+
+ return status_icon->priv->blinking;
+}
--- /dev/null
+/* eggstatusicon.h:
+ *
+ * Copyright (C) 2003 Sun Microsystems, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ * Mark McLoughlin <mark@skynet.ie>
+ */
+
+#ifndef __EGG_STATUS_ICON_H__
+#define __EGG_STATUS_ICON_H__
+
+#include "eggtrayicon.h"
+#include <gtk/gtkimage.h>
+
+G_BEGIN_DECLS
+
+#define EGG_TYPE_STATUS_ICON (egg_status_icon_get_type ())
+#define EGG_STATUS_ICON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EGG_TYPE_STATUS_ICON, EggStatusIcon))
+#define EGG_STATUS_ICON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), EGG_TYPE_STATUS_ICON, EggStatusIconClass))
+#define EGG_IS_STATUS_ICON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EGG_TYPE_STATUS_ICON))
+#define EGG_IS_STATUS_ICON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EGG_TYPE_STATUS_ICON))
+#define EGG_STATUS_ICON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EGG_TYPE_STATUS_ICON, EggStatusIconClass))
+
+typedef struct _EggStatusIcon EggStatusIcon;
+typedef struct _EggStatusIconClass EggStatusIconClass;
+typedef struct _EggStatusIconPrivate EggStatusIconPrivate;
+
+struct _EggStatusIcon
+{
+ GObject parent_instance;
+
+ EggStatusIconPrivate *priv;
+};
+
+struct _EggStatusIconClass
+{
+ GObjectClass parent_class;
+
+ void (* activate) (EggStatusIcon *status_icon);
+ void (* popup_menu) (EggStatusIcon *status_icon,
+ guint buttton,
+ guint32 activate_time);
+ gboolean (* size_changed) (EggStatusIcon *status_icon,
+ gint size);
+};
+
+GType egg_status_icon_get_type (void);
+
+EggStatusIcon *egg_status_icon_new (void);
+EggStatusIcon *egg_status_icon_new_from_pixbuf (GdkPixbuf *pixbuf);
+EggStatusIcon *egg_status_icon_new_from_file (const gchar *filename);
+EggStatusIcon *egg_status_icon_new_from_stock (const gchar *stock_id);
+EggStatusIcon *egg_status_icon_new_from_animation (GdkPixbufAnimation *animation);
+
+void egg_status_icon_set_from_pixbuf (EggStatusIcon *status_icon,
+ GdkPixbuf *pixbuf);
+void egg_status_icon_set_from_file (EggStatusIcon *status_icon,
+ const gchar *filename);
+void egg_status_icon_set_from_stock (EggStatusIcon *status_icon,
+ const gchar *stock_id);
+void egg_status_icon_set_from_animation (EggStatusIcon *status_icon,
+ GdkPixbufAnimation *animation);
+
+GtkImageType egg_status_icon_get_image_type (EggStatusIcon *status_icon);
+
+GdkPixbuf *egg_status_icon_get_pixbuf (EggStatusIcon *status_icon);
+G_CONST_RETURN gchar *egg_status_icon_get_stock (EggStatusIcon *status_icon);
+GdkPixbufAnimation *egg_status_icon_get_animation (EggStatusIcon *status_icon);
+
+gint egg_status_icon_get_size (EggStatusIcon *status_icon);
+
+void egg_status_icon_set_tooltip (EggStatusIcon *status_icon,
+ const gchar *tooltip_text,
+ const gchar *tooltip_private);
+
+void egg_status_icon_set_balloon_text (EggStatusIcon *status_icon,
+ const gchar *text);
+G_CONST_RETURN gchar *egg_status_icon_get_balloon_text (EggStatusIcon *status_icon);
+
+void egg_status_icon_set_is_blinking (EggStatusIcon *status_icon,
+ gboolean enable_blinking);
+gboolean egg_status_icon_get_is_blinking (EggStatusIcon *status_icon);
+
+G_END_DECLS
+
+#endif /* __EGG_STATUS_ICON_H__ */
--- /dev/null
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* eggtrayicon.c
+ * Copyright (C) 2002 Anders Carlsson <andersca@gnu.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+#include <libintl.h>
+
+#include "eggtrayicon.h"
+
+#include <gdk/gdkx.h>
+#include <X11/Xatom.h>
+
+#ifndef EGG_COMPILATION
+#ifndef _
+#define _(x) dgettext (GETTEXT_PACKAGE, x)
+#define N_(x) x
+#endif
+#else
+#define _(x) x
+#define N_(x) x
+#endif
+
+#define SYSTEM_TRAY_REQUEST_DOCK 0
+#define SYSTEM_TRAY_BEGIN_MESSAGE 1
+#define SYSTEM_TRAY_CANCEL_MESSAGE 2
+
+#define SYSTEM_TRAY_ORIENTATION_HORZ 0
+#define SYSTEM_TRAY_ORIENTATION_VERT 1
+
+enum {
+ PROP_0,
+ PROP_ORIENTATION
+};
+
+static GtkPlugClass *parent_class = NULL;
+
+static void egg_tray_icon_init (EggTrayIcon *icon);
+static void egg_tray_icon_class_init (EggTrayIconClass *klass);
+
+static void egg_tray_icon_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+static void egg_tray_icon_realize (GtkWidget *widget);
+static void egg_tray_icon_unrealize (GtkWidget *widget);
+
+static void egg_tray_icon_update_manager_window (EggTrayIcon *icon);
+
+GType
+egg_tray_icon_get_type (void)
+{
+ static GType our_type = 0;
+
+ if (our_type == 0)
+ {
+ static const GTypeInfo our_info =
+ {
+ sizeof (EggTrayIconClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) egg_tray_icon_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (EggTrayIcon),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) egg_tray_icon_init
+ };
+
+ our_type = g_type_register_static (GTK_TYPE_PLUG, "EggTrayIcon", &our_info, (GTypeFlags)0);
+ }
+
+ return our_type;
+}
+
+static void
+egg_tray_icon_init (EggTrayIcon *icon)
+{
+ icon->stamp = 1;
+ icon->orientation = GTK_ORIENTATION_HORIZONTAL;
+
+ gtk_widget_add_events (GTK_WIDGET (icon), GDK_PROPERTY_CHANGE_MASK);
+}
+
+static void
+egg_tray_icon_class_init (EggTrayIconClass *klass)
+{
+ GObjectClass *gobject_class = (GObjectClass *)klass;
+ GtkWidgetClass *widget_class = (GtkWidgetClass *)klass;
+
+ parent_class = (GtkPlugClass*)g_type_class_peek_parent (klass);
+
+ gobject_class->get_property = egg_tray_icon_get_property;
+
+ widget_class->realize = egg_tray_icon_realize;
+ widget_class->unrealize = egg_tray_icon_unrealize;
+
+ g_object_class_install_property (gobject_class,
+ PROP_ORIENTATION,
+ g_param_spec_enum ("orientation",
+ "Orientation",
+ "The orientation of the tray.",
+ GTK_TYPE_ORIENTATION,
+ GTK_ORIENTATION_HORIZONTAL,
+ G_PARAM_READABLE));
+}
+
+static void
+egg_tray_icon_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EggTrayIcon *icon = EGG_TRAY_ICON (object);
+
+ switch (prop_id)
+ {
+ case PROP_ORIENTATION:
+ g_value_set_enum (value, icon->orientation);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+egg_tray_icon_get_orientation_property (EggTrayIcon *icon)
+{
+ Display *xdisplay;
+ Atom type;
+ int format;
+ union {
+ gulong *prop;
+ guchar *prop_ch;
+ } prop = { NULL };
+ gulong nitems;
+ gulong bytes_after;
+ int error, result;
+
+ g_assert (icon->manager_window != None);
+
+ xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
+
+ gdk_error_trap_push ();
+ type = None;
+ result = XGetWindowProperty (xdisplay,
+ icon->manager_window,
+ icon->orientation_atom,
+ 0, G_MAXLONG, FALSE,
+ XA_CARDINAL,
+ &type, &format, &nitems,
+ &bytes_after, &(prop.prop_ch));
+ error = gdk_error_trap_pop ();
+
+ if (error || result != Success)
+ return;
+
+ if (type == XA_CARDINAL)
+ {
+ GtkOrientation orientation;
+
+ orientation = (prop.prop [0] == SYSTEM_TRAY_ORIENTATION_HORZ) ?
+ GTK_ORIENTATION_HORIZONTAL :
+ GTK_ORIENTATION_VERTICAL;
+
+ if (icon->orientation != orientation)
+ {
+ icon->orientation = orientation;
+
+ g_object_notify (G_OBJECT (icon), "orientation");
+ }
+ }
+
+ if (prop.prop)
+ XFree (prop.prop);
+}
+
+static GdkFilterReturn
+egg_tray_icon_manager_filter (GdkXEvent *xevent, GdkEvent *event, gpointer user_data)
+{
+ EggTrayIcon *icon = (EggTrayIcon*)user_data;
+ XEvent *xev = (XEvent *)xevent;
+
+ if (xev->xany.type == ClientMessage &&
+ xev->xclient.message_type == icon->manager_atom &&
+ xev->xclient.data.l[1] == icon->selection_atom)
+ {
+ egg_tray_icon_update_manager_window (icon);
+ }
+ else if (xev->xany.window == icon->manager_window)
+ {
+ if (xev->xany.type == PropertyNotify &&
+ xev->xproperty.atom == icon->orientation_atom)
+ {
+ egg_tray_icon_get_orientation_property (icon);
+ }
+ if (xev->xany.type == DestroyNotify)
+ {
+ egg_tray_icon_update_manager_window (icon);
+ }
+ }
+
+ return GDK_FILTER_CONTINUE;
+}
+
+static void
+egg_tray_icon_unrealize (GtkWidget *widget)
+{
+ EggTrayIcon *icon = EGG_TRAY_ICON (widget);
+ GdkWindow *root_window;
+
+ if (icon->manager_window != None)
+ {
+ GdkWindow *gdkwin;
+
+ gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (widget),
+ icon->manager_window);
+
+ gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon);
+ }
+
+ root_window = gdk_screen_get_root_window (gtk_widget_get_screen (widget));
+
+ gdk_window_remove_filter (root_window, egg_tray_icon_manager_filter, icon);
+
+ if (GTK_WIDGET_CLASS (parent_class)->unrealize)
+ (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
+}
+
+static void
+egg_tray_icon_send_manager_message (EggTrayIcon *icon,
+ long message,
+ Window window,
+ long data1,
+ long data2,
+ long data3)
+{
+ XClientMessageEvent ev;
+ Display *display;
+
+ ev.type = ClientMessage;
+ ev.window = window;
+ ev.message_type = icon->system_tray_opcode_atom;
+ ev.format = 32;
+ ev.data.l[0] = gdk_x11_get_server_time (GTK_WIDGET (icon)->window);
+ ev.data.l[1] = message;
+ ev.data.l[2] = data1;
+ ev.data.l[3] = data2;
+ ev.data.l[4] = data3;
+
+ display = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
+
+ gdk_error_trap_push ();
+ XSendEvent (display,
+ icon->manager_window, False, NoEventMask, (XEvent *)&ev);
+ XSync (display, False);
+ gdk_error_trap_pop ();
+}
+
+static void
+egg_tray_icon_send_dock_request (EggTrayIcon *icon)
+{
+ egg_tray_icon_send_manager_message (icon,
+ SYSTEM_TRAY_REQUEST_DOCK,
+ icon->manager_window,
+ gtk_plug_get_id (GTK_PLUG (icon)),
+ 0, 0);
+}
+
+static void
+egg_tray_icon_update_manager_window (EggTrayIcon *icon)
+{
+ Display *xdisplay;
+
+ xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
+
+ if (icon->manager_window != None)
+ {
+ GdkWindow *gdkwin;
+
+ gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)),
+ icon->manager_window);
+
+ gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon);
+ }
+
+ XGrabServer (xdisplay);
+
+ icon->manager_window = XGetSelectionOwner (xdisplay,
+ icon->selection_atom);
+
+ if (icon->manager_window != None)
+ XSelectInput (xdisplay,
+ icon->manager_window, StructureNotifyMask|PropertyChangeMask);
+
+ XUngrabServer (xdisplay);
+ XFlush (xdisplay);
+
+ if (icon->manager_window != None)
+ {
+ GdkWindow *gdkwin;
+
+ gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)),
+ icon->manager_window);
+
+ gdk_window_add_filter (gdkwin, egg_tray_icon_manager_filter, icon);
+
+ /* Send a request that we'd like to dock */
+ egg_tray_icon_send_dock_request (icon);
+
+ egg_tray_icon_get_orientation_property (icon);
+ }
+}
+
+static void
+egg_tray_icon_realize (GtkWidget *widget)
+{
+ EggTrayIcon *icon = EGG_TRAY_ICON (widget);
+ GdkScreen *screen;
+ GdkDisplay *display;
+ Display *xdisplay;
+ char buffer[256];
+ GdkWindow *root_window;
+
+ if (GTK_WIDGET_CLASS (parent_class)->realize)
+ GTK_WIDGET_CLASS (parent_class)->realize (widget);
+
+ screen = gtk_widget_get_screen (widget);
+ display = gdk_screen_get_display (screen);
+ xdisplay = gdk_x11_display_get_xdisplay (display);
+
+ /* Now see if there's a manager window around */
+ g_snprintf (buffer, sizeof (buffer),
+ "_NET_SYSTEM_TRAY_S%d",
+ gdk_screen_get_number (screen));
+
+ icon->selection_atom = XInternAtom (xdisplay, buffer, False);
+
+ icon->manager_atom = XInternAtom (xdisplay, "MANAGER", False);
+
+ icon->system_tray_opcode_atom = XInternAtom (xdisplay,
+ "_NET_SYSTEM_TRAY_OPCODE",
+ False);
+
+ icon->orientation_atom = XInternAtom (xdisplay,
+ "_NET_SYSTEM_TRAY_ORIENTATION",
+ False);
+
+ egg_tray_icon_update_manager_window (icon);
+
+ root_window = gdk_screen_get_root_window (screen);
+
+ /* Add a root window filter so that we get changes on MANAGER */
+ gdk_window_add_filter (root_window,
+ egg_tray_icon_manager_filter, icon);
+}
+
+EggTrayIcon *
+egg_tray_icon_new_for_xscreen (Screen *xscreen, const char *name)
+{
+ GdkDisplay *display;
+ GdkScreen *screen;
+
+ display = gdk_x11_lookup_xdisplay (DisplayOfScreen (xscreen));
+ screen = gdk_display_get_screen (display, XScreenNumberOfScreen (xscreen));
+
+ return egg_tray_icon_new_for_screen (screen, name);
+}
+
+EggTrayIcon *
+egg_tray_icon_new_for_screen (GdkScreen *screen, const char *name)
+{
+ g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+ return (EggTrayIcon*)g_object_new (EGG_TYPE_TRAY_ICON, "screen", screen, "title", name, NULL);
+}
+
+EggTrayIcon*
+egg_tray_icon_new (const gchar *name)
+{
+ return (EggTrayIcon*)g_object_new (EGG_TYPE_TRAY_ICON, "title", name, NULL);
+}
+
+guint
+egg_tray_icon_send_message (EggTrayIcon *icon,
+ gint timeout,
+ const gchar *message,
+ gint len)
+{
+ guint stamp;
+
+ g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), 0);
+ g_return_val_if_fail (timeout >= 0, 0);
+ g_return_val_if_fail (message != NULL, 0);
+
+ if (icon->manager_window == None)
+ return 0;
+
+ if (len < 0)
+ len = strlen (message);
+
+ stamp = icon->stamp++;
+
+ /* Get ready to send the message */
+ egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_BEGIN_MESSAGE,
+ (Window)gtk_plug_get_id (GTK_PLUG (icon)),
+ timeout, len, stamp);
+
+ /* Now to send the actual message */
+ gdk_error_trap_push ();
+ while (len > 0)
+ {
+ XClientMessageEvent ev;
+ Display *xdisplay;
+
+ xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon)));
+
+ ev.type = ClientMessage;
+ ev.window = (Window)gtk_plug_get_id (GTK_PLUG (icon));
+ ev.format = 8;
+ ev.message_type = XInternAtom (xdisplay,
+ "_NET_SYSTEM_TRAY_MESSAGE_DATA", False);
+ if (len > 20)
+ {
+ memcpy (&ev.data, message, 20);
+ len -= 20;
+ message += 20;
+ }
+ else
+ {
+ memcpy (&ev.data, message, len);
+ len = 0;
+ }
+
+ XSendEvent (xdisplay,
+ icon->manager_window, False, StructureNotifyMask, (XEvent *)&ev);
+ XSync (xdisplay, False);
+ }
+ gdk_error_trap_pop ();
+
+ return stamp;
+}
+
+void
+egg_tray_icon_cancel_message (EggTrayIcon *icon,
+ guint id)
+{
+ g_return_if_fail (EGG_IS_TRAY_ICON (icon));
+ g_return_if_fail (id > 0);
+
+ egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_CANCEL_MESSAGE,
+ (Window)gtk_plug_get_id (GTK_PLUG (icon)),
+ id, 0, 0);
+}
+
+GtkOrientation
+egg_tray_icon_get_orientation (EggTrayIcon *icon)
+{
+ g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), GTK_ORIENTATION_HORIZONTAL);
+
+ return icon->orientation;
+}
--- /dev/null
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* eggtrayicon.h
+ * Copyright (C) 2002 Anders Carlsson <andersca@gnu.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EGG_TRAY_ICON_H__
+#define __EGG_TRAY_ICON_H__
+
+#include <gtk/gtkplug.h>
+#include <gdk/gdkx.h>
+
+G_BEGIN_DECLS
+
+#define EGG_TYPE_TRAY_ICON (egg_tray_icon_get_type ())
+#define EGG_TRAY_ICON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_TRAY_ICON, EggTrayIcon))
+#define EGG_TRAY_ICON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_TRAY_ICON, EggTrayIconClass))
+#define EGG_IS_TRAY_ICON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_TRAY_ICON))
+#define EGG_IS_TRAY_ICON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_TRAY_ICON))
+#define EGG_TRAY_ICON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_TRAY_ICON, EggTrayIconClass))
+
+typedef struct _EggTrayIcon EggTrayIcon;
+typedef struct _EggTrayIconClass EggTrayIconClass;
+
+struct _EggTrayIcon
+{
+ GtkPlug parent_instance;
+
+ guint stamp;
+
+ Atom selection_atom;
+ Atom manager_atom;
+ Atom system_tray_opcode_atom;
+ Atom orientation_atom;
+ Window manager_window;
+
+ GtkOrientation orientation;
+};
+
+struct _EggTrayIconClass
+{
+ GtkPlugClass parent_class;
+};
+
+GType egg_tray_icon_get_type (void);
+
+EggTrayIcon *egg_tray_icon_new_for_screen (GdkScreen *screen,
+ const gchar *name);
+
+EggTrayIcon *egg_tray_icon_new (const gchar *name);
+
+guint egg_tray_icon_send_message (EggTrayIcon *icon,
+ gint timeout,
+ const char *message,
+ gint len);
+void egg_tray_icon_cancel_message (EggTrayIcon *icon,
+ guint id);
+
+GtkOrientation egg_tray_icon_get_orientation (EggTrayIcon *icon);
+
+G_END_DECLS
+
+#endif /* __EGG_TRAY_ICON_H__ */
--- /dev/null
+/*
+ *
+ * Bacula Gnome Tray Monitor
+ *
+ * Nicolas Boichat, August MMIV
+ *
+ * Version $Id$
+ */
+
+/*
+ Copyright (C) 2000-2004 Kern Sibbald and John Walker
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ */
+
+#include "bacula.h"
+#include "tray-monitor.h"
+
+#include "eggstatusicon.h"
+#include <gtk/gtk.h>
+
+#include "idle.xpm"
+#include "error.xpm"
+#include "running.xpm"
+#include "saving.xpm"
+#include "warn.xpm"
+
+/* Imported functions */
+int authenticate_file_daemon(JCR *jcr, MONITOR *monitor, CLIENT* client);
+
+/* Forward referenced functions */
+static void terminate_console(int sig);
+void writecmd(const char* command);
+
+/* Static variables */
+static char *configfile = NULL;
+static BSOCK *FD_sock = NULL;
+static MONITOR *monitor;
+static POOLMEM *args;
+
+/* UI variables and functions */
+gboolean fd_read(gpointer data);
+
+static EggStatusIcon* mTrayIcon;
+
+#define CONFIG_FILE "./tray-monitor.conf" /* default configuration file */
+
+static void usage()
+{
+ fprintf(stderr, _(
+"Copyright (C) 2000-2004 Kern Sibbald and John Walker\n"
+"\nVersion: " VERSION " (" BDATE ") %s %s %s\n\n"
+"Usage: tray-monitor [-s] [-c config_file] [-d debug_level]\n"
+" -c <file> set configuration file to file\n"
+" -dnn set debug level to nn\n"
+" -s no signals\n"
+" -t test - read configuration and exit\n"
+" -? print this message.\n"
+"\n"), HOST_OS, DISTNAME, DISTVER);
+}
+
+/*********************************************************************
+ *
+ * Main Bacula Tray Monitor -- User Interface Program
+ *
+ */
+int main(int argc, char *argv[])
+{
+ int ch, nfiled;
+ bool test_config = false;
+ JCR jcr;
+ CLIENT* filed;
+
+ init_stack_dump();
+ my_name_is(argc, argv, "tray-monitor");
+ textdomain("bacula");
+ init_msg(NULL, NULL);
+ working_directory = "/tmp";
+ args = get_pool_memory(PM_FNAME);
+
+ while ((ch = getopt(argc, argv, "bc:d:r:st?")) != -1) {
+ switch (ch) {
+ case 'c': /* configuration file */
+ if (configfile != NULL) {
+ free(configfile);
+ }
+ configfile = bstrdup(optarg);
+ break;
+
+ case 'd':
+ debug_level = atoi(optarg);
+ if (debug_level <= 0) {
+ debug_level = 1;
+ }
+ break;
+
+ case 't':
+ test_config = true;
+ break;
+
+ case '?':
+ default:
+ usage();
+ exit(1);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc) {
+ usage();
+ exit(1);
+ }
+
+ if (configfile == NULL) {
+ configfile = bstrdup(CONFIG_FILE);
+ }
+
+ parse_config(configfile);
+
+ LockRes();
+ nfiled = 0;
+ foreach_res(filed, R_CLIENT) {
+ nfiled++;
+ }
+ UnlockRes();
+ if (nfiled != 1) {
+ Emsg1(M_ERROR_TERM, 0, _("No Client resource defined in %s (or more than one)\n\
+Without that I don't how to get status from the Client :-(\n"), configfile);
+ }
+
+ if (test_config) {
+ terminate_console(0);
+ exit(0);
+ }
+
+ LockRes();
+ filed = (CLIENT*)GetNextRes(R_CLIENT, NULL);
+ UnlockRes();
+
+ memset(&jcr, 0, sizeof(jcr));
+
+ (void)WSA_Init(); /* Initialize Windows sockets */
+
+ printf(_("Connecting to Client %s:%d\n"), filed->address, filed->FDport);
+ FD_sock = bnet_connect(NULL, 5, 15, "File daemon", filed->address,
+ NULL, filed->FDport, 0);
+ if (FD_sock == NULL) {
+ terminate_console(0);
+ return 1;
+ }
+ jcr.file_bsock = FD_sock;
+
+ LockRes();
+ monitor = (MONITOR*)GetNextRes(R_MONITOR, (RES *)NULL);
+ UnlockRes();
+
+ if (!authenticate_file_daemon(&jcr, monitor, filed)) {
+ fprintf(stderr, "ERR=%s", FD_sock->msg);
+ terminate_console(0);
+ return 1;
+ }
+
+ printf("Opened connection with File daemon\n");
+
+ writecmd("status");
+
+ gtk_init (&argc, &argv);
+
+ GdkPixbuf* pixbuf = gdk_pixbuf_new_from_xpm_data(xpm_idle);
+ // This should be ideally replaced by a completely libpr0n-based icon rendering.
+ mTrayIcon = egg_status_icon_new_from_pixbuf(pixbuf);
+/* g_signal_connect(G_OBJECT(mTrayIcon), "activate", G_CALLBACK(TrayIconActivate), this);
+ g_signal_connect(G_OBJECT(mTrayIcon), "popup-menu", G_CALLBACK(TrayIconPopupMenu), this);*/
+ g_object_unref(G_OBJECT(pixbuf));
+
+ gtk_idle_add( fd_read, NULL );
+
+ gtk_main();
+
+ if (FD_sock) {
+ bnet_sig(FD_sock, BNET_TERMINATE); /* send EOF */
+ bnet_close(FD_sock);
+ }
+
+ terminate_console(0);
+ return 0;
+}
+
+gboolean fd_read(gpointer data) {
+ int stat;
+
+ while(1) {
+ if ((stat = bnet_recv(FD_sock)) >= 0) {
+ printf(FD_sock->msg);
+ }
+ else if (stat == BNET_SIGNAL) {
+ if (FD_sock->msglen == BNET_PROMPT) {
+ printf("<PROMPT>");
+ }
+ else if (FD_sock->msglen == BNET_EOD) {
+ printf("<END>");
+ writecmd("status");
+ sleep(1);
+ return 1;
+ }
+ else if (FD_sock->msglen == BNET_HEARTBEAT) {
+ bnet_sig(FD_sock, BNET_HB_RESPONSE);
+ printf("<< Heartbeat signal received, answered. >>");
+ }
+ else {
+ printf("<< Unexpected signal received : %s >>", bnet_sig_to_ascii(FD_sock));
+ }
+ }
+ else { /* BNET_HARDEOF || BNET_ERROR */
+ printf("<ERROR>");
+ break;
+ }
+
+ if (is_bnet_stop(FD_sock)) {
+ printf("<STOP>");
+ break; /* error or term */
+ }
+ }
+ return 0;
+}
+
+/* Cleanup and then exit */
+static void terminate_console(int sig)
+{
+
+ static bool already_here = false;
+
+ if (already_here) { /* avoid recursive temination problems */
+ exit(1);
+ }
+ already_here = true;
+ free_pool_memory(args);
+ (void)WSACleanup(); /* Cleanup Windows sockets */
+ if (sig != 0) {
+ exit(1);
+ }
+ return;
+}
+
+void writecmd(const char* command) {
+ FD_sock->msglen = strlen(command);
+ pm_strcpy(&FD_sock->msg, command);
+ bnet_send(FD_sock);
+}
--- /dev/null
+#
+# Bacula Tray Monitor Configuration File
+#
+
+Monitor {
+ Name = @hostname@-dir
+}
+
+Client {
+ Name = @hostname@-fd
+ Address = @hostname@
+ FDPort = @fd_port@
+ Password = "@fd_password@" # password for FileDaemon
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Includes specific to the Director
+ *
+ * Kern Sibbald, December MM
+ *
+ * Version $Id$
+ */
+/*
+ Copyright (C) 2000-2004 Kern Sibbald and John Walker
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ This program 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ */
+
+#include "tray_conf.h"
+
+#define TRAY_MONITOR 1
+
+#include "jcr.h"
--- /dev/null
+/*
+* Main configuration file parser for Bacula Tray Monitor.
+*
+* Adapted from dird_conf.c
+*
+* Note, the configuration file parser consists of three parts
+*
+* 1. The generic lexical scanner in lib/lex.c and lib/lex.h
+*
+* 2. The generic config scanner in lib/parse_config.c and
+* lib/parse_config.h.
+* These files contain the parser code, some utility
+* routines, and the common store routines (name, int,
+* string).
+*
+* 3. The daemon specific file, which contains the Resource
+* definitions as well as any specific store routines
+* for the resource records.
+*
+* Nicolas Boichat, August MMIV
+*
+* Version $Id$
+*/
+/*
+ Copyright (C) 2000-2004 Kern Sibbald and John Walker
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ This program 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+*/
+
+#include "bacula.h"
+#include "tray_conf.h"
+
+/* Define the first and last resource ID record
+* types. Note, these should be unique for each
+* daemon though not a requirement.
+*/
+int r_first = R_FIRST;
+int r_last = R_LAST;
+static RES *sres_head[R_LAST - R_FIRST + 1];
+RES **res_head = sres_head;
+
+/* We build the current resource here as we are
+* scanning the resource configuration definition,
+* then move it to allocated memory when the resource
+* scan is complete.
+*/
+URES res_all;
+int res_all_size = sizeof(res_all);
+
+
+/* Definition of records permitted within each
+* resource with the routine to process the record
+* information. NOTE! quoted names must be in lower case.
+*/
+/*
+* Monitor Resource
+*
+* name handler value code flags default_value
+*/
+static RES_ITEM dir_items[] = {
+ {"name", store_name, ITEM(res_monitor.hdr.name), 0, ITEM_REQUIRED, 0},
+ {"description", store_str, ITEM(res_monitor.hdr.desc), 0, 0, 0},
+ {"requiressl", store_yesno, ITEM(res_monitor.require_ssl), 1, ITEM_DEFAULT, 0},
+ {"fdconnecttimeout", store_time,ITEM(res_monitor.FDConnectTimeout), 0, ITEM_DEFAULT, 60 * 30},
+ {"sdconnecttimeout", store_time,ITEM(res_monitor.SDConnectTimeout), 0, ITEM_DEFAULT, 60 * 30},
+ {NULL, NULL, NULL, 0, 0, 0}
+};
+
+/*
+* Client or File daemon resource
+*
+* name handler value code flags default_value
+*/
+
+static RES_ITEM cli_items[] = {
+ {"name", store_name, ITEM(res_client.hdr.name), 0, ITEM_REQUIRED, 0},
+ {"description", store_str, ITEM(res_client.hdr.desc), 0, 0, 0},
+ {"address", store_str, ITEM(res_client.address), 0, ITEM_REQUIRED, 0},
+ {"fdaddress", store_str, ITEM(res_client.address), 0, 0, 0},
+ {"fdport", store_pint, ITEM(res_client.FDport), 0, ITEM_DEFAULT, 9102},
+ {"password", store_password, ITEM(res_client.password), 0, ITEM_REQUIRED, 0},
+ {"fdpassword", store_password, ITEM(res_client.password), 0, 0, 0},
+ {"enablessl", store_yesno, ITEM(res_client.enable_ssl), 1, ITEM_DEFAULT, 0},
+ {NULL, NULL, NULL, 0, 0, 0}
+};
+
+/* Storage daemon resource
+*
+* name handler value code flags default_value
+*/
+static RES_ITEM store_items[] = {
+ {"name", store_name, ITEM(res_store.hdr.name), 0, ITEM_REQUIRED, 0},
+ {"description", store_str, ITEM(res_store.hdr.desc), 0, 0, 0},
+ {"sdport", store_pint, ITEM(res_store.SDport), 0, ITEM_DEFAULT, 9103},
+ {"address", store_str, ITEM(res_store.address), 0, ITEM_REQUIRED, 0},
+ {"sdaddress", store_str, ITEM(res_store.address), 0, 0, 0},
+ {"password", store_password, ITEM(res_store.password), 0, ITEM_REQUIRED, 0},
+ {"sdpassword", store_password, ITEM(res_store.password), 0, 0, 0},
+ {"enablessl", store_yesno, ITEM(res_store.enable_ssl), 1, ITEM_DEFAULT, 0},
+ {NULL, NULL, NULL, 0, 0, 0}
+};
+
+/*
+* This is the master resource definition.
+* It must have one item for each of the resources.
+*
+* NOTE!!! keep it in the same order as the R_codes
+* or eliminate all resources[rindex].name
+*
+* name items rcode res_head
+*/
+RES_TABLE resources[] = {
+ {"monitor", dir_items, R_MONITOR},
+ {"client", cli_items, R_CLIENT},
+ {"storage", store_items, R_STORAGE},
+ {NULL, NULL, 0}
+};
+
+/* Dump contents of resource */
+void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fmt, ...), void *sock)
+{
+ URES *res = (URES *)reshdr;
+ bool recurse = true;
+ char ed1[100], ed2[100];
+
+ if (res == NULL) {
+ sendit(sock, "No %s resource defined\n", res_to_str(type));
+ return;
+ }
+ if (type < 0) { /* no recursion */
+ type = - type;
+ recurse = false;
+ }
+ switch (type) {
+ case R_MONITOR:
+ sendit(sock, "Director: name=%s FDtimeout=%s SDtimeout=%s\n",
+ reshdr->name,
+ edit_uint64(res->res_monitor.FDConnectTimeout, ed1),
+ edit_uint64(res->res_monitor.SDConnectTimeout, ed2));
+ break;
+ case R_CLIENT:
+ sendit(sock, "Client: name=%s address=%s FDport=%d\n",
+ res->res_client.hdr.name, res->res_client.address, res->res_client.FDport);
+ break;
+ case R_STORAGE:
+ sendit(sock, "Storage: name=%s address=%s SDport=%d\n",
+ res->res_store.hdr.name, res->res_store.address, res->res_store.SDport);
+ break;
+ default:
+ sendit(sock, "Unknown resource type %d in dump_resource.\n", type);
+ break;
+ }
+ if (recurse && res->res_monitor.hdr.next) {
+ dump_resource(type, res->res_monitor.hdr.next, sendit, sock);
+ }
+}
+
+
+/*
+* Free memory of resource -- called when daemon terminates.
+* NB, we don't need to worry about freeing any references
+* to other resources as they will be freed when that
+* resource chain is traversed. Mainly we worry about freeing
+* allocated strings (names).
+*/
+void free_resource(RES *sres, int type)
+{
+ int num;
+ RES *nres; /* next resource if linked */
+ URES *res = (URES *)sres;
+
+ if (res == NULL)
+ return;
+
+ /* common stuff -- free the resource name and description */
+ nres = (RES *)res->res_monitor.hdr.next;
+ if (res->res_monitor.hdr.name) {
+ free(res->res_monitor.hdr.name);
+ }
+ if (res->res_monitor.hdr.desc) {
+ free(res->res_monitor.hdr.desc);
+ }
+
+ switch (type) {
+ case R_MONITOR:
+ break;
+ case R_CLIENT:
+ if (res->res_client.address) {
+ free(res->res_client.address);
+ }
+ if (res->res_client.password) {
+ free(res->res_client.password);
+ }
+ break;
+ case R_STORAGE:
+ if (res->res_store.address) {
+ free(res->res_store.address);
+ }
+ if (res->res_store.password) {
+ free(res->res_store.password);
+ }
+ break;
+ default:
+ printf("Unknown resource type %d in free_resource.\n", type);
+ }
+ /* Common stuff again -- free the resource, recurse to next one */
+ if (res) {
+ free(res);
+ }
+ if (nres) {
+ free_resource(nres, type);
+ }
+}
+
+/*
+* Save the new resource by chaining it into the head list for
+* the resource. If this is pass 2, we update any resource
+* pointers because they may not have been defined until
+* later in pass 1.
+*/
+void save_resource(int type, RES_ITEM *items, int pass)
+{
+ URES *res;
+ int rindex = type - r_first;
+ int i, size;
+ int error = 0;
+
+ /*
+ * Ensure that all required items are present
+ */
+ for (i=0; items[i].name; i++) {
+ if (items[i].flags & ITEM_REQUIRED) {
+ if (!bit_is_set(i, res_all.res_monitor.hdr.item_present)) {
+ Emsg2(M_ERROR_TERM, 0, "%s item is required in %s resource, but not found.\n",
+ items[i].name, resources[rindex]);
+ }
+ }
+ /* If this triggers, take a look at lib/parse_conf.h */
+ if (i >= MAX_RES_ITEMS) {
+ Emsg1(M_ERROR_TERM, 0, "Too many items in %s resource\n", resources[rindex]);
+ }
+ }
+
+ /*
+ * During pass 2 in each "store" routine, we looked up pointers
+ * to all the resources referrenced in the current resource, now we
+ * must copy their addresses from the static record to the allocated
+ * record.
+ */
+ if (pass == 2) {
+ switch (type) {
+ /* Resources not containing a resource */
+ case R_MONITOR:
+ case R_CLIENT:
+ case R_STORAGE:
+ break;
+ default:
+ Emsg1(M_ERROR, 0, "Unknown resource type %d in save_resource.\n", type);
+ error = 1;
+ break;
+ }
+ /* Note, the resource name was already saved during pass 1,
+ * so here, we can just release it.
+ */
+ if (res_all.res_monitor.hdr.name) {
+ free(res_all.res_monitor.hdr.name);
+ res_all.res_monitor.hdr.name = NULL;
+ }
+ if (res_all.res_monitor.hdr.desc) {
+ free(res_all.res_monitor.hdr.desc);
+ res_all.res_monitor.hdr.desc = NULL;
+ }
+ return;
+ }
+
+ /*
+ * The following code is only executed during pass 1
+ */
+ switch (type) {
+ case R_MONITOR:
+ size = sizeof(MONITOR);
+ break;
+ case R_CLIENT:
+ size =sizeof(CLIENT);
+ break;
+ case R_STORAGE:
+ size = sizeof(STORE);
+ break;
+ default:
+ printf("Unknown resource type %d in save_resrouce.\n", type);
+ error = 1;
+ size = 1;
+ break;
+ }
+ /* Common */
+ if (!error) {
+ res = (URES *)malloc(size);
+ memcpy(res, &res_all, size);
+ if (!res_head[rindex]) {
+ res_head[rindex] = (RES *)res; /* store first entry */
+ Dmsg3(900, "Inserting first %s res: %s index=%d\n", res_to_str(type),
+ res->res_monitor.hdr.name, rindex);
+ } else {
+ RES *next;
+ /* Add new res to end of chain */
+ for (next=res_head[rindex]; next->next; next=next->next) {
+ if (strcmp(next->name, res->res_monitor.hdr.name) == 0) {
+ Emsg2(M_ERROR_TERM, 0,
+ _("Attempt to define second %s resource named \"%s\" is not permitted.\n"),
+ resources[rindex].name, res->res_monitor.hdr.name);
+ }
+ }
+ next->next = (RES *)res;
+ Dmsg4(900, "Inserting %s res: %s index=%d pass=%d\n", res_to_str(type),
+ res->res_monitor.hdr.name, rindex, pass);
+ }
+ }
+}
--- /dev/null
+/*
+ * Tray Monitor specific configuration and defines
+ *
+ * Adapted from dird_conf.c
+ *
+ * Nicolas Boichat, August MMIV
+ *
+ * Version $Id$
+ */
+/*
+ Copyright (C) 2000-2004 Kern Sibbald and John Walker
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+
+ This program 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
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with this program; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ */
+
+/* NOTE: #includes at the end of this file */
+
+/*
+ * Resource codes -- they must be sequential for indexing
+ */
+enum {
+ R_MONITOR = 1001,
+ R_CLIENT,
+ R_STORAGE,
+ R_FIRST = R_MONITOR,
+ R_LAST = R_STORAGE /* keep this updated */
+};
+
+
+/*
+ * Some resource attributes
+ */
+enum {
+ R_NAME = 1020,
+ R_ADDRESS,
+ R_PASSWORD,
+ R_TYPE,
+ R_BACKUP
+};
+
+/*
+ * Tray Monitor Resource
+ *
+ */
+struct MONITOR {
+ RES hdr;
+ int require_ssl; /* Require SSL for all connections */
+ MSGS *messages; /* Daemon message handler */
+ utime_t FDConnectTimeout; /* timeout for connect in seconds */
+ utime_t SDConnectTimeout; /* timeout in seconds */
+};
+
+
+/*
+ * Client Resource
+ *
+ */
+struct CLIENT {
+ RES hdr;
+
+ int FDport; /* Where File daemon listens */
+ char *address;
+ char *password;
+ int enable_ssl; /* Use SSL */
+};
+
+/*
+ * Store Resource
+ *
+ */
+struct STORE {
+ RES hdr;
+
+ int SDport; /* port where Directors connect */
+ char *address;
+ char *password;
+ int enable_ssl; /* Use SSL */
+};
+
+
+
+/* Define the Union of all the above
+ * resource structure definitions.
+ */
+union URES {
+ MONITOR res_monitor;
+ CLIENT res_client;
+ STORE res_store;
+ RES hdr;
+};
+