From: Bastien Nocera <hadess@hadess.net>
To: BlueZ development <bluez-devel@lists.sourceforge.net>
Subject: Re: [Bluez-devel] [PATCH] Updated sendto
Date: Wed, 27 Feb 2008 01:28:02 +0000 [thread overview]
Message-ID: <1204075682.2754.245.camel@cookie.hadess.net> (raw)
In-Reply-To: <1E808724-F721-415C-90F9-09C1B6E52C55@holtmann.org>
[-- Attachment #1: Type: text/plain, Size: 522 bytes --]
On Tue, 2008-02-26 at 02:21 +0100, Marcel Holtmann wrote:
<snip>
> lets use gtk_main_quit() since the exit code doesn't really matter and
> show me an updated patch. I am still working through the whole thing.
> We need some simplifications here and there, because the code looks
> too complicated to me.
There's some bits of the code that aren't as easy to read as they could,
but it's hard to take a step back when you've used to the code.
Let me know which parts you don't like and we can rework them.
Cheers
[-- Attachment #2: bluez-gnome-new-sendto-10.patch --]
[-- Type: text/x-patch, Size: 30100 bytes --]
Index: sendto/dialog.h
===================================================================
RCS file: /cvsroot/bluez/gnome/sendto/dialog.h,v
retrieving revision 1.1
diff -u -p -r1.1 dialog.h
--- sendto/dialog.h 23 Feb 2008 06:20:17 -0000 1.1
+++ sendto/dialog.h 27 Feb 2008 01:25:10 -0000
@@ -21,5 +21,7 @@
*
*/
+#include <glib.h>
+
gchar *show_browse_dialog(void);
GSList *show_select_dialog(void);
Index: sendto/main.c
===================================================================
RCS file: /cvsroot/bluez/gnome/sendto/main.c,v
retrieving revision 1.24
diff -u -p -r1.24 main.c
--- sendto/main.c 23 Feb 2008 06:20:17 -0000 1.24
+++ sendto/main.c 27 Feb 2008 01:25:10 -0000
@@ -3,6 +3,8 @@
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2005-2008 Marcel Holtmann <marcel@holtmann.org>
+ * Copyright (C) 2006-2007 Tadas Dailyda <tadas@dailyda.com>
+ * Copyright (C) 2007 Bastien Nocera <hadess@hadess.net>
*
*
* This program is free software; you can redistribute it and/or modify
@@ -25,199 +27,618 @@
#include <config.h>
#endif
-#include <dbus/dbus-glib.h>
#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#include <dbus/dbus-glib.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
#include <gtk/gtk.h>
+#include "dbus-glue.h"
#include "marshal.h"
-
#include "dialog.h"
-static DBusGConnection *conn = NULL;
+#define MSEC_PER_SEC 1000000
-static GtkWidget *dialog;
-static GtkWidget *label_filename;
-static GtkWidget *label_status;
-static GtkWidget *progress;
-
-static guint64 filesize = 0;
+/* DBus */
+static DBusGConnection *connection = NULL;
+static DBusGProxy *manager_proxy = NULL;
+static DBusGProxy *session_proxy = NULL;
+/* GTK */
+static GtkWidget *main_dialog, *from_label, *operation_label, *progress_bar;
+/* sending related */
+static gsize file_length = 0;
+static guint file_count = 0;
+static guint current_file = 0;
+static GSList *file_list = NULL;
+static guint byte_count = 0;
+static guint bytes_sent = 0;
+static gint64 first_transfer_time = 0;
+static gint64 last_update_time = 0;
+
+typedef enum {
+ BUTTONS_OK,
+ BUTTONS_RETRY_CANCEL,
+ BUTTONS_RETRY_SKIP_CANCEL
+} ButtonSet;
+
+/* Command line options */
+static gchar **files_to_send = NULL;
+static gchar *bdaddrstr = NULL;
+static gchar *device_name = NULL;
+
+#define DIALOG_RESPONSE_SKIP 1
+#define DIALOG_RESPONSE_RETRY 2
+
+static void error_occurred_cb(DBusGProxy *proxy, const gchar *error_name,
+ const gchar *error_message, gpointer user_data);
+
+static const GOptionEntry options[] = {
+ {"dest", 'd', 0, G_OPTION_ARG_STRING, &bdaddrstr,
+ "Bluetooth address of destination device", "BDADDR"},
+ {G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &files_to_send},
+ {NULL}
+};
-static void response_callback(GtkWidget *dialog,
- gint response, gpointer user_data)
+static gint64 get_system_time(void)
{
- gtk_widget_destroy(dialog);
+ struct timeval tmp;
- gtk_main_quit();
+ gettimeofday(&tmp, NULL);
+ return (gint64)tmp.tv_usec + (gint64)tmp.tv_sec * G_GINT64_CONSTANT(1000000);
}
-static void create_window(const gchar *filename)
+static gboolean is_palm_device(const gchar *bdaddr)
{
- GtkWidget *vbox;
- GtkWidget *label;
- gchar *text;
+ return (g_str_has_prefix(bdaddr, "00:04:6B")
+ || g_str_has_prefix(bdaddr, "00:07:E0")
+ || g_str_has_prefix(bdaddr, "00:0E:20"));
+}
- dialog = gtk_dialog_new_with_buttons(_("File Transfer"), NULL,
- GTK_DIALOG_NO_SEPARATOR,
- GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL);
+/* Return the local absolute filename for the file, and its size
+ * if the file exists and is stat()'able */
+static gchar *normalise_filename(const gchar *filename, gint64 *size)
+{
+ char *ret;
+ struct stat file_stat;
- gtk_window_set_default_size(GTK_WINDOW(dialog), 400, -1);
+ g_return_val_if_fail(filename != NULL, NULL);
+ g_return_val_if_fail(size != NULL, NULL);
- gtk_container_set_border_width(GTK_CONTAINER(dialog), 6);
+ if (g_str_has_prefix(filename, "file://")) {
+ ret = g_filename_from_uri(filename, NULL, NULL);
+ if (ret == NULL)
+ return NULL;
+ } else if (filename[0] == '/') {
+ ret = g_strdup(filename);
+ } else {
+ gchar *curdir;
+
+ curdir = g_get_current_dir();
+ ret = g_build_filename(curdir, filename, NULL);
+ g_free(curdir);
+ }
- vbox = gtk_vbox_new(FALSE, 6);
- gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
- gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), vbox);
+ if (!g_file_test(ret, G_FILE_TEST_IS_REGULAR)) {
+ g_free(ret);
+ return NULL;
+ }
- label = gtk_label_new(NULL);
- gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
- gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
+ if (!g_stat(ret, &file_stat)) {
+ *size = file_stat.st_size;
+ } else {
+ g_free(ret);
+ return NULL;
+ }
- label_filename = label;
+ return ret;
+}
- progress = gtk_progress_bar_new();
- gtk_box_pack_start(GTK_BOX(vbox), progress, FALSE, FALSE, 0);
+static gchar *get_device_name(void)
+{
+ DBusGConnection *connection;
+ DBusGProxy *manager;
+ GError *error = NULL;
+ gchar *name, **adapters;
+ guint i;
- label = gtk_label_new(NULL);
- gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
- gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
- gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 6);
+ name = NULL;
- label_status = label;
+ connection = dbus_g_bus_get(DBUS_BUS_SYSTEM, NULL);
+ if (connection == NULL)
+ return NULL;
+
+ manager = dbus_g_proxy_new_for_name(connection, "org.bluez",
+ "/org/bluez", "org.bluez.Manager");
+ if (!manager) {
+ dbus_g_connection_unref(connection);
+ return NULL;
+ }
- text = g_strdup_printf("<b>%s</b>", filename);
- gtk_label_set_markup(GTK_LABEL(label_filename), text);
- g_free(text);
+ if (!manager_list_adapters(manager, &adapters, &error)) {
+ g_object_unref(manager);
+ dbus_g_connection_unref(connection);
+ return NULL;
+ }
- gtk_label_set_markup(GTK_LABEL(label_status), _("Connecting..."));
+ for (i = 0; adapters[i] != NULL; i++) {
+ DBusGProxy *adapter;
- gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog),
- GTK_RESPONSE_CLOSE, FALSE);
+ adapter = dbus_g_proxy_new_for_name(connection, "org.bluez",
+ adapters[i], "org.bluez.Adapter");
+ if (dbus_g_proxy_call(adapter, "GetRemoteName", NULL,
+ G_TYPE_STRING, bdaddrstr, G_TYPE_INVALID,
+ G_TYPE_STRING, &name, G_TYPE_INVALID)) {
+ if (name != NULL && name[0] != '\0') {
+ g_object_unref(adapter);
+ break;
+ }
+ }
+ g_object_unref(adapter);
+ }
- g_signal_connect(G_OBJECT(dialog), "response",
- G_CALLBACK(response_callback), NULL);
+ g_strfreev(adapters);
+ g_object_unref(manager);
+ dbus_g_connection_unref(connection);
- gtk_widget_show_all(dialog);
+ return name;
}
-static void transfer_started(DBusGProxy *proxy, gchar *a, gchar *b,
- guint64 size, gpointer user_data)
+static gint show_error_dialog(GtkWindow *parent, ButtonSet buttons,
+ const gchar *primary_text, const gchar *secondary_text)
{
- gchar *text;
+ GtkWidget *dialog;
+ gchar *primary_text_markup;
+ gint ret;
+
+ primary_text_markup = g_strdup_printf("<span weight=\"bold\" size=\"larger\">%s</span>",
+ primary_text);
+ dialog = gtk_message_dialog_new_with_markup(parent, 0, GTK_MESSAGE_ERROR,
+ buttons==BUTTONS_OK? GTK_BUTTONS_OK: GTK_BUTTONS_CANCEL,
+ primary_text_markup);
+ gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
+ secondary_text);
+ if (buttons == BUTTONS_RETRY_SKIP_CANCEL) {
+ gtk_dialog_add_button(GTK_DIALOG(dialog), _("Skip"),
+ DIALOG_RESPONSE_SKIP);
+ }
+ if (buttons != BUTTONS_OK) {
+ gtk_dialog_add_button(GTK_DIALOG(dialog), _("Retry"),
+ DIALOG_RESPONSE_RETRY);
+ }
+ ret = gtk_dialog_run(GTK_DIALOG(dialog));
- filesize = size;
+ gtk_widget_destroy(dialog);
+ g_free(primary_text_markup);
+ return ret;
+}
- text = g_strdup_printf(_("Starting transfer of %jd bytes"), size);
- gtk_label_set_markup(GTK_LABEL(label_status), text);
- g_free(text);
+static gint show_connection_error_dialog(GtkWindow *parent, const gchar *bdaddr,
+ const gchar *primary_text)
+{
+ if (!is_palm_device(bdaddrstr)) {
+ return show_error_dialog(parent,
+ BUTTONS_RETRY_CANCEL,
+ primary_text,
+ _("Make sure that remote device is on and that it accepts Bluetooth connections."));
+ } else {
+ return show_error_dialog(parent,
+ BUTTONS_RETRY_CANCEL,
+ primary_text,
+ _("Make sure \"Beam receive\" is enabled in the Power preferences, and Bluetooth is enabled, on your Palm device."));
+ }
+}
+
+static gint handle_file_sending_error(const gchar *error_text,
+ const gchar *error_secondary_text)
+{
+ ButtonSet buttons;
+ gint response_id;
- gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), 0.0);
+ if (file_count > 1 && current_file < file_count - 1)
+ buttons = BUTTONS_RETRY_SKIP_CANCEL;
+ else
+ buttons = BUTTONS_RETRY_CANCEL;
+
+ response_id = show_error_dialog(GTK_WINDOW(main_dialog), buttons,
+ error_text, error_secondary_text);
+
+ switch (response_id) {
+ case DIALOG_RESPONSE_SKIP:
+ current_file++;
+ bytes_sent += file_length;
+ case DIALOG_RESPONSE_RETRY:
+ return TRUE;
+ case GTK_RESPONSE_CANCEL:
+ default:
+ gtk_main_quit();
+ break;
+ }
+ return response_id;
}
-static void transfer_progress(DBusGProxy *proxy,
- guint64 bytes, gpointer user_data)
+static void cancel_clicked_cb(GtkWidget *button, gpointer user_data)
{
+ gtk_main_quit();
+}
+
+static void ui_init(void)
+{
+ GtkWidget *vbox, *vbox_parent, *table;
+ GtkWidget *label1, *label2, *label3, *target_label;
+ GtkWidget *button;
gchar *text;
- gdouble fraction;
- text = g_strdup_printf(_("Transfered %jd of %jd bytes"),
- bytes, filesize);
- gtk_label_set_markup(GTK_LABEL(label_status), text);
+ device_name = get_device_name();
+
+ /* main dialog */
+ main_dialog = gtk_dialog_new();
+ gtk_dialog_set_has_separator(GTK_DIALOG(main_dialog), FALSE);
+ gtk_window_set_title(GTK_WINDOW(main_dialog),
+ _("Bluetooth file transfer"));
+ gtk_window_set_icon_name(GTK_WINDOW(main_dialog), "stock_bluetooth");
+ gtk_window_set_type_hint(GTK_WINDOW(main_dialog),
+ GDK_WINDOW_TYPE_HINT_NORMAL);
+ gtk_window_set_position(GTK_WINDOW(main_dialog), GTK_WIN_POS_CENTER);
+ gtk_window_set_resizable(GTK_WINDOW(main_dialog), FALSE);
+ gtk_widget_set(main_dialog, "width-request", 400, NULL);
+ button = gtk_dialog_add_button(GTK_DIALOG(main_dialog),
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL);
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(cancel_clicked_cb), NULL);
+ gtk_container_set_border_width(GTK_CONTAINER(main_dialog), 6);
+
+ /* table elements */
+ from_label = gtk_label_new(NULL);
+ gtk_misc_set_alignment(GTK_MISC(from_label), 0, 0.5);
+ gtk_label_set_ellipsize(GTK_LABEL(from_label), PANGO_ELLIPSIZE_MIDDLE);
+ target_label = gtk_label_new(NULL);
+ gtk_misc_set_alignment(GTK_MISC(target_label), 0, 0.5);
+ gtk_label_set_ellipsize(GTK_LABEL(target_label), PANGO_ELLIPSIZE_END);
+ gtk_label_set_text(GTK_LABEL(target_label), device_name ? device_name : bdaddrstr);
+ label2 = gtk_label_new(NULL);
+ text = g_markup_printf_escaped("<b>%s</b>", _("From:"));
+ gtk_label_set_markup(GTK_LABEL(label2), text);
+ g_free(text);
+ label3 = gtk_label_new(NULL);
+ gtk_misc_set_alignment(GTK_MISC(label3), 1, 0.5);
+ text = g_markup_printf_escaped("<b>%s</b>", _("To:"));
+ gtk_label_set_markup(GTK_LABEL(label3), text);
g_free(text);
- fraction = (gdouble) bytes / (gdouble) filesize;
- gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), fraction);
+ /* table */
+ table = gtk_table_new(2, 2, FALSE);
+ gtk_table_set_col_spacings(GTK_TABLE(table), 4);
+ gtk_table_set_row_spacings(GTK_TABLE(table), 4);
+ gtk_table_attach_defaults(GTK_TABLE(table), from_label, 1, 2, 0, 1);
+ gtk_table_attach_defaults(GTK_TABLE(table), target_label, 1, 2, 1, 2);
+ gtk_table_attach(GTK_TABLE(table), label2, 0, 1, 0, 1, GTK_FILL, 0, 0, 0);
+ gtk_table_attach(GTK_TABLE(table), label3, 0, 1, 1, 2, GTK_FILL, 0, 0, 0);
+
+ /* vbox elements */
+ label1 = gtk_label_new(NULL);
+ gtk_misc_set_alignment(GTK_MISC(label1), 0, 0.5);
+ text = g_markup_printf_escaped("<span weight=\"bold\" size=\"larger\">%s</span>",
+ _("Sending files via bluetooth"));
+ gtk_label_set_markup(GTK_LABEL(label1), text);
+ g_free(text);
+ progress_bar = gtk_progress_bar_new();
+ gtk_progress_bar_set_ellipsize(GTK_PROGRESS_BAR(progress_bar),
+ PANGO_ELLIPSIZE_END);
+ gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress_bar),
+ _("Connecting..."));
+ operation_label = gtk_label_new(NULL);
+ gtk_misc_set_alignment(GTK_MISC(operation_label), 0, 0.5);
+ gtk_label_set_ellipsize(GTK_LABEL(operation_label), PANGO_ELLIPSIZE_END);
+
+ /* vbox */
+ vbox = gtk_vbox_new(FALSE, 0);
+ gtk_box_set_spacing(GTK_BOX(vbox), 6);
+ gtk_container_set_border_width(GTK_CONTAINER(vbox), 6);
+ gtk_box_pack_start_defaults(GTK_BOX(vbox), label1);
+ gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 9);
+ gtk_box_pack_start_defaults(GTK_BOX(vbox), progress_bar);
+ gtk_box_pack_start(GTK_BOX(vbox), operation_label, TRUE, TRUE, 2);
+ vbox_parent = gtk_bin_get_child(GTK_BIN(main_dialog));
+ gtk_box_pack_start_defaults(GTK_BOX(vbox_parent), vbox);
+
+ gtk_widget_show_all(main_dialog);
}
-static void transfer_completed(DBusGProxy *proxy, gpointer user_data)
+static gboolean send_one(gpointer user_data)
{
- gtk_label_set_markup(GTK_LABEL(label_status), _("Completed"));
+ const gchar *fname;
+ gint ret;
+ gchar *bname, *dirname;
+ GError *err = NULL;
+ gchar *operation_text, *operation_markup, *progressbar_text;
+
+ if ((fname = g_slist_nth_data(file_list, current_file))) {
+ /* there's a file to send */
+ dbus_g_proxy_call(session_proxy, "SendFile", &err,
+ G_TYPE_STRING, fname, G_TYPE_INVALID, G_TYPE_INVALID);
+
+ if (err != NULL) {
+ ret = handle_file_sending_error(_("Unable to read file"),
+ err->message);
+ if (ret != GTK_RESPONSE_CANCEL) {
+ g_idle_add((GSourceFunc) send_one, NULL);
+ }
+ g_error_free(err);
+ return FALSE;
+ }
- gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), 1.0);
+ if (!first_transfer_time) {
+ first_transfer_time = get_system_time();
+ }
+ bname = g_path_get_basename(fname);
+ dirname = g_path_get_dirname(fname);
- dbus_g_proxy_call(proxy, "Disconnect", NULL, G_TYPE_INVALID,
- G_TYPE_INVALID);
+ operation_text = g_strdup_printf(_("Sending %s"), bname);
+ operation_markup = g_markup_printf_escaped("<i>%s</i>", operation_text);
+ progressbar_text = g_strdup_printf(_("Sending file: %d of %d"),
+ current_file+1,
+ file_count);
+ gtk_label_set_text(GTK_LABEL(from_label), dirname);
+ gtk_label_set_markup(GTK_LABEL(operation_label), operation_markup);
+ gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress_bar),
+ progressbar_text);
+
+ g_free(bname);
+ g_free(dirname);
+ g_free(operation_text);
+ g_free(operation_markup);
+ g_free(progressbar_text);
+ } else {
+ /* nothing left to send, time to quit */
+ gtk_main_quit();
+ }
+ return FALSE;
+}
- gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog),
- GTK_RESPONSE_CLOSE, TRUE);
+static void session_connected_cb(DBusGProxy *proxy, gpointer user_data)
+{
+ /* OBEX connect has succeeded, so start sending */
+ g_idle_add((GSourceFunc) send_one, NULL);
}
-static void session_connected(DBusGProxy *proxy, gpointer user_data)
+static void transfer_started_cb(DBusGProxy *proxy, const gchar *filename,
+ const gchar *local_path, guint64 byte_count, gpointer user_data)
{
- gchar *filename = user_data;
- GError *error = NULL;
+ file_length = byte_count;
+}
- gtk_label_set_markup(GTK_LABEL(label_status), _("Connected"));
+static void transfer_cancelled_cb(DBusGProxy *proxy, gpointer user_data)
+{
+ gint ret;
+ gchar *error_text;
- dbus_g_proxy_call(proxy, "SendFile", &error,
- G_TYPE_STRING, filename, G_TYPE_INVALID,
- G_TYPE_INVALID);
-
- if (error != NULL) {
- g_printerr("Sending of file %s failed: %s\n", filename,
- error->message);
- g_error_free(error);
- gtk_main_quit();
+ error_text = g_strdup_printf(_("An error occured while sending file '%s'"),
+ (gchar *)g_slist_nth_data(file_list, current_file));
+ ret = handle_file_sending_error(error_text,
+ _("The remote device cancelled the transfer"));
+
+ if (ret != GTK_RESPONSE_CANCEL)
+ g_idle_add((GSourceFunc) send_one, NULL);
+
+ g_free(error_text);
+}
+
+static void transfer_progress_cb(DBusGProxy *proxy, guint64 bytes_transferred, gpointer user_data)
+{
+ gdouble frac;
+ guint actual_bytes_sent;
+ gint elapsed_time;
+ gint transfer_rate;
+ gint time_remaining;
+ gint64 current_time;
+ gchar *str, *str2;
+ gchar *progressbar_text;
+
+ /* update progress bar fraction */
+ actual_bytes_sent = bytes_sent + bytes_transferred;
+ frac = (gdouble)actual_bytes_sent / byte_count;
+ gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress_bar), frac);
+
+ /* update progress bar text (time remaining)
+ * (only update 4 times in a second) */
+ current_time = get_system_time();
+ elapsed_time = (current_time - first_transfer_time) / MSEC_PER_SEC;
+
+ if (last_update_time) {
+ if (current_time < last_update_time + MSEC_PER_SEC / 4)
+ return;
+ else
+ last_update_time = current_time;
+ } else {
+ last_update_time = current_time;
}
+
+ if (!elapsed_time)
+ return;
+
+ transfer_rate = actual_bytes_sent / elapsed_time;
+ if (transfer_rate == 0)
+ return;
+
+ time_remaining = (byte_count - actual_bytes_sent) / transfer_rate;
+
+ if (time_remaining >= 3600) {
+ str = g_strdup_printf(_("(%d:%02d:%d Remaining)"),
+ time_remaining / 3600,
+ (time_remaining % 3600) / 60,
+ (time_remaining % 3600) % 60);
+ } else {
+ str = g_strdup_printf(_("(%d:%02d Remaining)"),
+ time_remaining / 60,
+ time_remaining % 60);
+ }
+
+ /* Translators:
+ * Sending file 1 of 3 */
+ str2 = g_strdup_printf(_("Sending file %d of %d"),
+ current_file + 1,
+ file_count);
+ progressbar_text = g_strconcat(str2, " ", str, NULL);
+ gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress_bar),
+ progressbar_text);
+ g_free(str);
+ g_free(str2);
+ g_free(progressbar_text);
}
-static void create_notify(DBusGProxy *proxy,
- DBusGProxyCall *call, void *user_data)
+static void transfer_completed_cb(DBusGProxy *proxy, gpointer user_data)
+{
+ current_file++;
+ bytes_sent += file_length;
+
+ g_idle_add((GSourceFunc) send_one, NULL);
+}
+
+static void session_created_cb(DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
{
GError *error = NULL;
const gchar *path = NULL;
- if (dbus_g_proxy_end_call(proxy, call, &error,
- DBUS_TYPE_G_OBJECT_PATH, &path,
- G_TYPE_INVALID) == FALSE) {
- gchar *text, *message;
-
- if (error != NULL) {
- message = g_strdup(error->message);
- g_error_free(error);
- } else
- message = g_strdup(_("An unknown error occured"));
-
- text = g_strdup_printf("<span foreground=\"red\">%s</span>",
- message);
- gtk_label_set_markup(GTK_LABEL(label_status), text);
- g_free(text);
-
- g_free(message);
+ if (!dbus_g_proxy_end_call(proxy, call, &error,
+ DBUS_TYPE_G_OBJECT_PATH, &path, G_TYPE_INVALID)) {
+ const gchar *error_name = NULL;
+ gint response_id;
+
+ if (error && error->code == DBUS_GERROR_REMOTE_EXCEPTION)
+ error_name = dbus_g_error_get_name(error);
+ if (error_name && !strcmp(error_name, "org.openobex.Error.ConnectionAttemptFailed")) {
+ response_id = show_connection_error_dialog(GTK_WINDOW(main_dialog), bdaddrstr, error->message);
+ if (response_id == DIALOG_RESPONSE_RETRY) {
+ /* Try to create Session again */
+ dbus_g_proxy_begin_call(manager_proxy,
+ "CreateBluetoothSession",
+ (DBusGProxyCallNotify) session_created_cb, NULL, NULL,
+ G_TYPE_STRING, bdaddrstr, G_TYPE_STRING, "opp",
+ G_TYPE_BOOLEAN, FALSE, G_TYPE_INVALID);
+ goto out;
+ }
+ } else {
+ show_error_dialog(GTK_WINDOW(main_dialog), BUTTONS_OK,
+ error->message, "");
+ }
- gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog),
- GTK_RESPONSE_CLOSE, TRUE);
- return;
+ gtk_main_quit();
+ goto out;
}
- proxy = dbus_g_proxy_new_for_name(conn, "org.openobex",
- path, "org.openobex.Session");
+ session_proxy = dbus_g_proxy_new_for_name(connection,
+ "org.openobex",
+ path,
+ "org.openobex.Session");
- dbus_g_proxy_add_signal(proxy, "Connected", G_TYPE_INVALID);
+ dbus_g_proxy_add_signal(session_proxy, "Connected",
+ G_TYPE_INVALID);
+
+ dbus_g_proxy_connect_signal(session_proxy, "Connected",
+ G_CALLBACK(session_connected_cb), NULL, NULL);
+
+ dbus_g_proxy_add_signal(session_proxy, "TransferStarted",
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT64, G_TYPE_INVALID);
+
+ dbus_g_proxy_connect_signal(session_proxy, "TransferStarted",
+ G_CALLBACK(transfer_started_cb), NULL, NULL);
- dbus_g_proxy_connect_signal(proxy, "Connected",
- G_CALLBACK(session_connected), user_data, NULL);
+ dbus_g_proxy_add_signal(session_proxy, "Cancelled",
+ G_TYPE_INVALID);
+
+ dbus_g_proxy_connect_signal(session_proxy, "Cancelled",
+ G_CALLBACK(transfer_cancelled_cb), NULL, NULL);
- dbus_g_proxy_add_signal(proxy, "TransferStarted", G_TYPE_STRING,
- G_TYPE_STRING, G_TYPE_UINT64, G_TYPE_INVALID);
+ dbus_g_proxy_add_signal(session_proxy, "ErrorOccurred",
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
- dbus_g_proxy_connect_signal(proxy, "TransferStarted",
- G_CALLBACK(transfer_started), NULL, NULL);
+ dbus_g_proxy_connect_signal(session_proxy, "ErrorOccurred",
+ G_CALLBACK(error_occurred_cb), NULL, NULL);
- dbus_g_proxy_add_signal(proxy, "TransferProgress",
- G_TYPE_UINT64, G_TYPE_INVALID);
+ dbus_g_proxy_add_signal(session_proxy, "TransferProgress",
+ G_TYPE_UINT64, G_TYPE_INVALID);
- dbus_g_proxy_connect_signal(proxy, "TransferProgress",
- G_CALLBACK(transfer_progress), NULL, NULL);
+ dbus_g_proxy_connect_signal(session_proxy, "TransferProgress",
+ G_CALLBACK(transfer_progress_cb), NULL, NULL);
+
+ dbus_g_proxy_add_signal(session_proxy, "TransferCompleted",
+ G_TYPE_INVALID);
- dbus_g_proxy_add_signal(proxy, "TransferCompleted", G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal(session_proxy, "TransferCompleted",
+ G_CALLBACK(transfer_completed_cb), NULL, NULL);
- dbus_g_proxy_connect_signal(proxy, "TransferCompleted",
- G_CALLBACK(transfer_completed), NULL, NULL);
+ dbus_g_proxy_call(session_proxy, "Connect", &error, G_TYPE_INVALID,
+ G_TYPE_INVALID);
- dbus_g_proxy_call(proxy, "Connect", NULL, G_TYPE_INVALID,
- G_TYPE_INVALID);
+out:
+ if (error)
+ g_error_free(error);
+}
+
+static void error_occurred_cb(DBusGProxy *proxy, const gchar *error_name, const gchar *error_message, gpointer user_data)
+{
+ gint ret;
+ gboolean link_error = FALSE;
+ gchar *error_text;
+ const gchar *reason;
+
+ g_message("ErrorOccurred");
+ g_message("Error name: %s", error_name);
+ g_message("Error message: %s", error_message);
+
+ error_text = g_strdup_printf(_("An error occured while sending file '%s'"),
+ (gchar *)g_slist_nth_data(file_list, current_file));
+ if (!strcmp(error_name, "org.openobex.Error.LinkError")) {
+ g_object_unref(G_OBJECT(session_proxy));
+ reason = _("Connection to remote device was lost");
+ link_error = TRUE;
+ } else if (!strcmp(error_name, "org.openobex.Error.Forbidden")) {
+ reason = _("Remote device rejected file");
+ } else {
+ reason = _("Unknown error");
+ }
+ ret = handle_file_sending_error(error_text, reason);
+
+ if (ret != GTK_RESPONSE_CANCEL) {
+ if (link_error) {
+ /* Need to reestablish connection */
+ dbus_g_proxy_begin_call(manager_proxy, "CreateBluetoothSession",
+ (DBusGProxyCallNotify) session_created_cb, NULL, NULL,
+ G_TYPE_STRING, bdaddrstr, G_TYPE_STRING, "opp",
+ G_TYPE_INVALID);
+ } else {
+ g_idle_add((GSourceFunc) send_one, NULL);
+ }
+ }
+
+
+ g_free(error_text);
+}
+
+static void free_mem(void)
+{
+ if (files_to_send)
+ g_strfreev(files_to_send);
+ g_free(bdaddrstr);
+
+ if (main_dialog)
+ gtk_widget_destroy (main_dialog);
+ if (G_IS_OBJECT(manager_proxy))
+ g_object_unref(G_OBJECT(manager_proxy));
+ if (G_IS_OBJECT(session_proxy))
+ g_object_unref (G_OBJECT(session_proxy));
+ g_slist_free(file_list);
}
static void name_owner_changed(DBusGProxy *proxy, const char *name,
@@ -227,102 +648,121 @@ static void name_owner_changed(DBusGProx
gtk_main_quit();
}
-static gchar *option_device = NULL;
-
-static GOptionEntry options[] = {
- { "device", 0, 0, G_OPTION_ARG_STRING, &option_device,
- N_("Remote device to use"), "ADDRESS" },
- { NULL },
-};
-
int main(int argc, char *argv[])
{
- DBusGProxy *proxy;
+ GOptionContext *option_context;
GError *error = NULL;
- GSList *filenames;
- gchar *filename, *address;
+ guint i;
bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
textdomain(GETTEXT_PACKAGE);
- error = NULL;
+ option_context = g_option_context_new("<file list>");
+ g_option_context_add_main_entries(option_context, options, GETTEXT_PACKAGE);
+ g_option_context_add_group(option_context, gtk_get_option_group(TRUE));
+ g_option_context_parse(option_context, &argc, &argv, &error);
+ g_option_context_free(option_context);
+ if (error) {
+ printf("Usage:\n");
+ printf(" %s [--dest=BDADDR] <file list>\n", g_get_prgname());
+ g_error_free(error);
+ free_mem();
+ return 0;
+ }
- if (gtk_init_with_args(&argc, &argv, "[FILE...]",
- options, GETTEXT_PACKAGE, &error) == FALSE) {
- if (error != NULL) {
- g_printerr("%s\n", error->message);
- g_error_free(error);
- } else
- g_printerr("An unknown error occurred\n");
-
- gtk_exit(1);
- }
-
- gtk_window_set_default_icon_name("bluetooth");
-
- if (argc < 2) {
- filenames = show_select_dialog();
- if (filenames == NULL)
- gtk_exit(1);
- } else
- filenames = g_slist_append(NULL, g_strdup(argv[1]));
-
- if (option_device == NULL) {
- address = show_browse_dialog();
- if (address == NULL) {
- g_slist_free(filenames);
- gtk_exit(1);
- }
- } else
- address = g_strdup(option_device);
+ gtk_init(&argc, &argv);
+
+ connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
+ if (!connection) {
+ show_error_dialog(NULL, GTK_BUTTONS_OK,
+ _("Please verify that D-Bus is correctly installed and setup."), error->message);
+ g_error_free(error);
+ return 1;
+ }
- conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
- if (conn == NULL) {
- if (error != NULL) {
- g_printerr("Connecting to session bus failed: %s\n",
- error->message);
- g_error_free(error);
- } else
- g_print("An unknown error occured\n");
+ main_dialog = NULL;
+ from_label = NULL;
+ operation_label = NULL;
+ progress_bar = NULL;
+
+ /* get a list of files to send from command-line */
+ if (files_to_send)
+ file_count = g_strv_length(files_to_send);
+ else
+ file_count = 0;
+ for (i = 0; i < file_count; i++) {
+ file_list = g_slist_append(file_list,
+ g_strdup(*(files_to_send + i)));
+ }
+ /* show file chooser if no files were specified */
+ if (!file_count) {
+ file_list = show_select_dialog();
+ file_count = g_slist_length(file_list);
+ }
+ /* Check if there are some files to send */
+ if (!file_count) {
+ free_mem();
+ return 0;
+ }
+ /* Check for non regular and non existand files and
+ * determine total bytes to send */
+ for (i = 0; i < file_count; i++) {
+ GSList *item;
+ gchar *path, *filename;
+ gint64 size;
+
+ item = g_slist_nth(file_list, i);
+ path = (gchar *) item->data;
+ filename = normalise_filename(path, &size);
+ if (filename == NULL) {
+ g_free(path);
+ file_list = g_slist_remove_link(file_list, item);
+ continue;
+ }
+ g_free(item->data);
+ item->data = filename;
+ byte_count += size;
+ }
- gtk_exit(1);
+ /* determine Bluetooth device to send to */
+ if (!bdaddrstr) {
+ bdaddrstr = show_browse_dialog();
+ if (!bdaddrstr) {
+ free_mem();
+ return 0;
+ }
}
dbus_g_object_register_marshaller(marshal_VOID__STRING_STRING_UINT64,
- G_TYPE_NONE, G_TYPE_STRING,
- G_TYPE_STRING, G_TYPE_UINT64, G_TYPE_INVALID);
-
+ G_TYPE_NONE, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_UINT64, G_TYPE_INVALID);
+ dbus_g_object_register_marshaller(marshal_VOID__STRING_STRING,
+ G_TYPE_NONE, G_TYPE_STRING,
+ G_TYPE_STRING, G_TYPE_INVALID);
dbus_g_object_register_marshaller(marshal_VOID__UINT64,
G_TYPE_NONE, G_TYPE_UINT64, G_TYPE_INVALID);
- filename = g_slist_nth_data(filenames, 0);
-
- create_window(filename);
+ ui_init();
- proxy = dbus_g_proxy_new_for_name(conn, "org.openobex",
- "/org/openobex", "org.openobex.Manager");
-
- dbus_g_proxy_add_signal(proxy, "NameOwnerChanged",
- G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
-
- dbus_g_proxy_connect_signal(proxy, "NameOwnerChanged",
- G_CALLBACK(name_owner_changed), NULL, NULL);
-
- dbus_g_proxy_begin_call(proxy, "CreateBluetoothSession",
- create_notify, filename, NULL,
- G_TYPE_STRING, address, G_TYPE_STRING, "opp",
+ manager_proxy = dbus_g_proxy_new_for_name(connection,
+ "org.openobex",
+ "/org/openobex",
+ "org.openobex.Manager");
+ dbus_g_proxy_add_signal(manager_proxy, "NameOwnerChanged",
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal(manager_proxy, "NameOwnerChanged",
+ G_CALLBACK(name_owner_changed), NULL, NULL);
+
+ dbus_g_proxy_begin_call(manager_proxy, "CreateBluetoothSession",
+ (DBusGProxyCallNotify) session_created_cb, NULL, NULL,
+ G_TYPE_STRING, bdaddrstr, G_TYPE_STRING, "opp",
G_TYPE_INVALID);
gtk_main();
- g_object_unref(proxy);
-
- dbus_g_connection_unref(conn);
-
- g_free(address);
-
- g_slist_free(filenames);
+ free_mem();
return 0;
}
+
[-- Attachment #3: Type: text/plain, Size: 228 bytes --]
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
[-- Attachment #4: Type: text/plain, Size: 164 bytes --]
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel
prev parent reply other threads:[~2008-02-27 1:28 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-01-17 10:43 [Bluez-devel] [PATCH] Allow multiple files to be sent Bastien Nocera
2008-01-18 13:43 ` Bastien Nocera
2008-02-01 13:14 ` Bastien Nocera
2008-02-01 16:08 ` Bastien Nocera
2008-02-01 16:20 ` Bastien Nocera
2008-02-06 12:18 ` [Bluez-devel] [PATCH] Updated sendto Bastien Nocera
2008-02-06 13:08 ` Bastien Nocera
2008-02-07 0:59 ` Bastien Nocera
2008-02-23 1:30 ` Bastien Nocera
2008-02-24 18:29 ` Bastien Nocera
2008-02-25 2:21 ` Marcel Holtmann
2008-02-25 10:56 ` Bastien Nocera
2008-02-25 20:36 ` Marcel Holtmann
2008-02-26 1:18 ` Bastien Nocera
2008-02-26 1:21 ` Marcel Holtmann
2008-02-27 1:28 ` Bastien Nocera [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1204075682.2754.245.camel@cookie.hadess.net \
--to=hadess@hadess.net \
--cc=bluez-devel@lists.sourceforge.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox