No issues found
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2012 Jonathan Matthew <jonathan@d14n.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * The Rhythmbox authors hereby grant permission for non-GPL compatible
11 * GStreamer plugins to be used and distributed together with GStreamer
12 * and Rhythmbox. This permission is above and beyond the permissions granted
13 * by the GPL license by which Rhythmbox is covered. If you modify this code
14 * you may extend this exception to your version of the code, but you are not
15 * obligated to do so. If you do not wish to do so, delete this exception
16 * statement from your version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
26 *
27 */
28
29 #include "config.h"
30
31 #include <lib/rb-async-copy.h>
32 #include <lib/rb-debug.h>
33
34 /**
35 * SECTION:rb-async-copy
36 * @short_description: performs asynchronous file copies (like g_file_copy_async)
37 *
38 */
39
40
41 static void rb_async_copy_class_init (RBAsyncCopyClass *klass);
42 static void rb_async_copy_init (RBAsyncCopy *copy);
43
44 struct _RBAsyncCopyPrivate
45 {
46 GError *error;
47 GCancellable *cancel;
48
49 GFile *src;
50 GFile *dest;
51
52 RBAsyncCopyCallback callback;
53 gpointer callback_data;
54 GDestroyNotify destroy_data;
55
56 RBAsyncCopyProgressCallback progress;
57 gpointer progress_data;
58 GDestroyNotify destroy_progress_data;
59 };
60
61 G_DEFINE_TYPE (RBAsyncCopy, rb_async_copy, G_TYPE_OBJECT);
62
63 static void
64 progress_cb (goffset current_num_bytes, goffset total_bytes, gpointer data)
65 {
66 RBAsyncCopy *copy = RB_ASYNC_COPY (data);
67
68 if (copy->priv->progress)
69 copy->priv->progress (copy, current_num_bytes, total_bytes, copy->priv->progress_data);
70 }
71
72 static void
73 copy_cb (GObject *src, GAsyncResult *res, gpointer data)
74 {
75 RBAsyncCopy *copy = RB_ASYNC_COPY (data);
76 gboolean result;
77
78 result = g_file_copy_finish (G_FILE (src), res, ©->priv->error);
79
80 rb_debug ("copy finished: %s", (result == FALSE) ? copy->priv->error->message : "ok");
81 copy->priv->callback (copy, result, copy->priv->callback_data);
82 }
83
84 /**
85 * rb_async_copy_start:
86 * @copy: a #RBAsyncCopy
87 * @src: source URI
88 * @dest: destination URI
89 * @callback: completion callback
90 * @user_data: data for completion callback
91 * @destroy_data: destroy function for user_data
92 *
93 * Starts copying @src to @dest, calling @callback on completion or error.
94 */
95 void
96 rb_async_copy_start (RBAsyncCopy *copy,
97 const char *src,
98 const char *dest,
99 RBAsyncCopyCallback callback,
100 gpointer user_data,
101 GDestroyNotify destroy_data)
102 {
103 g_assert (copy->priv->src == NULL);
104
105 copy->priv->cancel = g_cancellable_new ();
106
107 copy->priv->callback = callback;
108 copy->priv->callback_data = user_data;
109 copy->priv->destroy_data = destroy_data;
110
111 copy->priv->src = g_file_new_for_commandline_arg (src);
112 copy->priv->dest = g_file_new_for_commandline_arg (dest);
113
114 g_file_copy_async (copy->priv->src,
115 copy->priv->dest,
116 G_FILE_COPY_NONE,
117 G_PRIORITY_DEFAULT,
118 copy->priv->cancel,
119 progress_cb,
120 copy,
121 copy_cb,
122 copy);
123 }
124
125 /**
126 * rb_async_copy_cancel:
127 * @copy: a #RBAsyncCopy
128 *
129 * Cancels the loading operation, ensuring that the callback
130 * will not be called again.
131 */
132 void
133 rb_async_copy_cancel (RBAsyncCopy *copy)
134 {
135 g_cancellable_cancel (copy->priv->cancel);
136 }
137
138 /**
139 * rb_async_copy_set_callback:
140 * @copy: a #RBAsyncCopy
141 * @callback: the progress callback
142 * @user_data: data to pass to the callback
143 * @destroy_data: function to call to destroy user_data
144 *
145 * Sets the progress callback for the copy. The callback will
146 * be called periodically while the copy is proceeding.
147 */
148 void
149 rb_async_copy_set_progress (RBAsyncCopy *copy,
150 RBAsyncCopyProgressCallback callback,
151 gpointer user_data,
152 GDestroyNotify destroy_data)
153 {
154 g_assert (copy->priv->progress == NULL);
155 g_assert (copy->priv->src == NULL);
156
157 copy->priv->progress = callback;
158 copy->priv->progress_data = user_data;
159 copy->priv->destroy_progress_data = destroy_data;
160 }
161
162 /**
163 * rb_async_copy_get_error:
164 * @copy: a #RBAsyncCopy
165 *
166 * If an error has occurred that prevents the copy from proceeding,
167 * this function will return a #GError, otherwise NULL.
168 *
169 * Return value: copy error or NULL
170 */
171 GError *
172 rb_async_copy_get_error (RBAsyncCopy *copy)
173 {
174 if (copy->priv->error)
175 return g_error_copy (copy->priv->error);
176 return NULL;
177 }
178
179 /**
180 * rb_async_copy_new:
181 *
182 * Creates and returns a new #RBAsyncCopy instance.
183 *
184 * Return value: #RBAsyncCopy instance
185 */
186 RBAsyncCopy *
187 rb_async_copy_new (void)
188 {
189 return RB_ASYNC_COPY (g_object_new (RB_TYPE_ASYNC_COPY, NULL));
190 }
191
192 static void
193 impl_finalize (GObject *object)
194 {
195 RBAsyncCopy *copy = RB_ASYNC_COPY (object);
196
197 g_clear_error (©->priv->error);
198
199 if (copy->priv->cancel) {
200 g_object_unref (copy->priv->cancel);
201 copy->priv->cancel = NULL;
202 }
203
204 if (copy->priv->src) {
205 g_object_unref (copy->priv->src);
206 copy->priv->src = NULL;
207 }
208 if (copy->priv->dest) {
209 g_object_unref (copy->priv->dest);
210 copy->priv->dest = NULL;
211 }
212
213 if (copy->priv->destroy_data) {
214 copy->priv->destroy_data (copy->priv->callback_data);
215 }
216 if (copy->priv->destroy_progress_data) {
217 copy->priv->destroy_progress_data (copy->priv->progress_data);
218 }
219
220 G_OBJECT_CLASS (rb_async_copy_parent_class)->finalize (object);
221 }
222
223 static void
224 rb_async_copy_init (RBAsyncCopy *copy)
225 {
226 copy->priv = G_TYPE_INSTANCE_GET_PRIVATE (copy, RB_TYPE_ASYNC_COPY, RBAsyncCopyPrivate);
227 }
228
229 static void
230 rb_async_copy_class_init (RBAsyncCopyClass *klass)
231 {
232 GObjectClass *object_class = G_OBJECT_CLASS (klass);
233
234 object_class->finalize = impl_finalize;
235
236 g_type_class_add_private (klass, sizeof (RBAsyncCopyPrivate));
237 }