|
Packit |
8fb625 |
/*
|
|
Packit |
8fb625 |
*
|
|
Packit |
8fb625 |
* BlueZ - Bluetooth protocol stack for Linux
|
|
Packit |
8fb625 |
*
|
|
Packit |
8fb625 |
* Copyright (C) 2005-2008 Marcel Holtmann <marcel@holtmann.org>
|
|
Packit |
8fb625 |
* Copyright (C) 2013 Intel Corporation.
|
|
Packit |
8fb625 |
*
|
|
Packit |
8fb625 |
*
|
|
Packit |
8fb625 |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
8fb625 |
* it under the terms of the GNU General Public License as published by
|
|
Packit |
8fb625 |
* the Free Software Foundation; either version 2 of the License, or
|
|
Packit |
8fb625 |
* (at your option) any later version.
|
|
Packit |
8fb625 |
*
|
|
Packit |
8fb625 |
* This program is distributed in the hope that it will be useful,
|
|
Packit |
8fb625 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
8fb625 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
8fb625 |
* GNU General Public License for more details.
|
|
Packit |
8fb625 |
*
|
|
Packit |
8fb625 |
* You should have received a copy of the GNU General Public License
|
|
Packit |
8fb625 |
* along with this program; if not, write to the Free Software
|
|
Packit |
8fb625 |
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
Packit |
8fb625 |
*
|
|
Packit |
8fb625 |
*/
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
8fb625 |
#include <config.h>
|
|
Packit |
8fb625 |
#endif
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
#include <sys/time.h>
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
#include <glib/gi18n.h>
|
|
Packit |
8fb625 |
#include <glib/gstdio.h>
|
|
Packit |
8fb625 |
#include <gio/gio.h>
|
|
Packit |
8fb625 |
#include <gtk/gtk.h>
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
#include <bluetooth-client.h>
|
|
Packit |
8fb625 |
#include <bluetooth-chooser.h>
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
#define OBEX_SERVICE "org.bluez.obex"
|
|
Packit |
8fb625 |
#define OBEX_PATH "/org/bluez/obex"
|
|
Packit |
8fb625 |
#define TRANSFER_IFACE "org.bluez.obex.Transfer1"
|
|
Packit |
8fb625 |
#define OPP_IFACE "org.bluez.obex.ObjectPush1"
|
|
Packit |
8fb625 |
#define CLIENT_IFACE "org.bluez.obex.Client1"
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
#define RESPONSE_RETRY 1
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static GDBusConnection *conn = NULL;
|
|
Packit |
8fb625 |
static GDBusProxy *client_proxy = NULL;
|
|
Packit |
8fb625 |
static GDBusProxy *session = NULL;
|
|
Packit |
8fb625 |
static GDBusProxy *current_transfer = NULL;
|
|
Packit |
8fb625 |
static GCancellable *cancellable = NULL;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static GtkWidget *dialog;
|
|
Packit |
8fb625 |
static GtkWidget *label_from;
|
|
Packit |
8fb625 |
static GtkWidget *image_status;
|
|
Packit |
8fb625 |
static GtkWidget *label_status;
|
|
Packit |
8fb625 |
static GtkWidget *progress;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static gchar *option_device = NULL;
|
|
Packit |
8fb625 |
static gchar *option_device_name = NULL;
|
|
Packit |
8fb625 |
static gchar **option_files = NULL;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static guint64 current_size = 0;
|
|
Packit |
8fb625 |
static guint64 total_size = 0;
|
|
Packit |
8fb625 |
static guint64 total_sent = 0;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static int file_count = 0;
|
|
Packit |
8fb625 |
static int file_index = 0;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static gint64 first_update = 0;
|
|
Packit |
8fb625 |
static gint64 last_update = 0;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static void on_transfer_properties (GVariant *props);
|
|
Packit |
8fb625 |
static void on_transfer_progress (guint64 transferred);
|
|
Packit |
8fb625 |
static void on_transfer_complete (void);
|
|
Packit |
8fb625 |
static void on_transfer_error (void);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static gint64
|
|
Packit |
8fb625 |
get_system_time (void)
|
|
Packit |
8fb625 |
{
|
|
Packit |
8fb625 |
struct timeval tmp;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
gettimeofday(&tmp, NULL);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
return (gint64) tmp.tv_usec +
|
|
Packit |
8fb625 |
(gint64) tmp.tv_sec * G_GINT64_CONSTANT(1000000);
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static void
|
|
Packit |
8fb625 |
update_from_label (void)
|
|
Packit |
8fb625 |
{
|
|
Packit |
8fb625 |
char *filename = option_files[file_index];
|
|
Packit |
8fb625 |
GFile *file, *dir;
|
|
Packit |
8fb625 |
char *text, *markup;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
file = g_file_new_for_path (filename);
|
|
Packit |
8fb625 |
dir = g_file_get_parent (file);
|
|
Packit |
8fb625 |
g_object_unref (file);
|
|
Packit |
8fb625 |
if (g_file_has_uri_scheme (dir, "file") != FALSE) {
|
|
Packit |
8fb625 |
text = g_file_get_path (dir);
|
|
Packit |
8fb625 |
} else {
|
|
Packit |
8fb625 |
text = g_file_get_uri (dir);
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
markup = g_markup_escape_text (text, -1);
|
|
Packit |
8fb625 |
g_free (text);
|
|
Packit |
8fb625 |
g_object_unref (dir);
|
|
Packit |
8fb625 |
gtk_label_set_markup (GTK_LABEL (label_from), markup);
|
|
Packit |
8fb625 |
g_free (markup);
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static char *
|
|
Packit |
8fb625 |
cleanup_error (GError *error)
|
|
Packit |
8fb625 |
{
|
|
Packit |
8fb625 |
char *remote_error;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
if (!error || *error->message == '\0')
|
|
Packit |
8fb625 |
return g_strdup (_("An unknown error occurred"));
|
|
Packit |
8fb625 |
if (g_dbus_error_is_remote_error (error) == FALSE)
|
|
Packit |
8fb625 |
return g_strdup (error->message);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
remote_error = g_dbus_error_get_remote_error (error);
|
|
Packit |
8fb625 |
g_debug ("Remote error is: %s", remote_error);
|
|
Packit |
8fb625 |
g_free (remote_error);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
g_dbus_error_strip_remote_error (error);
|
|
Packit |
8fb625 |
g_debug ("Error message is: %s", error->message);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
/* And now, take advantage of the fact that obexd isn't translated */
|
|
Packit |
8fb625 |
if (g_strcmp0 (error->message, "Unable to find service record") == 0) {
|
|
Packit |
8fb625 |
return g_strdup (_("Make sure that the remote device is switched on and that it accepts Bluetooth connections"));
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
return g_strdup (error->message);
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static void
|
|
Packit |
8fb625 |
handle_error (GError *error)
|
|
Packit |
8fb625 |
{
|
|
Packit |
8fb625 |
char *message;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
message = cleanup_error (error);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
gtk_widget_show (image_status);
|
|
Packit |
8fb625 |
gtk_label_set_markup (GTK_LABEL (label_status), message);
|
|
Packit |
8fb625 |
g_clear_error (&error);
|
|
Packit |
8fb625 |
g_free (message);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
/* Clear the progress bar as it may be saying 'Connecting' or
|
|
Packit |
8fb625 |
* 'Sending file 1 of 1' which is not true. */
|
|
Packit |
8fb625 |
gtk_progress_bar_set_text (GTK_PROGRESS_BAR (progress), "");
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), RESPONSE_RETRY, TRUE);
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static void
|
|
Packit |
8fb625 |
transfer_properties_changed (GDBusProxy *proxy,
|
|
Packit |
8fb625 |
GVariant *changed_properties,
|
|
Packit |
8fb625 |
GStrv invalidated_properties,
|
|
Packit |
8fb625 |
gpointer user_data)
|
|
Packit |
8fb625 |
{
|
|
Packit |
8fb625 |
GVariantIter iter;
|
|
Packit |
8fb625 |
const char *key;
|
|
Packit |
8fb625 |
GVariant *value;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
g_variant_iter_init (&iter, changed_properties);
|
|
Packit |
8fb625 |
while (g_variant_iter_next (&iter, "{&sv}", &key, &value)) {
|
|
Packit |
8fb625 |
if (g_str_equal (key, "Status")) {
|
|
Packit |
8fb625 |
const char *status;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
status = g_variant_get_string (value, NULL);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
if (g_str_equal (status, "complete")) {
|
|
Packit |
8fb625 |
on_transfer_complete ();
|
|
Packit |
8fb625 |
} else if (g_str_equal (status, "error")) {
|
|
Packit |
8fb625 |
on_transfer_error ();
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
} else if (g_str_equal (key, "Transferred")) {
|
|
Packit |
8fb625 |
guint64 transferred = g_variant_get_uint64 (value);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
on_transfer_progress (transferred);
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
g_variant_unref (value);
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static void
|
|
Packit |
8fb625 |
transfer_proxy (GDBusProxy *proxy, GAsyncResult *res, gpointer user_data)
|
|
Packit |
8fb625 |
{
|
|
Packit |
8fb625 |
GError *error = NULL;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
current_transfer = g_dbus_proxy_new_finish (res, &error);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
if (current_transfer == NULL) {
|
|
Packit |
8fb625 |
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
|
Packit |
8fb625 |
g_error_free (error);
|
|
Packit |
8fb625 |
return;
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
handle_error (error);
|
|
Packit |
8fb625 |
return;
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
g_signal_connect (G_OBJECT (current_transfer), "g-properties-changed",
|
|
Packit |
8fb625 |
G_CALLBACK (transfer_properties_changed), NULL);
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static void
|
|
Packit |
8fb625 |
transfer_created (GDBusProxy *proxy, GAsyncResult *res, gpointer user_data)
|
|
Packit |
8fb625 |
{
|
|
Packit |
8fb625 |
GError *error = NULL;
|
|
Packit |
8fb625 |
GVariant *variant, *properties;
|
|
Packit |
8fb625 |
const char *transfer;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
variant = g_dbus_proxy_call_finish (proxy, res, &error);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
if (variant == NULL) {
|
|
Packit |
8fb625 |
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
|
Packit |
8fb625 |
g_error_free (error);
|
|
Packit |
8fb625 |
return;
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
handle_error (error);
|
|
Packit |
8fb625 |
return;
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
gtk_progress_bar_set_text (GTK_PROGRESS_BAR (progress), NULL);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
first_update = get_system_time ();
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
g_variant_get (variant, "(&o@a{sv})", &transfer, &properties);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
on_transfer_properties (properties);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
g_dbus_proxy_new (conn,
|
|
Packit |
8fb625 |
G_DBUS_PROXY_FLAGS_NONE,
|
|
Packit |
8fb625 |
NULL,
|
|
Packit |
8fb625 |
OBEX_SERVICE,
|
|
Packit |
8fb625 |
transfer,
|
|
Packit |
8fb625 |
TRANSFER_IFACE,
|
|
Packit |
8fb625 |
cancellable,
|
|
Packit |
8fb625 |
(GAsyncReadyCallback) transfer_proxy,
|
|
Packit |
8fb625 |
NULL);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
g_variant_unref (properties);
|
|
Packit |
8fb625 |
g_variant_unref (variant);
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static void
|
|
Packit |
8fb625 |
send_next_file (void)
|
|
Packit |
8fb625 |
{
|
|
Packit |
8fb625 |
update_from_label ();
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
g_dbus_proxy_call (session,
|
|
Packit |
8fb625 |
"SendFile",
|
|
Packit |
8fb625 |
g_variant_new ("(s)", option_files[file_index]),
|
|
Packit |
8fb625 |
G_DBUS_CALL_FLAGS_NONE,
|
|
Packit |
8fb625 |
-1,
|
|
Packit |
8fb625 |
cancellable,
|
|
Packit |
8fb625 |
(GAsyncReadyCallback) transfer_created,
|
|
Packit |
8fb625 |
NULL);
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static void
|
|
Packit |
8fb625 |
session_proxy (GDBusProxy *proxy, GAsyncResult *res, gpointer user_data)
|
|
Packit |
8fb625 |
{
|
|
Packit |
8fb625 |
GError *error = NULL;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
g_clear_object (&session);
|
|
Packit |
8fb625 |
session = g_dbus_proxy_new_finish (res, &error);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
if (session == NULL) {
|
|
Packit |
8fb625 |
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
|
Packit |
8fb625 |
g_error_free (error);
|
|
Packit |
8fb625 |
return;
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
handle_error (error);
|
|
Packit |
8fb625 |
return;
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
send_next_file ();
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static void
|
|
Packit |
8fb625 |
session_created (GDBusProxy *proxy, GAsyncResult *res, gpointer user_data)
|
|
Packit |
8fb625 |
{
|
|
Packit |
8fb625 |
GError *error = NULL;
|
|
Packit |
8fb625 |
GVariant *variant;
|
|
Packit |
8fb625 |
const char *session;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
variant = g_dbus_proxy_call_finish (proxy, res, &error);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
if (variant == NULL) {
|
|
Packit |
8fb625 |
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
|
Packit |
8fb625 |
g_error_free (error);
|
|
Packit |
8fb625 |
return;
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
handle_error (error);
|
|
Packit |
8fb625 |
return;
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
g_variant_get (variant, "(&o)", &session);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
g_dbus_proxy_new (conn,
|
|
Packit |
8fb625 |
G_DBUS_PROXY_FLAGS_NONE,
|
|
Packit |
8fb625 |
NULL,
|
|
Packit |
8fb625 |
OBEX_SERVICE,
|
|
Packit |
8fb625 |
session,
|
|
Packit |
8fb625 |
OPP_IFACE,
|
|
Packit |
8fb625 |
cancellable,
|
|
Packit |
8fb625 |
(GAsyncReadyCallback) session_proxy,
|
|
Packit |
8fb625 |
NULL);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
g_variant_unref (variant);
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static void
|
|
Packit |
8fb625 |
send_files (void)
|
|
Packit |
8fb625 |
{
|
|
Packit |
8fb625 |
GVariant *parameters;
|
|
Packit |
8fb625 |
GVariantBuilder *builder;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
builder = g_variant_builder_new (G_VARIANT_TYPE_DICTIONARY);
|
|
Packit |
8fb625 |
g_variant_builder_add (builder, "{sv}", "Target",
|
|
Packit |
8fb625 |
g_variant_new_string ("opp"));
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
parameters = g_variant_new ("(sa{sv})", option_device, builder);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
g_dbus_proxy_call (client_proxy,
|
|
Packit |
8fb625 |
"CreateSession",
|
|
Packit |
8fb625 |
parameters,
|
|
Packit |
8fb625 |
G_DBUS_CALL_FLAGS_NONE,
|
|
Packit |
8fb625 |
-1,
|
|
Packit |
8fb625 |
cancellable,
|
|
Packit |
8fb625 |
(GAsyncReadyCallback) session_created,
|
|
Packit |
8fb625 |
NULL);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
g_variant_builder_unref (builder);
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static gchar *filename_to_path(const gchar *filename)
|
|
Packit |
8fb625 |
{
|
|
Packit |
8fb625 |
GFile *file;
|
|
Packit |
8fb625 |
gchar *path;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
file = g_file_new_for_commandline_arg(filename);
|
|
Packit |
8fb625 |
path = g_file_get_path(file);
|
|
Packit |
8fb625 |
g_object_unref(file);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
return path;
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static gchar *format_time(gint seconds)
|
|
Packit |
8fb625 |
{
|
|
Packit |
8fb625 |
gint hours, minutes;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
if (seconds < 0)
|
|
Packit |
8fb625 |
seconds = 0;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
if (seconds < 60)
|
|
Packit |
8fb625 |
return g_strdup_printf(ngettext("%'d second",
|
|
Packit |
8fb625 |
"%'d seconds", seconds), seconds);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
if (seconds < 60 * 60) {
|
|
Packit |
8fb625 |
minutes = (seconds + 30) / 60;
|
|
Packit |
8fb625 |
return g_strdup_printf(ngettext("%'d minute",
|
|
Packit |
8fb625 |
"%'d minutes", minutes), minutes);
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
hours = seconds / (60 * 60);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
if (seconds < 60 * 60 * 4) {
|
|
Packit |
8fb625 |
gchar *res, *h, *m;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
minutes = (seconds - hours * 60 * 60 + 30) / 60;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
h = g_strdup_printf(ngettext("%'d hour",
|
|
Packit |
8fb625 |
"%'d hours", hours), hours);
|
|
Packit |
8fb625 |
m = g_strdup_printf(ngettext("%'d minute",
|
|
Packit |
8fb625 |
"%'d minutes", minutes), minutes);
|
|
Packit |
8fb625 |
res = g_strconcat(h, ", ", m, NULL);
|
|
Packit |
8fb625 |
g_free(h);
|
|
Packit |
8fb625 |
g_free(m);
|
|
Packit |
8fb625 |
return res;
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
return g_strdup_printf(ngettext("approximately %'d hour",
|
|
Packit |
8fb625 |
"approximately %'d hours", hours), hours);
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static void response_callback(GtkWidget *dialog,
|
|
Packit |
8fb625 |
gint response, gpointer user_data)
|
|
Packit |
8fb625 |
{
|
|
Packit |
8fb625 |
if (response == RESPONSE_RETRY) {
|
|
Packit |
8fb625 |
/* Reset buttons */
|
|
Packit |
8fb625 |
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), RESPONSE_RETRY, FALSE);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
/* Reset status and progress bar */
|
|
Packit |
8fb625 |
gtk_progress_bar_set_text (GTK_PROGRESS_BAR (progress),
|
|
Packit |
8fb625 |
_("Connecting…"));
|
|
Packit |
8fb625 |
gtk_label_set_text (GTK_LABEL (label_status), "");
|
|
Packit |
8fb625 |
gtk_widget_hide (image_status);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
/* If we have a session, we don't need to create another one. */
|
|
Packit |
8fb625 |
if (session)
|
|
Packit |
8fb625 |
send_next_file ();
|
|
Packit |
8fb625 |
else
|
|
Packit |
8fb625 |
send_files ();
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
return;
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
/* Cancel any ongoing dbus calls we may have */
|
|
Packit |
8fb625 |
g_cancellable_cancel (cancellable);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
if (current_transfer != NULL) {
|
|
Packit |
8fb625 |
g_dbus_proxy_call (current_transfer,
|
|
Packit |
8fb625 |
"Cancel",
|
|
Packit |
8fb625 |
NULL,
|
|
Packit |
8fb625 |
G_DBUS_CALL_FLAGS_NONE,
|
|
Packit |
8fb625 |
-1,
|
|
Packit |
8fb625 |
NULL,
|
|
Packit |
8fb625 |
(GAsyncReadyCallback) NULL,
|
|
Packit |
8fb625 |
NULL);
|
|
Packit |
8fb625 |
g_object_unref (current_transfer);
|
|
Packit |
8fb625 |
current_transfer = NULL;
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
gtk_widget_destroy(dialog);
|
|
Packit |
8fb625 |
gtk_main_quit();
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static void create_window(void)
|
|
Packit |
8fb625 |
{
|
|
Packit |
8fb625 |
GtkWidget *vbox, *hbox;
|
|
Packit |
8fb625 |
GtkWidget *table;
|
|
Packit |
8fb625 |
GtkWidget *label;
|
|
Packit |
8fb625 |
gchar *text;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
dialog = g_object_new (GTK_TYPE_DIALOG,
|
|
Packit |
8fb625 |
"use-header-bar", 1,
|
|
Packit |
8fb625 |
"title", _("Bluetooth File Transfer"),
|
|
Packit |
8fb625 |
NULL);
|
|
Packit |
8fb625 |
gtk_dialog_add_buttons(GTK_DIALOG (dialog),
|
|
Packit |
8fb625 |
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
|
Packit |
8fb625 |
_("_Retry"), RESPONSE_RETRY,
|
|
Packit |
8fb625 |
NULL);
|
|
Packit |
8fb625 |
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), RESPONSE_RETRY, FALSE);
|
|
Packit |
8fb625 |
gtk_window_set_type_hint(GTK_WINDOW(dialog),
|
|
Packit |
8fb625 |
GDK_WINDOW_TYPE_HINT_NORMAL);
|
|
Packit |
8fb625 |
gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
|
|
Packit |
8fb625 |
gtk_window_set_default_size(GTK_WINDOW(dialog), 400, -1);
|
|
Packit |
8fb625 |
gtk_container_set_border_width(GTK_CONTAINER(dialog), 6);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
|
|
Packit |
8fb625 |
gtk_box_set_spacing(GTK_BOX(vbox), 6);
|
|
Packit |
8fb625 |
gtk_container_set_border_width(GTK_CONTAINER(vbox), 6);
|
|
Packit |
8fb625 |
gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
|
|
Packit |
8fb625 |
vbox);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
table = gtk_grid_new();
|
|
Packit |
8fb625 |
gtk_grid_set_column_spacing(GTK_GRID(table), 4);
|
|
Packit |
8fb625 |
gtk_grid_set_row_spacing(GTK_GRID(table), 4);
|
|
Packit |
8fb625 |
gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 9);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
label = gtk_label_new(NULL);
|
|
Packit |
8fb625 |
gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
|
|
Packit |
8fb625 |
text = g_markup_printf_escaped("%s", _("From:"));
|
|
Packit |
8fb625 |
gtk_label_set_markup(GTK_LABEL(label), text);
|
|
Packit |
8fb625 |
g_free(text);
|
|
Packit |
8fb625 |
gtk_grid_attach(GTK_GRID(table), label, 0, 0, 1, 1);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
label_from = gtk_label_new(NULL);
|
|
Packit |
8fb625 |
gtk_misc_set_alignment(GTK_MISC(label_from), 0, 0.5);
|
|
Packit |
8fb625 |
gtk_label_set_ellipsize(GTK_LABEL(label_from), PANGO_ELLIPSIZE_MIDDLE);
|
|
Packit |
8fb625 |
gtk_grid_attach(GTK_GRID(table), label_from, 1, 0, 1, 1);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
update_from_label ();
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
label = gtk_label_new(NULL);
|
|
Packit |
8fb625 |
gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
|
|
Packit |
8fb625 |
text = g_markup_printf_escaped("%s", _("To:"));
|
|
Packit |
8fb625 |
gtk_label_set_markup(GTK_LABEL(label), text);
|
|
Packit |
8fb625 |
g_free(text);
|
|
Packit |
8fb625 |
gtk_grid_attach(GTK_GRID(table), label, 0, 1, 1, 1);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
label = gtk_label_new(NULL);
|
|
Packit |
8fb625 |
gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
|
|
Packit |
8fb625 |
gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_END);
|
|
Packit |
8fb625 |
gtk_label_set_text(GTK_LABEL(label), option_device_name);
|
|
Packit |
8fb625 |
gtk_grid_attach(GTK_GRID(table), label, 1, 1, 1, 1);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
progress = gtk_progress_bar_new();
|
|
Packit |
8fb625 |
gtk_progress_bar_set_show_text (GTK_PROGRESS_BAR (progress), TRUE);
|
|
Packit |
8fb625 |
gtk_progress_bar_set_ellipsize(GTK_PROGRESS_BAR(progress),
|
|
Packit |
8fb625 |
PANGO_ELLIPSIZE_END);
|
|
Packit |
8fb625 |
gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress),
|
|
Packit |
8fb625 |
_("Connecting…"));
|
|
Packit |
8fb625 |
gtk_box_pack_start(GTK_BOX(vbox), progress, TRUE, TRUE, 0);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
image_status = gtk_image_new_from_icon_name ("dialog-warning", GTK_ICON_SIZE_MENU);
|
|
Packit |
8fb625 |
gtk_widget_set_no_show_all (image_status, TRUE);
|
|
Packit |
8fb625 |
gtk_box_pack_start(GTK_BOX (hbox), image_status, FALSE, FALSE, 4);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
label_status = gtk_label_new(NULL);
|
|
Packit |
8fb625 |
gtk_misc_set_alignment(GTK_MISC(label_status), 0, 0.5);
|
|
Packit |
8fb625 |
gtk_label_set_line_wrap(GTK_LABEL(label_status), TRUE);
|
|
Packit |
8fb625 |
gtk_box_pack_start(GTK_BOX (hbox), label_status, TRUE, TRUE, 4);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 2);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
g_signal_connect(G_OBJECT(dialog), "response",
|
|
Packit |
8fb625 |
G_CALLBACK(response_callback), NULL);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
gtk_widget_show_all(dialog);
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static gchar *get_device_name(const gchar *address)
|
|
Packit |
8fb625 |
{
|
|
Packit |
8fb625 |
BluetoothClient *client;
|
|
Packit |
8fb625 |
GtkTreeModel *model;
|
|
Packit |
8fb625 |
GtkTreeIter iter;
|
|
Packit |
8fb625 |
gboolean cont;
|
|
Packit |
8fb625 |
char *found_name;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
found_name = NULL;
|
|
Packit |
8fb625 |
client = bluetooth_client_new ();
|
|
Packit |
8fb625 |
model = bluetooth_client_get_model (client);
|
|
Packit |
8fb625 |
if (model == NULL) {
|
|
Packit |
8fb625 |
g_object_unref (client);
|
|
Packit |
8fb625 |
return NULL;
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
cont = gtk_tree_model_get_iter_first(model, &iter);
|
|
Packit |
8fb625 |
while (cont != FALSE) {
|
|
Packit |
8fb625 |
char *bdaddr, *name;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
gtk_tree_model_get(model, &iter,
|
|
Packit |
8fb625 |
BLUETOOTH_COLUMN_ADDRESS, &bdaddr,
|
|
Packit |
8fb625 |
BLUETOOTH_COLUMN_ALIAS, &name,
|
|
Packit |
8fb625 |
-1);
|
|
Packit |
8fb625 |
if (g_strcmp0 (bdaddr, address) == 0) {
|
|
Packit |
8fb625 |
g_free (bdaddr);
|
|
Packit |
8fb625 |
found_name = name;
|
|
Packit |
8fb625 |
break;
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
g_free (bdaddr);
|
|
Packit |
8fb625 |
g_free (name);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
cont = gtk_tree_model_iter_next(model, &iter);
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
g_object_unref (model);
|
|
Packit |
8fb625 |
g_object_unref (client);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
return found_name;
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static void
|
|
Packit |
8fb625 |
on_transfer_properties (GVariant *props)
|
|
Packit |
8fb625 |
{
|
|
Packit |
8fb625 |
char *filename = option_files[file_index];
|
|
Packit |
8fb625 |
char *basename, *text, *markup;
|
|
Packit |
8fb625 |
GVariant *size;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
size = g_variant_lookup_value (props, "Size", G_VARIANT_TYPE_UINT64);
|
|
Packit |
8fb625 |
if (size) {
|
|
Packit |
8fb625 |
current_size = g_variant_get_uint64 (size);
|
|
Packit |
8fb625 |
last_update = get_system_time ();
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
basename = g_path_get_basename(filename);
|
|
Packit |
8fb625 |
text = g_strdup_printf(_("Sending %s"), basename);
|
|
Packit |
8fb625 |
g_free(basename);
|
|
Packit |
8fb625 |
markup = g_markup_printf_escaped("%s", text);
|
|
Packit |
8fb625 |
gtk_label_set_markup(GTK_LABEL(label_status), markup);
|
|
Packit |
8fb625 |
g_free(markup);
|
|
Packit |
8fb625 |
g_free(text);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
text = g_strdup_printf(_("Sending file %d of %d"),
|
|
Packit |
8fb625 |
file_index + 1, file_count);
|
|
Packit |
8fb625 |
gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress), text);
|
|
Packit |
8fb625 |
g_free(text);
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static void
|
|
Packit |
8fb625 |
on_transfer_progress (guint64 transferred)
|
|
Packit |
8fb625 |
{
|
|
Packit |
8fb625 |
gint64 current_time;
|
|
Packit |
8fb625 |
gint elapsed_time;
|
|
Packit |
8fb625 |
gint remaining_time;
|
|
Packit |
8fb625 |
gint transfer_rate;
|
|
Packit |
8fb625 |
guint64 current_sent;
|
|
Packit |
8fb625 |
gdouble fraction;
|
|
Packit |
8fb625 |
gchar *time, *rate, *file, *text;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
current_sent = total_sent + transferred;
|
|
Packit |
8fb625 |
if (total_size == 0)
|
|
Packit |
8fb625 |
fraction = 0.0;
|
|
Packit |
8fb625 |
else
|
|
Packit |
8fb625 |
fraction = (gdouble) current_sent / (gdouble) total_size;
|
|
Packit |
8fb625 |
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), fraction);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
current_time = get_system_time();
|
|
Packit |
8fb625 |
elapsed_time = (current_time - first_update) / 1000000;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
if (current_time < last_update + 1000000)
|
|
Packit |
8fb625 |
return;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
last_update = current_time;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
if (elapsed_time == 0)
|
|
Packit |
8fb625 |
return;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
transfer_rate = current_sent / elapsed_time;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
if (transfer_rate == 0)
|
|
Packit |
8fb625 |
return;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
remaining_time = (total_size - current_sent) / transfer_rate;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
time = format_time(remaining_time);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
if (transfer_rate >= 3000)
|
|
Packit |
8fb625 |
rate = g_strdup_printf(_("%d kB/s"), transfer_rate / 1000);
|
|
Packit |
8fb625 |
else
|
|
Packit |
8fb625 |
rate = g_strdup_printf(_("%d B/s"), transfer_rate);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
file = g_strdup_printf(_("Sending file %d of %d"),
|
|
Packit |
8fb625 |
file_index + 1, file_count);
|
|
Packit |
8fb625 |
text = g_strdup_printf("%s (%s, %s)", file, rate, time);
|
|
Packit |
8fb625 |
g_free(file);
|
|
Packit |
8fb625 |
g_free(rate);
|
|
Packit |
8fb625 |
g_free(time);
|
|
Packit |
8fb625 |
gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress), text);
|
|
Packit |
8fb625 |
g_free(text);
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static void
|
|
Packit |
8fb625 |
on_transfer_complete (void)
|
|
Packit |
8fb625 |
{
|
|
Packit |
8fb625 |
total_sent += current_size;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
file_index++;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
/* And we're done with the transfer */
|
|
Packit |
8fb625 |
g_object_unref (current_transfer);
|
|
Packit |
8fb625 |
current_transfer = NULL;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
if (file_index == file_count) {
|
|
Packit |
8fb625 |
GtkWidget *button;
|
|
Packit |
8fb625 |
char *complete;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), 1.0);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress), "");
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
complete = g_strdup_printf (ngettext ("%u transfer complete",
|
|
Packit |
8fb625 |
"%u transfers complete",
|
|
Packit |
8fb625 |
file_count), file_count);
|
|
Packit |
8fb625 |
gtk_label_set_text (GTK_LABEL (label_status), complete);
|
|
Packit |
8fb625 |
g_free (complete);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
button = gtk_dialog_get_widget_for_response(GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
|
|
Packit |
8fb625 |
gtk_button_set_label (GTK_BUTTON (button), _("_Close"));
|
|
Packit |
8fb625 |
} else {
|
|
Packit |
8fb625 |
send_next_file ();
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static void
|
|
Packit |
8fb625 |
on_transfer_error (void)
|
|
Packit |
8fb625 |
{
|
|
Packit |
8fb625 |
gtk_widget_show (image_status);
|
|
Packit |
8fb625 |
gtk_label_set_markup (GTK_LABEL (label_status), _("There was an error"));
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), RESPONSE_RETRY, TRUE);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
g_object_unref (current_transfer);
|
|
Packit |
8fb625 |
current_transfer = NULL;
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static void
|
|
Packit |
8fb625 |
select_device_changed(BluetoothChooser *sel,
|
|
Packit |
8fb625 |
char *address,
|
|
Packit |
8fb625 |
gpointer user_data)
|
|
Packit |
8fb625 |
{
|
|
Packit |
8fb625 |
GtkDialog *dialog = user_data;
|
|
Packit |
8fb625 |
char *icon;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
if (address == NULL)
|
|
Packit |
8fb625 |
goto bail;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
icon = bluetooth_chooser_get_selected_device_icon (sel);
|
|
Packit |
8fb625 |
if (icon == NULL)
|
|
Packit |
8fb625 |
goto bail;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
/* Apple's device don't have OBEX */
|
|
Packit |
8fb625 |
if (g_str_equal (icon, "phone-apple-iphone"))
|
|
Packit |
8fb625 |
goto bail;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
gtk_dialog_set_response_sensitive (dialog,
|
|
Packit |
8fb625 |
GTK_RESPONSE_ACCEPT, TRUE);
|
|
Packit |
8fb625 |
return;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
bail:
|
|
Packit |
8fb625 |
gtk_dialog_set_response_sensitive (dialog,
|
|
Packit |
8fb625 |
GTK_RESPONSE_ACCEPT, FALSE);
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static void
|
|
Packit |
8fb625 |
select_device_activated(BluetoothChooser *sel,
|
|
Packit |
8fb625 |
char *address,
|
|
Packit |
8fb625 |
gpointer user_data)
|
|
Packit |
8fb625 |
{
|
|
Packit |
8fb625 |
GtkDialog *dialog = user_data;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
gtk_dialog_response(dialog, GTK_RESPONSE_ACCEPT);
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static char *
|
|
Packit |
8fb625 |
show_browse_dialog (char **device_name)
|
|
Packit |
8fb625 |
{
|
|
Packit |
8fb625 |
GtkWidget *dialog, *selector, *send_button, *content_area;
|
|
Packit |
8fb625 |
char *bdaddr;
|
|
Packit |
8fb625 |
int response_id;
|
|
Packit |
8fb625 |
GtkStyleContext *context;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
dialog = g_object_new (GTK_TYPE_DIALOG,
|
|
Packit |
8fb625 |
"title", _("Select device to send to"),
|
|
Packit |
8fb625 |
"use-header-bar", 1,
|
|
Packit |
8fb625 |
NULL);
|
|
Packit |
8fb625 |
gtk_dialog_add_buttons(GTK_DIALOG (dialog),
|
|
Packit |
8fb625 |
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
|
Packit |
8fb625 |
_("_Send"), GTK_RESPONSE_ACCEPT,
|
|
Packit |
8fb625 |
NULL);
|
|
Packit |
8fb625 |
gtk_window_set_type_hint (GTK_WINDOW (dialog), GDK_WINDOW_TYPE_HINT_NORMAL);
|
|
Packit |
8fb625 |
send_button = gtk_dialog_get_widget_for_response(GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
|
|
Packit |
8fb625 |
context = gtk_widget_get_style_context(send_button);
|
|
Packit |
8fb625 |
gtk_style_context_add_class (context, "suggested-action");
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog),
|
|
Packit |
8fb625 |
GTK_RESPONSE_ACCEPT, FALSE);
|
|
Packit |
8fb625 |
gtk_window_set_default_size(GTK_WINDOW(dialog), 480, 400);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
|
|
Packit |
8fb625 |
content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
|
|
Packit |
8fb625 |
gtk_box_set_spacing (GTK_BOX (content_area), 2);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
selector = bluetooth_chooser_new();
|
|
Packit |
8fb625 |
gtk_container_set_border_width(GTK_CONTAINER(selector), 5);
|
|
Packit |
8fb625 |
gtk_widget_show(selector);
|
|
Packit |
8fb625 |
g_object_set(selector,
|
|
Packit |
8fb625 |
"show-searching", TRUE,
|
|
Packit |
8fb625 |
"show-device-category", TRUE,
|
|
Packit |
8fb625 |
"show-device-type", TRUE,
|
|
Packit |
8fb625 |
NULL);
|
|
Packit |
8fb625 |
g_signal_connect(selector, "selected-device-changed",
|
|
Packit |
8fb625 |
G_CALLBACK(select_device_changed), dialog);
|
|
Packit |
8fb625 |
g_signal_connect(selector, "selected-device-activated",
|
|
Packit |
8fb625 |
G_CALLBACK(select_device_activated), dialog);
|
|
Packit |
8fb625 |
gtk_box_pack_start (GTK_BOX (content_area), selector, TRUE, TRUE, 0);
|
|
Packit |
8fb625 |
bluetooth_chooser_start_discovery (BLUETOOTH_CHOOSER (selector));
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
bdaddr = NULL;
|
|
Packit |
8fb625 |
response_id = gtk_dialog_run (GTK_DIALOG (dialog));
|
|
Packit |
8fb625 |
if (response_id == GTK_RESPONSE_ACCEPT) {
|
|
Packit |
8fb625 |
bdaddr = bluetooth_chooser_get_selected_device (BLUETOOTH_CHOOSER (selector));
|
|
Packit |
8fb625 |
*device_name = bluetooth_chooser_get_selected_device_name (BLUETOOTH_CHOOSER (selector));
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
gtk_widget_destroy (dialog);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
return bdaddr;
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static char **
|
|
Packit |
8fb625 |
show_select_dialog(void)
|
|
Packit |
8fb625 |
{
|
|
Packit |
8fb625 |
GtkWidget *dialog, *button;
|
|
Packit |
8fb625 |
gchar **files = NULL;
|
|
Packit |
8fb625 |
GtkStyleContext *context;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
dialog = g_object_new (GTK_TYPE_FILE_CHOOSER_DIALOG,
|
|
Packit |
8fb625 |
"title", _("Choose files to send"),
|
|
Packit |
8fb625 |
"action", GTK_FILE_CHOOSER_ACTION_OPEN,
|
|
Packit |
8fb625 |
"use-header-bar", 1,
|
|
Packit |
8fb625 |
NULL);
|
|
Packit |
8fb625 |
gtk_dialog_add_buttons(GTK_DIALOG (dialog),
|
|
Packit |
8fb625 |
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
|
Packit |
8fb625 |
_("Select"), GTK_RESPONSE_ACCEPT, NULL);
|
|
Packit |
8fb625 |
gtk_window_set_type_hint (GTK_WINDOW (dialog), GDK_WINDOW_TYPE_HINT_NORMAL);
|
|
Packit |
8fb625 |
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
button = gtk_dialog_get_widget_for_response(GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
|
|
Packit |
8fb625 |
context = gtk_widget_get_style_context(button);
|
|
Packit |
8fb625 |
gtk_style_context_add_class (context, "suggested-action");
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
|
|
Packit |
8fb625 |
GSList *list, *filenames;
|
|
Packit |
8fb625 |
int i;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
filenames = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog));
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
files = g_new(gchar *, g_slist_length(filenames) + 1);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
for (list = filenames, i = 0; list; list = list->next, i++)
|
|
Packit |
8fb625 |
files[i] = list->data;
|
|
Packit |
8fb625 |
files[i] = NULL;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
g_slist_free(filenames);
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
gtk_widget_destroy(dialog);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
return files;
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
static GOptionEntry options[] = {
|
|
Packit |
8fb625 |
{ "device", 0, 0, G_OPTION_ARG_STRING, &option_device,
|
|
Packit |
8fb625 |
N_("Remote device to use"), N_("ADDRESS") },
|
|
Packit |
8fb625 |
{ "name", 0, 0, G_OPTION_ARG_STRING, &option_device_name,
|
|
Packit |
8fb625 |
N_("Remote device’s name"), N_("NAME") },
|
|
Packit |
8fb625 |
{ "dest", 0, G_OPTION_FLAG_HIDDEN,
|
|
Packit |
8fb625 |
G_OPTION_ARG_STRING, &option_device, NULL, NULL },
|
|
Packit |
8fb625 |
{ G_OPTION_REMAINING, 0, 0,
|
|
Packit |
8fb625 |
G_OPTION_ARG_FILENAME_ARRAY, &option_files },
|
|
Packit |
8fb625 |
{ NULL },
|
|
Packit |
8fb625 |
};
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
int main(int argc, char *argv[])
|
|
Packit |
8fb625 |
{
|
|
Packit |
8fb625 |
GError *error = NULL;
|
|
Packit |
8fb625 |
int i;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
|
|
Packit |
8fb625 |
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
|
|
Packit |
8fb625 |
textdomain(GETTEXT_PACKAGE);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
error = NULL;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
if (gtk_init_with_args(&argc, &argv, _("[FILE…]"),
|
|
Packit |
8fb625 |
options, GETTEXT_PACKAGE, &error) == FALSE) {
|
|
Packit |
8fb625 |
if (error != NULL) {
|
|
Packit |
8fb625 |
g_printerr("%s\n", error->message);
|
|
Packit |
8fb625 |
g_error_free(error);
|
|
Packit |
8fb625 |
} else
|
|
Packit |
8fb625 |
g_printerr("An unknown error occurred\n");
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
return 1;
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
gtk_window_set_default_icon_name("bluetooth");
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
cancellable = g_cancellable_new ();
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
/* A device name, but no device? */
|
|
Packit |
8fb625 |
if (option_device == NULL && option_device_name != NULL) {
|
|
Packit |
8fb625 |
if (option_files != NULL)
|
|
Packit |
8fb625 |
g_strfreev(option_files);
|
|
Packit |
8fb625 |
g_free (option_device_name);
|
|
Packit |
8fb625 |
return 1;
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
if (option_files == NULL) {
|
|
Packit |
8fb625 |
option_files = show_select_dialog();
|
|
Packit |
8fb625 |
if (option_files == NULL)
|
|
Packit |
8fb625 |
return 1;
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
if (option_device == NULL) {
|
|
Packit |
8fb625 |
option_device = show_browse_dialog(&option_device_name);
|
|
Packit |
8fb625 |
if (option_device == NULL) {
|
|
Packit |
8fb625 |
g_strfreev(option_files);
|
|
Packit |
8fb625 |
return 1;
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
file_count = g_strv_length(option_files);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
for (i = 0; i < file_count; i++) {
|
|
Packit |
8fb625 |
gchar *filename;
|
|
Packit |
8fb625 |
struct stat st;
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
filename = filename_to_path(option_files[i]);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
if (filename != NULL) {
|
|
Packit |
8fb625 |
g_free(option_files[i]);
|
|
Packit |
8fb625 |
option_files[i] = filename;
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
if (g_file_test(option_files[i],
|
|
Packit |
8fb625 |
G_FILE_TEST_IS_REGULAR) == FALSE) {
|
|
Packit |
8fb625 |
option_files[i][0] = '\0';
|
|
Packit |
8fb625 |
continue;
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
if (g_stat(option_files[i], &st) < 0)
|
|
Packit |
8fb625 |
option_files[i][0] = '\0';
|
|
Packit |
8fb625 |
else
|
|
Packit |
8fb625 |
total_size += st.st_size;
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
|
|
Packit |
8fb625 |
if (conn == NULL) {
|
|
Packit |
8fb625 |
if (error != NULL) {
|
|
Packit |
8fb625 |
g_printerr("Connecting to session bus failed: %s\n",
|
|
Packit |
8fb625 |
error->message);
|
|
Packit |
8fb625 |
g_error_free(error);
|
|
Packit |
8fb625 |
} else
|
|
Packit |
8fb625 |
g_print("An unknown error occurred\n");
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
return 1;
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
client_proxy = g_dbus_proxy_new_sync (conn,
|
|
Packit |
8fb625 |
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
|
|
Packit |
8fb625 |
NULL,
|
|
Packit |
8fb625 |
OBEX_SERVICE,
|
|
Packit |
8fb625 |
OBEX_PATH,
|
|
Packit |
8fb625 |
CLIENT_IFACE,
|
|
Packit |
8fb625 |
cancellable,
|
|
Packit |
8fb625 |
&error);
|
|
Packit |
8fb625 |
if (client_proxy == NULL) {
|
|
Packit |
8fb625 |
g_printerr("Acquiring proxy failed: %s\n", error->message);
|
|
Packit |
8fb625 |
g_error_free (error);
|
|
Packit |
8fb625 |
return 1;
|
|
Packit |
8fb625 |
}
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
if (option_device_name == NULL)
|
|
Packit |
8fb625 |
option_device_name = get_device_name(option_device);
|
|
Packit |
8fb625 |
if (option_device_name == NULL)
|
|
Packit |
8fb625 |
option_device_name = g_strdup(option_device);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
create_window();
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
if (!g_cancellable_is_cancelled (cancellable))
|
|
Packit |
8fb625 |
send_files ();
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
gtk_main();
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
g_cancellable_cancel (cancellable);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
g_clear_object (&cancellable);
|
|
Packit |
8fb625 |
g_clear_object (¤t_transfer);
|
|
Packit |
8fb625 |
g_clear_object (&session);
|
|
Packit |
8fb625 |
g_object_unref (client_proxy);
|
|
Packit |
8fb625 |
g_object_unref (conn);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
g_strfreev(option_files);
|
|
Packit |
8fb625 |
g_free(option_device);
|
|
Packit |
8fb625 |
g_free(option_device_name);
|
|
Packit |
8fb625 |
|
|
Packit |
8fb625 |
return 0;
|
|
Packit |
8fb625 |
}
|