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