SOURCES: gnome-bluetooth-obex.patch (NEW) - patch from http://bugz...
wolvverine
wolvverine at pld-linux.org
Mon Apr 3 05:49:01 CEST 2006
Author: wolvverine Date: Mon Apr 3 03:49:01 2006 GMT
Module: SOURCES Tag: HEAD
---- Log message:
- patch from http://bugzilla.gnome.org/show_bug.cgi?id=330894
---- Files affected:
SOURCES:
gnome-bluetooth-obex.patch (NONE -> 1.1) (NEW)
---- Diffs:
================================================================
Index: SOURCES/gnome-bluetooth-obex.patch
diff -u /dev/null SOURCES/gnome-bluetooth-obex.patch:1.1
--- /dev/null Mon Apr 3 05:49:01 2006
+++ SOURCES/gnome-bluetooth-obex.patch Mon Apr 3 05:48:56 2006
@@ -0,0 +1,1176 @@
+diff -ur gnome-bluetooth-cvs/obex/chooser.c gnome-bluetooth-changed/obex/chooser.c
+--- gnome-bluetooth-cvs/obex/chooser.c 2004-06-04 22:29:04.000000000 +0300
++++ gnome-bluetooth-changed/obex/chooser.c 2005-11-22 00:20:23.000000000 +0200
+@@ -25,9 +25,10 @@
+ #include "chooser.h"
+
+ gchar *
+-choose_bdaddr ()
++choose_bd (gchar **name)
+ {
+ gchar *ret = NULL;
++ GnomebtDeviceDesc *btDevice;
+ GnomebtController *btctl;
+ GnomebtChooser *btchooser;
+ gint result;
+@@ -37,7 +38,11 @@
+ result = gtk_dialog_run (GTK_DIALOG (btchooser));
+
+ if (result == GTK_RESPONSE_OK)
+- ret = gnomebt_chooser_get_bdaddr (btchooser);
++ {
++ btDevice = gnomebt_chooser_get_bd (btchooser);
++ ret = g_strdup(btDevice->bdaddr);
++ *name = g_strdup(btDevice->name);
++ }
+
+ gtk_widget_destroy (GTK_WIDGET (btchooser));
+
+diff -ur gnome-bluetooth-cvs/obex/chooser.h gnome-bluetooth-changed/obex/chooser.h
+--- gnome-bluetooth-cvs/obex/chooser.h 2003-10-30 23:56:51.000000000 +0200
++++ gnome-bluetooth-changed/obex/chooser.h 2005-11-21 23:58:42.000000000 +0200
+@@ -1,4 +1,5 @@
+ #ifndef __CHOOSER_H
+ #define __CHOOSER_H
+-gchar *choose_bdaddr (void);
++
++gchar *choose_bd (gchar **name);
+ #endif
+diff -ur gnome-bluetooth-cvs/obex/gnome-obex-send.c gnome-bluetooth-changed/obex/gnome-obex-send.c
+--- gnome-bluetooth-cvs/obex/gnome-obex-send.c 2005-11-23 02:57:11.000000000 +0200
++++ gnome-bluetooth-changed/obex/gnome-obex-send.c 2006-02-10 14:16:41.000000000 +0200
+@@ -1,6 +1,7 @@
+ /*
+ * gnome-obex-send
+- * Copyright (c) 2003-4 Edd Dumbill <edd at usefulinc.com>.
++ * Copyright (c) 2003-4 Edd Dumbill <edd at usefulinc.com>
++ * Copyright (c) 2006 Tadas Dailyda <tadas at stablebeast.com>
+ *
+ * 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
+@@ -26,6 +27,8 @@
+ #include <string.h>
+ #include <fcntl.h>
+ #include <stdlib.h>
++#include <sys/time.h>
++#include <errno.h>
+
+ #include <glib.h>
+ #include <gtk/gtk.h>
+@@ -41,85 +44,163 @@
+
+ typedef struct _appinfo {
+ GladeXML *xml;
+- poptContext context;
++ GtkWidget *main_dialog;
++ GnomebtController *btmanager;
+ BtctlObexClient *obex;
+- GnomeProgram *prog;
+ gchar *data;
+- gchar *error;
++ gsize fileLength;
+ } MyApp;
+
++typedef enum {
++ BUTTONS_OK,
++ BUTTONS_RETRY_CANCEL,
++ BUTTONS_RETRY_SKIP_CANCEL
++} ButtonSet;
++
++static MyApp *app = NULL;
++static gchar **filesToSend = NULL;
++static guint currentFile = 0;
++static struct stat fileStat;
++static guint totalBytes = 0;
++static guint bytesSent = 0;
++static guint totalFiles = 0;
++static gint64 firstTransferTime = 0;
++static gint64 lastUpdateTime = 0;
++static gchar *bdaddrstr = NULL;
++static gchar *bdname = NULL;
++static gchar *temp_error_text = NULL;
++
++#define DIALOG_RESPONSE_SKIP 1
++#define DIALOG_RESPONSE_RETRY 2
+ #define GLADE_FILE DATA_DIR "/gnome-obex-send.glade"
+ #define ICON_FILE ICON_DIR "/blueradio-48.png"
+
+-static void mainloop (MyApp *app);
+-static uint8_t get_obex_channel (const gchar *bdaddr);
+-static gboolean send_one (MyApp *app);
+-
+-static gchar *bdaddrstr = NULL;
++static void mainloop ();
++static uint8_t get_obex_channel (GnomebtController *btmanager, const gchar *bdaddr, GError **err);
++static gboolean send_one ();
++static void establish_connection ();
++
++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, &filesToSend},
++ {NULL}
++ };
+
+-static const struct poptOption options[] = {
+- {"dest", 'd', POPT_ARG_STRING, &bdaddrstr,
+-/* FIXME: find way of doing this:
+- * 0, _("Bluetooth address of destination device"), "BDADDR"}, */
+- 0, "Bluetooth address of destination device", "BDADDR"},
+- {NULL, '\0', 0, NULL, 0}
+-};
+
+ static uint8_t
+-get_obex_channel (const gchar *bdaddr)
++get_obex_channel (GnomebtController *btmanager, const gchar *bdaddr, GError **err)
+ {
+- GnomebtController *btmanager;
+ GSList *list, *item;
+ uint8_t ret=0;
+
+- btmanager = gnomebt_controller_new ();
+-
+- if (! btmanager) {
+- g_warning ("gnomebt_controller_new() failed");
+- return -1;
+- }
+-
+ list = gnomebt_controller_channels_for_service (btmanager,
+ (const gchar *) bdaddr,
+- OBEX_OBJPUSH_SVCLASS_ID);
++ OBEX_OBJPUSH_SVCLASS_ID, err);
++ if (*err) {
++ g_warning("gnomebt_controller_channels_for_service() failed: %s (%s)",
++ (*err)->message, errno ? g_strerror(errno): "");
++ return ret;
++ }
+
+ for (item=list; item != NULL; item = g_slist_next(item)) {
+ ret = GPOINTER_TO_UINT(item->data);
+ }
++
++ return ret;
++}
+
+- g_object_unref (btmanager);
++static gint64
++get_system_time (void)
++{
++ struct timeval tmp;
+
+- return ret;
++ gettimeofday (&tmp, NULL);
++ return (gint64)tmp.tv_usec + (gint64)tmp.tv_sec * G_GINT64_CONSTANT (1000000);
+ }
+
+ static void
+-update_gui (MyApp *app)
++update_gui ()
+ {
+ GladeXML *xml=app->xml;
+ GtkWidget *bar;
+- gdouble frac = btctl_obex_client_progress (app->obex);
++ gdouble frac;
++ guint actualBytesSent;
++ gint elapsed_time;
++ gint transfer_rate;
++ gint time_remaining;
++ gint64 current_time;
++ gchar *str, *str2;
++ gchar *progressbar_text;
++
+ bar = glade_xml_get_widget (xml, "progressbar1");
++ /* update progress bar fraction */
++ frac = btctl_obex_client_progress (app->obex);
++ actualBytesSent = bytesSent + app->fileLength * frac;
++ frac = (gdouble)actualBytesSent / totalBytes;
+ gtk_progress_bar_set_fraction( GTK_PROGRESS_BAR (bar), frac);
+-}
++ /* update progress bar text (time remaining)
++ * (only update once in a second) */
++ current_time = get_system_time();
++ elapsed_time = (current_time - firstTransferTime) / 1000000;
++ if (lastUpdateTime != 0) {
++ if (current_time < lastUpdateTime + 1000000)
++ return;
++ else
++ lastUpdateTime = current_time;
++ } else {
++ lastUpdateTime = current_time;
++ }
++ if (elapsed_time == 0) {
++ return;
++ }
++ transfer_rate = actualBytesSent / elapsed_time;
++ if (transfer_rate == 0) {
++ return;
++ }
++ time_remaining = (totalBytes - actualBytesSent) / 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);
+
+-static gboolean
+-is_palm_device (const char *bdaddr)
+-{
+- 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"));
++ }
++ else {
++ str = g_strdup_printf (_("(%d:%02d Remaining)"),
++ time_remaining / 60, time_remaining % 60);
++ }
++
++ str2 = g_strdup_printf(_("Sending file: %d of %d"), currentFile+1, totalFiles);
++ progressbar_text = g_strconcat(str2, " ", str, NULL);
++ gtk_progress_bar_set_text(GTK_PROGRESS_BAR(bar), progressbar_text);
++ g_free(str);
++ g_free(str2);
++ g_free(progressbar_text);
+ }
+
+-static void
+-report_error (const gchar *msg) {
++static gint
++show_error_dialog (GtkWindow *parent, ButtonSet buttons, const gchar *primary_text, const gchar *secondary_text)
++{
+ GtkWidget *dialog;
+-
+- dialog = gnome_error_dialog (msg);
+- gtk_signal_connect_object (GTK_OBJECT (dialog),
+- "close", GTK_SIGNAL_FUNC (gtk_main_quit),
+- (gpointer) dialog);
+-
+- gtk_main ();
++ 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));
++
++ gtk_widget_destroy(dialog);
++ g_free(primary_text_markup);
++ return ret;
+ }
+
+ static void
+@@ -131,54 +212,115 @@
+ static void
+ progress_callback (BtctlObexClient *bo, gchar * bdaddr, gpointer data)
+ {
+- update_gui ((MyApp *)data);
++ update_gui ();
+ }
+
+ static void
+ complete_callback (BtctlObexClient *bo, gchar * bdaddr, gpointer data)
+ {
+- MyApp *app = (MyApp *)data;
+-
+ if (app->data) {
+ g_free (app->data);
+ app->data = NULL;
+ }
++
++ currentFile++;
++ bytesSent += app->fileLength;
+
+- g_idle_add ((GSourceFunc) send_one, data);
++ g_idle_add ((GSourceFunc) send_one, NULL);
++}
++
++static void
++handle_file_sending_error (const gchar *error_text, const gchar *error_secondary_text)
++{
++ ButtonSet buttons;
++ int response_id;
++
++ if (totalFiles > 1 && currentFile < totalFiles-1)
++ buttons = BUTTONS_RETRY_SKIP_CANCEL;
++ else
++ buttons = BUTTONS_RETRY_CANCEL;
++ gdk_threads_enter();
++ response_id = show_error_dialog(GTK_WINDOW(app->main_dialog), buttons,
++ error_text, error_secondary_text);
++ gdk_threads_leave();
++ switch (response_id) {
++ case DIALOG_RESPONSE_SKIP:
++ currentFile++;
++ bytesSent += app->fileLength;
++ case DIALOG_RESPONSE_RETRY:
++ if (temp_error_text) {
++ /* error happened during transfer */
++ temp_error_text = NULL;
++ firstTransferTime = 0;
++ g_object_unref(app->obex);
++ /* the connection might be lost, need to reestablish it */
++ if (!g_thread_create((GThreadFunc)establish_connection, NULL, FALSE, NULL)) {
++ g_warning("Failed to create thread. Continuing synchroniously.");
++ establish_connection();
++ }
++ }
++ else {
++ /* continue sending */
++ g_idle_add ((GSourceFunc) send_one, NULL);
++ }
++ break;
++ case GTK_RESPONSE_CANCEL:
++ default:
++ gtk_main_quit ();
++ break;
++ }
+ }
+
+ static gboolean
+-send_one (MyApp *app)
++send_one ()
+ {
+ const gchar *fname;
+- gchar *bname;
+- gsize len;
++ gchar *bname, *dirname;
+ GError *err = NULL;
+- GtkWidget *label;
+-
+- if ((fname = poptGetArg (app->context))) {
++ GtkWidget *from_label, *operation_label, *bar;
++ gchar *operation_text, *operation_markup, *progressbar_text;
++
++ if (fname = *(filesToSend+currentFile)) {
+ /* there's a file to send */
+ app->data = NULL;
+- if (g_file_get_contents (fname, &(app->data), &len, &err)) {
++ if (g_file_get_contents (fname, &(app->data), &(app->fileLength), &err)) {
++ /* file read successfully, send it */
++ if (firstTransferTime == 0) {
++ firstTransferTime = get_system_time();
++ }
+ bname = g_path_get_basename (fname);
+- label = glade_xml_get_widget (app->xml, "filename_label");
+- gtk_label_set_text (GTK_LABEL (label), bname);
+- btctl_obex_client_push_data (app->obex,
+- bname, app->data, len);
+- /* TODO: check error return here from command submit */
++ dirname = g_path_get_dirname (fname);
++
++ from_label = glade_xml_get_widget (app->xml, "from_label");
++ operation_label = glade_xml_get_widget (app->xml, "operation_label");
++ bar = glade_xml_get_widget (app->xml, "progressbar1");
++
++ 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"), currentFile+1, totalFiles);
++ 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(bar), progressbar_text);
++
++ if (!btctl_obex_client_push_data (app->obex, bname, app->data, app->fileLength)) {
++ /* obex error */
++ handle_file_sending_error(g_strdup_printf(_("Could not send file '%s'"), fname), "");
++ }
++
+ g_free (bname);
++ g_free (dirname);
++ g_free (operation_text);
++ g_free (operation_markup);
++ g_free (progressbar_text);
+ } else {
+- app->error = g_strdup_printf (_("Unable to read file '%s'."), fname);
+- /* TODO: implement error handling */
++ /* error while reading file */
++ handle_file_sending_error(_("Unable to read file"), err->message);
+ g_error_free (err);
+- /* error, so we quit */
+- gtk_main_quit ();
+ }
+ } else {
+ /* nothing left to send, time to quit */
+ gtk_main_quit ();
+ }
+-
+ return FALSE;
+ }
+
+@@ -186,101 +328,214 @@
+ connected_callback (BtctlObexClient *bo, gchar * bdaddr, gpointer data)
+ {
+ /* OBEX connect has succeeded, so start sending */
+- g_idle_add ((GSourceFunc) send_one, data);
++ g_idle_add ((GSourceFunc) send_one, NULL);
++}
++
++static gboolean
++error_callback_helper ()
++{
++ handle_file_sending_error (g_strdup_printf(_("An error occured while sending file '%s'"), *(filesToSend+currentFile)),
++ temp_error_text);
++ return FALSE;
+ }
+
+ static void
+ error_callback (BtctlObexClient *bo, gchar * bdaddr, guint reason,
+ gpointer data)
+ {
+- MyApp *app = (MyApp *) data;
+-
+- switch (reason) {
+- case BTCTL_OBEX_ERR_LINK:
+- case BTCTL_OBEX_ERR_PARSE:
+- app->error = g_strdup (_("An error occurred while sending data."));
+- break;
+- case BTCTL_OBEX_ERR_ABORT:
+- app->error = g_strdup (_("The remote device canceled the transfer."));
+- break;
+- default:
+- app->error = g_strdup (_("An unknown error occurred."));
++ if (app->data) {
++ g_free (app->data);
++ app->data = NULL;
+ }
+- /* Error condition, so quit. */
+- gtk_main_quit ();
++
++ if (reason == BTCTL_OBEX_ERR_ABORT)
++ temp_error_text = _("The remote device canceled the transfer.");
++ else if (reason == BTCTL_OBEX_ERR_LINK)
++ temp_error_text = _("Connection to remote device was lost.");
++
++ g_idle_add ((GSourceFunc) error_callback_helper, NULL);
+ }
+
+ static void
+-mainloop (MyApp *app)
++establish_connection ()
+ {
+- GtkWidget *dialog, *label, *button;
+-
++ uint8_t channel;
++ gint response_id;
++ GError *err=NULL;
++
++ /* try to connect */
++ channel = get_obex_channel (app->btmanager, bdaddrstr, &err);
++ if (channel) {
++ app->obex = BTCTL_OBEX_CLIENT (
++ btctl_obex_client_new_and_connect (bdaddrstr, channel));
++ if (!btctl_obex_client_is_initialised (app->obex)) {
++ /* it means remote device bluetooth subsystem is busy or has hanged
++ * so we say that remote device doesn't support receiving objects */
++ channel = 0;
++ }
++ }
++
++ /* handle errors */
++ if (!channel) {
++ gdk_threads_enter();
++ if (err) {
++ response_id = show_error_dialog(GTK_WINDOW(app->main_dialog), BUTTONS_RETRY_CANCEL,
++ err->message,
++ _("Make sure that remote device is on and that it accepts bluetooth connections."));
++ g_error_free (err);
++ } else {
++ response_id = show_error_dialog(GTK_WINDOW(app->main_dialog), BUTTONS_RETRY_CANCEL,
++ _("Remote device can not receive files"),
++ _("Make sure that remote device is not busy with another bluetooth connection."));
++ }
++ gdk_threads_leave();
++ if (response_id == DIALOG_RESPONSE_RETRY) {
++ /* try reconnecting */
++
++ if (!g_thread_create((GThreadFunc)establish_connection, NULL, FALSE, NULL)) {
++ g_warning("Failed to create thread. Continuing synchroniously.");
++ establish_connection();
++ }
++ return;
++ }
++
++ gtk_main_quit();
++ return;
++ }
++
++ /* connect signals */
+ g_signal_connect (G_OBJECT (app->obex), "progress",
+- G_CALLBACK (progress_callback), (gpointer) app);
++ G_CALLBACK (progress_callback), NULL);
+ g_signal_connect (G_OBJECT (app->obex), "complete",
+- G_CALLBACK (complete_callback), (gpointer) app);
++ G_CALLBACK (complete_callback), NULL);
+ g_signal_connect (G_OBJECT (app->obex), "connected",
+- G_CALLBACK (connected_callback), (gpointer) app);
++ G_CALLBACK (connected_callback), NULL);
+ g_signal_connect (G_OBJECT (app->obex), "error",
+- G_CALLBACK (error_callback), (gpointer) app);
++ G_CALLBACK (error_callback), NULL);
++}
++
++static void
++mainloop ()
++{
++ GtkWidget *label1, *label2, *label3, *target_label, *progressbar, *button;
++ gchar *text;
+
+- dialog = glade_xml_get_widget (app->xml, "send_dialog");
++ /* initialize UI */
++ app->main_dialog = glade_xml_get_widget (app->xml, "send_dialog");
+
+- gtk_widget_show_all (dialog);
++ gtk_widget_show_all (app->main_dialog);
+
+- label = glade_xml_get_widget (app->xml, "filename_label");
++ label1 = glade_xml_get_widget (app->xml, "label1");
++ label2 = glade_xml_get_widget (app->xml, "label2");
++ label3 = glade_xml_get_widget (app->xml, "label3");
++ target_label = glade_xml_get_widget (app->xml, "target_label");
++ progressbar = glade_xml_get_widget(app->xml, "progressbar1");
+ button = glade_xml_get_widget (app->xml, "cancelbutton");
+
+ g_signal_connect (G_OBJECT (button), "clicked",
+ G_CALLBACK (cancel_clicked),
+ (gpointer) app);
+
+- gtk_label_set_text (GTK_LABEL (label), _("Connecting..."));
++ 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);
++ text = g_markup_printf_escaped ("<b>%s</b>", _("From:"));
++ gtk_label_set_markup (GTK_LABEL (label2), text);
++ g_free (text);
++ text = g_markup_printf_escaped ("<b>%s</b>", _("To:"));
++ gtk_label_set_markup (GTK_LABEL (label3), text);
++ g_free (text);
++ gtk_progress_bar_set_text (GTK_PROGRESS_BAR (progressbar), _("Connecting..."));
++ text = g_strdup_printf("%s (%s)", bdname, bdaddrstr);
++ gtk_label_set_text (GTK_LABEL (target_label), text);
++ g_free (text);
++
++ /* begin connecting in separate thread */
++ gdk_threads_init();
++ if (!g_thread_create((GThreadFunc)establish_connection, NULL, FALSE, NULL)) {
++ g_warning("Failed to create thread. Continuing synchroniously.");
++ establish_connection();
++ }
+
+ gtk_main ();
+
+- gtk_widget_hide (dialog);
++ gtk_widget_hide (app->main_dialog);
++}
++
++static void
++free_mem ()
++{
++ if (filesToSend)
++ g_strfreev (filesToSend);
++ if (bdaddrstr)
++ g_free (bdaddrstr);
++ if (bdname)
++ g_free (bdname);
++ if (app) {
++ if (app->data)
++ g_free (app->data);
++ if (app->obex)
++ g_object_unref (app->obex);
++ if (app->btmanager)
++ g_object_unref (app->btmanager);
++ g_free (app);
++ }
+ }
+
+ int
<<Diff was trimmed, longer than 597 lines>>
More information about the pld-cvs-commit
mailing list