~ubuntu-branches/debian/experimental/brasero/experimental

« back to all changes in this revision

Viewing changes to plugins/local-track/burn-uri.c

  • Committer: Bazaar Package Importer
  • Author(s): Emilio Pozuelo Monfort
  • Date: 2009-09-09 21:02:15 UTC
  • mfrom: (1.3.17 upstream)
  • Revision ID: james.westby@ubuntu.com-20090909210215-2a78qki0a1wyvtah
Tags: 2.27.92-2
Let libbrasero-media-dev depend on libdbus-glib-1-dev as it's required
by libbrasero-burn.pc.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 
2
/*
 
3
 * Libbrasero-burn
 
4
 * Copyright (C) Philippe Rouquier 2005-2009 <bonfire-app@wanadoo.fr>
 
5
 *
 
6
 * Libbrasero-burn is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * The Libbrasero-burn authors hereby grant permission for non-GPL compatible
 
12
 * GStreamer plugins to be used and distributed together with GStreamer
 
13
 * and Libbrasero-burn. This permission is above and beyond the permissions granted
 
14
 * by the GPL license by which Libbrasero-burn is covered. If you modify this code
 
15
 * you may extend this exception to your version of the code, but you are not
 
16
 * obligated to do so. If you do not wish to do so, delete this exception
 
17
 * statement from your version.
 
18
 * 
 
19
 * Libbrasero-burn is distributed in the hope that it will be useful,
 
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
22
 * GNU Library General Public License for more details.
 
23
 * 
 
24
 * You should have received a copy of the GNU General Public License
 
25
 * along with this program; if not, write to:
 
26
 *      The Free Software Foundation, Inc.,
 
27
 *      51 Franklin Street, Fifth Floor
 
28
 *      Boston, MA  02110-1301, USA.
 
29
 */
 
30
 
 
31
#ifdef HAVE_CONFIG_H
 
32
#  include <config.h>
 
33
#endif
 
34
 
 
35
#include <glib.h>
 
36
#include <glib-object.h>
 
37
#include <glib/gi18n-lib.h>
 
38
#include <glib/gstdio.h>
 
39
 
 
40
#include <gio/gio.h>
 
41
 
 
42
#include <gmodule.h>
 
43
 
 
44
#include "brasero-units.h"
 
45
#include "burn-job.h"
 
46
#include "brasero-plugin-registration.h"
 
47
#include "burn-uri.h"
 
48
 
 
49
#include "brasero-track.h"
 
50
#include "brasero-track-data.h"
 
51
#include "brasero-track-image.h"
 
52
 
 
53
BRASERO_PLUGIN_BOILERPLATE (BraseroBurnURI, brasero_burn_uri, BRASERO_TYPE_JOB, BraseroJob);
 
54
 
 
55
struct _BraseroBurnURIPrivate {
 
56
        GCancellable *cancel;
 
57
 
 
58
        BraseroTrack *track;
 
59
 
 
60
        guint thread_id;
 
61
        GThread *thread;
 
62
        GMutex *mutex;
 
63
        GCond *cond;
 
64
 
 
65
        GError *error;
 
66
};
 
67
typedef struct _BraseroBurnURIPrivate BraseroBurnURIPrivate;
 
68
 
 
69
#define BRASERO_BURN_URI_PRIVATE(o)  (G_TYPE_INSTANCE_GET_PRIVATE ((o), BRASERO_TYPE_BURN_URI, BraseroBurnURIPrivate))
 
70
 
 
71
static GObjectClass *parent_class = NULL;
 
72
 
 
73
 
 
74
static gboolean
 
75
brasero_burn_uri_thread_finished (BraseroBurnURI *self)
 
76
{
 
77
        BraseroBurnURIPrivate *priv;
 
78
 
 
79
        priv = BRASERO_BURN_URI_PRIVATE (self);
 
80
 
 
81
        priv->thread_id = 0;
 
82
 
 
83
        if (priv->cancel) {
 
84
                g_object_unref (priv->cancel);
 
85
                priv->cancel = NULL;
 
86
                if (g_cancellable_is_cancelled (priv->cancel))
 
87
                        return FALSE;
 
88
        }
 
89
 
 
90
        if (priv->error) {
 
91
                GError *error;
 
92
 
 
93
                error = priv->error;
 
94
                priv->error = NULL;
 
95
                brasero_job_error (BRASERO_JOB (self), error);
 
96
                return FALSE;
 
97
        }
 
98
 
 
99
        brasero_job_add_track (BRASERO_JOB (self), priv->track);
 
100
        brasero_job_finished_track (BRASERO_JOB (self));
 
101
 
 
102
        return FALSE;
 
103
}
 
104
 
 
105
static gint
 
106
brasero_burn_uri_find_graft (gconstpointer A, gconstpointer B)
 
107
{
 
108
        const BraseroGraftPt *graft = A;
 
109
 
 
110
        if (graft && graft->path)
 
111
                return strcmp (graft->path, B);
 
112
 
 
113
        return 1;
 
114
}
 
115
 
 
116
static GSList *
 
117
brasero_burn_uri_explore_directory (BraseroBurnURI *self,
 
118
                                    GSList *grafts,
 
119
                                    GFile *file,
 
120
                                    const gchar *path,
 
121
                                    GCancellable *cancel,
 
122
                                    GError **error)
 
123
{
 
124
        BraseroTrack *current = NULL;
 
125
        GFileEnumerator *enumerator;
 
126
        GSList *current_grafts;
 
127
        GFileInfo *info;
 
128
 
 
129
        enumerator = g_file_enumerate_children (file,
 
130
                                                G_FILE_ATTRIBUTE_STANDARD_NAME ","
 
131
                                                G_FILE_ATTRIBUTE_STANDARD_TYPE ","
 
132
                                                "burn::backing-file",
 
133
                                                G_FILE_QUERY_INFO_NONE,
 
134
                                                cancel,
 
135
                                                error);
 
136
 
 
137
        if (!enumerator) {
 
138
                g_slist_foreach (grafts, (GFunc) brasero_graft_point_free, NULL);
 
139
                g_slist_free (grafts);
 
140
                return NULL;
 
141
        }
 
142
 
 
143
        brasero_job_get_current_track (BRASERO_JOB (self), &current);
 
144
        current_grafts = brasero_track_data_get_grafts (BRASERO_TRACK_DATA (current));
 
145
 
 
146
        while ((info = g_file_enumerator_next_file (enumerator, cancel, error))) {
 
147
                if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
 
148
                        gchar *disc_path;
 
149
                        GFile *directory;
 
150
                        BraseroGraftPt *graft;
 
151
 
 
152
                        /* Make sure it's not one of the original grafts */
 
153
                        /* we need to know if that's a directory or not since if
 
154
                         * it is then mkisofs (but not genisoimage) requires the
 
155
                         * disc path to end with '/'; if there isn't '/' at the 
 
156
                         * end then only the directory contents are added. */
 
157
                        disc_path = g_build_filename (path, g_file_info_get_name (info), G_DIR_SEPARATOR_S, NULL);
 
158
                        if (g_slist_find_custom (current_grafts, disc_path, (GCompareFunc) brasero_burn_uri_find_graft)) {
 
159
                                BRASERO_JOB_LOG (self, "Graft already in list %s", disc_path);
 
160
                                g_object_unref (info);
 
161
                                g_free (disc_path);
 
162
                                continue;
 
163
                        }
 
164
 
 
165
                        /* we need a dummy directory */
 
166
                        graft = g_new0 (BraseroGraftPt, 1);
 
167
                        graft->uri = NULL;
 
168
                        graft->path = disc_path;
 
169
                        grafts = g_slist_prepend (grafts, graft);
 
170
 
 
171
                        BRASERO_JOB_LOG (self, "Adding directory %s at %s", graft->uri, graft->path);
 
172
 
 
173
                        directory = g_file_get_child (file, g_file_info_get_name (info));
 
174
                        grafts = brasero_burn_uri_explore_directory (self,
 
175
                                                                     grafts,
 
176
                                                                     directory,
 
177
                                                                     graft->path,
 
178
                                                                     cancel,
 
179
                                                                     error);
 
180
                        g_object_unref (directory);
 
181
 
 
182
                        if (!grafts) {
 
183
                                g_object_unref (info);
 
184
                                g_object_unref (enumerator);
 
185
                                return NULL;
 
186
                        }
 
187
                }
 
188
                else if (g_file_info_get_file_type (info) == G_FILE_TYPE_REGULAR
 
189
                     /* NOTE: burn:// URI allows symlink */
 
190
                     ||  g_file_info_get_file_type (info) == G_FILE_TYPE_SYMBOLIC_LINK) {
 
191
                        const gchar *real_path;
 
192
                        BraseroGraftPt *graft;
 
193
                        gchar *disc_path;
 
194
 
 
195
                        real_path = g_file_info_get_attribute_byte_string (info, "burn::backing-file");
 
196
                        if (!real_path) {
 
197
                                g_set_error (error,
 
198
                                             BRASERO_BURN_ERROR,
 
199
                                             BRASERO_BURN_ERROR_GENERAL,
 
200
                                             _("Impossible to retrieve local file path"));
 
201
 
 
202
                                g_slist_foreach (grafts, (GFunc) brasero_graft_point_free, NULL);
 
203
                                g_slist_free (grafts);
 
204
                                g_object_unref (info);
 
205
                                g_object_unref (file);
 
206
                                return NULL;
 
207
                        }
 
208
 
 
209
                        /* Make sure it's not one of the original grafts */
 
210
                        disc_path = g_build_filename (path, g_file_info_get_name (info), NULL);
 
211
                        if (g_slist_find_custom (current_grafts, disc_path, (GCompareFunc) brasero_burn_uri_find_graft)) {
 
212
                                BRASERO_JOB_LOG (self, "Graft already in list %s", disc_path);
 
213
                                g_object_unref (info);
 
214
                                g_free (disc_path);
 
215
                                continue;
 
216
                        }
 
217
 
 
218
                        graft = g_new0 (BraseroGraftPt, 1);
 
219
                        graft->path = disc_path;
 
220
                        graft->uri = g_strdup (real_path);
 
221
                        /* FIXME: maybe one day, graft->uri will always be an URI */
 
222
                        /* graft->uri = g_filename_to_uri (real_path, NULL, NULL); */
 
223
 
 
224
                        /* Make sure it's not one of the original grafts */
 
225
                        
 
226
                        grafts = g_slist_prepend (grafts, graft);
 
227
 
 
228
                        BRASERO_JOB_LOG (self, "Added file %s at %s", graft->uri, graft->path);
 
229
                }
 
230
 
 
231
                g_object_unref (info);
 
232
        }
 
233
        g_object_unref (enumerator);
 
234
 
 
235
        return grafts;
 
236
}
 
237
 
 
238
static gboolean
 
239
brasero_burn_uri_retrieve_path (BraseroBurnURI *self,
 
240
                                const gchar *uri,
 
241
                                gchar **path)
 
242
{
 
243
        GFile *file;
 
244
        GFileInfo *info;
 
245
        BraseroBurnURIPrivate *priv;
 
246
 
 
247
        priv = BRASERO_BURN_URI_PRIVATE (self);
 
248
 
 
249
        if (!uri)
 
250
                return FALSE;
 
251
 
 
252
        file = g_file_new_for_uri (uri);
 
253
        info = g_file_query_info (file,
 
254
                                  G_FILE_ATTRIBUTE_STANDARD_NAME ","
 
255
                                  G_FILE_ATTRIBUTE_STANDARD_TYPE ","
 
256
                                  "burn::backing-file",
 
257
                                  G_FILE_QUERY_INFO_NONE,
 
258
                                  priv->cancel,
 
259
                                  &priv->error);
 
260
 
 
261
        if (priv->error) {
 
262
                g_object_unref (file);
 
263
                return FALSE;
 
264
        }
 
265
 
 
266
        if (g_cancellable_is_cancelled (priv->cancel)) {
 
267
                g_object_unref (file);
 
268
                return FALSE;
 
269
        }
 
270
 
 
271
        if (!info) {
 
272
                /* Error */
 
273
                g_object_unref (file);
 
274
                g_object_unref (info);
 
275
                return FALSE;
 
276
        }
 
277
                
 
278
        if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
 
279
                *path = NULL;
 
280
        }
 
281
        else if (g_file_info_get_file_type (info) == G_FILE_TYPE_REGULAR
 
282
             /* NOTE: burn:// URI allows symlink */
 
283
             ||  g_file_info_get_file_type (info) == G_FILE_TYPE_SYMBOLIC_LINK) {
 
284
                const gchar *real_path;
 
285
 
 
286
                real_path = g_file_info_get_attribute_byte_string (info, "burn::backing-file");
 
287
                if (!real_path) {
 
288
                        priv->error = g_error_new (BRASERO_BURN_ERROR,
 
289
                                                   BRASERO_BURN_ERROR_GENERAL,
 
290
                                                   _("Impossible to retrieve local file path"));
 
291
                        g_object_unref (info);
 
292
                        g_object_unref (file);
 
293
                        return FALSE;
 
294
                }
 
295
 
 
296
                *path = g_strdup (real_path);
 
297
        }
 
298
 
 
299
        g_object_unref (file);
 
300
        g_object_unref (info);
 
301
        return TRUE;
 
302
}
 
303
 
 
304
static gpointer
 
305
brasero_burn_uri_thread (gpointer data)
 
306
{
 
307
        BraseroBurnURI *self = BRASERO_BURN_URI (data);
 
308
        BraseroTrack *current = NULL;
 
309
        BraseroBurnURIPrivate *priv;
 
310
        BraseroTrackData *track;
 
311
        GSList *excluded = NULL;
 
312
        GSList *grafts = NULL;
 
313
        guint64 num = 0;
 
314
        GSList *src;
 
315
 
 
316
        priv = BRASERO_BURN_URI_PRIVATE (self);
 
317
        brasero_job_set_current_action (BRASERO_JOB (self),
 
318
                                        BRASERO_BURN_ACTION_FILE_COPY,
 
319
                                        _("Copying files locally"),
 
320
                                        TRUE);
 
321
 
 
322
        brasero_job_get_current_track (BRASERO_JOB (self), &current);
 
323
 
 
324
        /* This is for IMAGE tracks */
 
325
        if (BRASERO_IS_TRACK_IMAGE (current)) {
 
326
                gchar *uri;
 
327
                gchar *path_toc;
 
328
                gchar *path_image;
 
329
                goffset blocks = 0;
 
330
                BraseroTrackImage *image;
 
331
 
 
332
                path_image = NULL;
 
333
                uri = brasero_track_image_get_source (BRASERO_TRACK_IMAGE (current), TRUE);
 
334
                if (!brasero_burn_uri_retrieve_path (self, uri, &path_image)) {
 
335
                        g_free (uri);
 
336
                        goto end;
 
337
                }
 
338
                g_free (uri);
 
339
 
 
340
                path_toc = NULL;
 
341
                uri = brasero_track_image_get_toc_source (BRASERO_TRACK_IMAGE (current), TRUE);
 
342
                if (uri) {
 
343
                        /* NOTE: if it's a .bin image there is not .toc file */
 
344
                        if (!brasero_burn_uri_retrieve_path (self, uri, &path_toc)) {
 
345
                                g_free (path_image);
 
346
                                g_free (uri);
 
347
                                goto end;
 
348
                        }
 
349
                        g_free (uri);
 
350
                }
 
351
 
 
352
                brasero_track_get_size (current, &blocks, NULL);
 
353
 
 
354
                image = brasero_track_image_new ();
 
355
                brasero_track_tag_copy_missing (BRASERO_TRACK (image), current);
 
356
                brasero_track_image_set_source (image,
 
357
                                                path_image,
 
358
                                                path_toc,
 
359
                                                brasero_track_image_get_format (BRASERO_TRACK_IMAGE (current)));
 
360
                brasero_track_image_set_block_num (image, blocks);
 
361
 
 
362
                priv->track = BRASERO_TRACK (image);
 
363
 
 
364
                g_free (path_toc);
 
365
                g_free (path_image);
 
366
                goto end;
 
367
        }
 
368
 
 
369
        /* This is for DATA tracks */
 
370
        for (src = brasero_track_data_get_grafts (BRASERO_TRACK_DATA (current)); src; src = src->next) {
 
371
                GFile *file;
 
372
                GFileInfo *info;
 
373
                BraseroGraftPt *graft;
 
374
 
 
375
                graft = src->data;
 
376
 
 
377
                if (!graft->uri) {
 
378
                        grafts = g_slist_prepend (grafts, brasero_graft_point_copy (graft));
 
379
                        continue;
 
380
                }
 
381
 
 
382
                if (!g_str_has_prefix (graft->uri, "burn://")) {
 
383
                        grafts = g_slist_prepend (grafts, brasero_graft_point_copy (graft));
 
384
                        continue;
 
385
                }
 
386
 
 
387
                BRASERO_JOB_LOG (self, "Information retrieval for %s", graft->uri);
 
388
 
 
389
                file = g_file_new_for_uri (graft->uri);
 
390
                info = g_file_query_info (file,
 
391
                                          G_FILE_ATTRIBUTE_STANDARD_NAME ","
 
392
                                          G_FILE_ATTRIBUTE_STANDARD_TYPE ","
 
393
                                          "burn::backing-file",
 
394
                                          G_FILE_QUERY_INFO_NONE,
 
395
                                          priv->cancel,
 
396
                                          &priv->error);
 
397
 
 
398
                if (priv->error) {
 
399
                        g_object_unref (file);
 
400
                        goto end;
 
401
                }
 
402
 
 
403
                if (g_cancellable_is_cancelled (priv->cancel)) {
 
404
                        g_object_unref (file);
 
405
                        goto end;
 
406
                }
 
407
 
 
408
                if (!info) {
 
409
                        /* Error */
 
410
                        g_object_unref (file);
 
411
                        g_object_unref (info);
 
412
                        goto end;
 
413
                }
 
414
 
 
415
                /* See if we were passed the burn:/// uri itself (the root).
 
416
                 * Then skip graft point addition */
 
417
                if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
 
418
                        if (g_file_info_get_name (info)
 
419
                        &&  strcmp (g_file_info_get_name (info), "/")) {
 
420
                                BraseroGraftPt *newgraft;
 
421
 
 
422
                                /* we need a dummy directory */
 
423
                                newgraft = g_new0 (BraseroGraftPt, 1);
 
424
                                newgraft->uri = NULL;
 
425
                                newgraft->path = g_strdup (graft->path);
 
426
                                grafts = g_slist_prepend (grafts, newgraft);
 
427
 
 
428
                                BRASERO_JOB_LOG (self,
 
429
                                                 "Adding directory %s at %s",
 
430
                                                 newgraft->uri,
 
431
                                                 newgraft->path);
 
432
                                grafts = brasero_burn_uri_explore_directory (self,
 
433
                                                                             grafts,
 
434
                                                                             file,
 
435
                                                                             newgraft->path,
 
436
                                                                             priv->cancel,
 
437
                                                                             &priv->error);
 
438
                        }
 
439
                        else {
 
440
                                BRASERO_JOB_LOG (self, "Directory is root");
 
441
                                grafts = brasero_burn_uri_explore_directory (self,
 
442
                                                                             grafts,
 
443
                                                                             file,
 
444
                                                                             "/",
 
445
                                                                             priv->cancel,
 
446
                                                                             &priv->error);
 
447
                        }
 
448
 
 
449
                        if (!grafts) {
 
450
                                g_object_unref (info);
 
451
                                g_object_unref (file);
 
452
                                goto end;
 
453
                        }
 
454
                }
 
455
                else if (g_file_info_get_file_type (info) == G_FILE_TYPE_REGULAR
 
456
                     /* NOTE: burn:// URI allows symlink */
 
457
                     ||  g_file_info_get_file_type (info) == G_FILE_TYPE_SYMBOLIC_LINK) {
 
458
                        const gchar *real_path;
 
459
                        BraseroGraftPt *newgraft;
 
460
 
 
461
                        real_path = g_file_info_get_attribute_byte_string (info, "burn::backing-file");
 
462
                        if (!real_path) {
 
463
                                priv->error = g_error_new (BRASERO_BURN_ERROR,
 
464
                                                           BRASERO_BURN_ERROR_GENERAL,
 
465
                                                           _("Impossible to retrieve local file path"));
 
466
 
 
467
                                g_slist_foreach (grafts, (GFunc) brasero_graft_point_free, NULL);
 
468
                                g_slist_free (grafts);
 
469
                                g_object_unref (info);
 
470
                                g_object_unref (file);
 
471
                                goto end;
 
472
                        }
 
473
 
 
474
                        newgraft = brasero_graft_point_copy (graft);
 
475
                        g_free (newgraft->uri);
 
476
 
 
477
                        newgraft->uri = g_strdup (real_path);
 
478
                        /* FIXME: maybe one day, graft->uri will always be an URI */
 
479
                        /* newgraft->uri = g_filename_to_uri (real_path, NULL, NULL); */
 
480
 
 
481
                        BRASERO_JOB_LOG (self,
 
482
                                         "Added file %s at %s",
 
483
                                         newgraft->uri,
 
484
                                         newgraft->path);
 
485
                        grafts = g_slist_prepend (grafts, newgraft);
 
486
                }
 
487
 
 
488
                g_object_unref (info);
 
489
                g_object_unref (file);
 
490
        }
 
491
        grafts = g_slist_reverse (grafts);
 
492
 
 
493
        /* remove all excluded starting by burn:// from the list */
 
494
        for (src = brasero_track_data_get_excluded (BRASERO_TRACK_DATA (current), FALSE); src; src = src->next) {
 
495
                gchar *uri;
 
496
 
 
497
                uri = src->data;
 
498
 
 
499
                if (uri && g_str_has_prefix (uri, "burn://"))
 
500
                        continue;
 
501
 
 
502
                uri = g_strdup (uri);
 
503
                excluded = g_slist_prepend (excluded, uri);
 
504
 
 
505
                BRASERO_JOB_LOG (self, "Added excluded file %s", uri);
 
506
        }
 
507
        excluded = g_slist_reverse (excluded);
 
508
 
 
509
        track = brasero_track_data_new ();
 
510
        brasero_track_tag_copy_missing (BRASERO_TRACK (track), current);
 
511
        
 
512
        brasero_track_data_add_fs (track, brasero_track_data_get_fs (BRASERO_TRACK_DATA (current)));
 
513
 
 
514
        brasero_track_data_get_file_num (BRASERO_TRACK_DATA (current), &num);
 
515
        brasero_track_data_set_file_num (track, num);
 
516
 
 
517
        brasero_track_data_set_source (track,
 
518
                                       grafts,
 
519
                                       excluded);
 
520
        priv->track = BRASERO_TRACK (track);
 
521
 
 
522
end:
 
523
 
 
524
        if (!g_cancellable_is_cancelled (priv->cancel))
 
525
                priv->thread_id = g_idle_add ((GSourceFunc) brasero_burn_uri_thread_finished, self);
 
526
 
 
527
        /* End thread */
 
528
        g_mutex_lock (priv->mutex);
 
529
        g_atomic_pointer_set (&priv->thread, NULL);
 
530
        g_cond_signal (priv->cond);
 
531
        g_mutex_unlock (priv->mutex);
 
532
 
 
533
        g_thread_exit (NULL);
 
534
 
 
535
        return NULL;
 
536
}
 
537
 
 
538
static BraseroBurnResult
 
539
brasero_burn_uri_start_thread (BraseroBurnURI *self,
 
540
                               GError **error)
 
541
{
 
542
        BraseroBurnURIPrivate *priv;
 
543
        GError *thread_error = NULL;
 
544
 
 
545
        priv = BRASERO_BURN_URI_PRIVATE (self);
 
546
 
 
547
        if (priv->thread)
 
548
                return BRASERO_BURN_RUNNING;
 
549
 
 
550
        priv->cancel = g_cancellable_new ();
 
551
 
 
552
        g_mutex_lock (priv->mutex);
 
553
        priv->thread = g_thread_create (brasero_burn_uri_thread,
 
554
                                        self,
 
555
                                        FALSE,
 
556
                                        &thread_error);
 
557
        g_mutex_unlock (priv->mutex);
 
558
 
 
559
        /* Reminder: this is not necessarily an error as the thread may have finished */
 
560
        //if (!priv->thread)
 
561
        //      return BRASERO_BURN_ERR;
 
562
        if (thread_error) {
 
563
                g_propagate_error (error, thread_error);
 
564
                return BRASERO_BURN_ERR;
 
565
        }
 
566
 
 
567
        return BRASERO_BURN_OK;
 
568
}
 
569
 
 
570
static BraseroBurnResult
 
571
brasero_burn_uri_start_if_found (BraseroBurnURI *self,
 
572
                                 const gchar *uri,
 
573
                                 GError **error)
 
574
{
 
575
        if (!uri)
 
576
                return BRASERO_BURN_NOT_RUNNING;
 
577
 
 
578
        /* Find any graft point with burn:// URI */
 
579
        if (!g_str_has_prefix (uri, "burn://"))
 
580
                return BRASERO_BURN_NOT_RUNNING;
 
581
 
 
582
        BRASERO_JOB_LOG (self, "burn:// URI found %s", uri);
 
583
        brasero_burn_uri_start_thread (self, error);
 
584
        return BRASERO_BURN_OK;
 
585
}
 
586
 
 
587
static BraseroBurnResult
 
588
brasero_burn_uri_start (BraseroJob *job,
 
589
                        GError **error)
 
590
{
 
591
        BraseroBurnURIPrivate *priv;
 
592
        BraseroBurnResult result;
 
593
        BraseroJobAction action;
 
594
        BraseroBurnURI *self;
 
595
        BraseroTrack *track;
 
596
        GSList *grafts;
 
597
        gchar *uri;
 
598
 
 
599
        self = BRASERO_BURN_URI (job);
 
600
        priv = BRASERO_BURN_URI_PRIVATE (self);
 
601
 
 
602
        /* skip that part */
 
603
        brasero_job_get_action (job, &action);
 
604
        if (action == BRASERO_JOB_ACTION_SIZE) {
 
605
                /* say we won't write to disc */
 
606
                brasero_job_set_output_size_for_current_track (job, 0, 0);
 
607
                return BRASERO_BURN_NOT_RUNNING;
 
608
        }
 
609
 
 
610
        if (action != BRASERO_JOB_ACTION_IMAGE)
 
611
                return BRASERO_BURN_NOT_SUPPORTED;
 
612
 
 
613
        /* can't be piped so brasero_job_get_current_track will work */
 
614
        brasero_job_get_current_track (job, &track);
 
615
 
 
616
        result = BRASERO_BURN_NOT_RUNNING;
 
617
 
 
618
        /* make a list of all non local uris to be downloaded and put them in a
 
619
         * list to avoid to download the same file twice. */
 
620
        if (BRASERO_IS_TRACK_DATA (track)) {
 
621
                /* we put all the non local graft point uris in the hash */
 
622
                grafts = brasero_track_data_get_grafts (BRASERO_TRACK_DATA (track));
 
623
                for (; grafts; grafts = grafts->next) {
 
624
                        BraseroGraftPt *graft;
 
625
 
 
626
                        graft = grafts->data;
 
627
                        result = brasero_burn_uri_start_if_found (self, graft->uri, error);
 
628
                        if (result != BRASERO_BURN_NOT_RUNNING)
 
629
                                break;
 
630
                }
 
631
        }
 
632
        else if (BRASERO_IS_TRACK_IMAGE (track)) {
 
633
                /* NOTE: don't delete URI as they will be inserted in hash */
 
634
                uri = brasero_track_image_get_source (BRASERO_TRACK_IMAGE (track), TRUE);
 
635
                result = brasero_burn_uri_start_if_found (self, uri, error);
 
636
                g_free (uri);
 
637
 
 
638
                if (result == BRASERO_BURN_NOT_RUNNING) {
 
639
                        uri = brasero_track_image_get_toc_source (BRASERO_TRACK_IMAGE (track), TRUE);
 
640
                        result = brasero_burn_uri_start_if_found (self, uri, error);
 
641
                        g_free (uri);
 
642
                }
 
643
        }
 
644
        else
 
645
                BRASERO_JOB_NOT_SUPPORTED (self);
 
646
 
 
647
        if (!priv->thread)
 
648
                BRASERO_JOB_LOG (self, "no burn:// URI found");
 
649
 
 
650
        return result;
 
651
}
 
652
 
 
653
static BraseroBurnResult
 
654
brasero_burn_uri_stop (BraseroJob *job,
 
655
                       GError **error)
 
656
{
 
657
        BraseroBurnURIPrivate *priv = BRASERO_BURN_URI_PRIVATE (job);
 
658
 
 
659
        if (priv->cancel) {
 
660
                /* signal that we've been cancelled */
 
661
                g_cancellable_cancel (priv->cancel);
 
662
        }
 
663
 
 
664
        g_mutex_lock (priv->mutex);
 
665
        if (priv->thread)
 
666
                g_cond_wait (priv->cond, priv->mutex);
 
667
        g_mutex_unlock (priv->mutex);
 
668
 
 
669
        if (priv->cancel) {
 
670
                /* unref it after the thread has stopped */
 
671
                g_object_unref (priv->cancel);
 
672
                priv->cancel = NULL;
 
673
        }
 
674
 
 
675
        if (priv->thread_id) {
 
676
                g_source_remove (priv->thread_id);
 
677
                priv->thread_id = 0;
 
678
        }
 
679
 
 
680
        if (priv->error) {
 
681
                g_error_free (priv->error);
 
682
                priv->error = NULL;
 
683
        }
 
684
 
 
685
        return BRASERO_BURN_OK;
 
686
}
 
687
 
 
688
static void
 
689
brasero_burn_uri_finalize (GObject *object)
 
690
{
 
691
        BraseroBurnURIPrivate *priv = BRASERO_BURN_URI_PRIVATE (object);
 
692
 
 
693
        if (priv->mutex) {
 
694
                g_mutex_free (priv->mutex);
 
695
                priv->mutex = NULL;
 
696
        }
 
697
 
 
698
        if (priv->cond) {
 
699
                g_cond_free (priv->cond);
 
700
                priv->cond = NULL;
 
701
        }
 
702
 
 
703
        G_OBJECT_CLASS (parent_class)->finalize (object);
 
704
}
 
705
 
 
706
static void
 
707
brasero_burn_uri_class_init (BraseroBurnURIClass *klass)
 
708
{
 
709
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
710
        BraseroJobClass *job_class = BRASERO_JOB_CLASS (klass);
 
711
 
 
712
        g_type_class_add_private (klass, sizeof (BraseroBurnURIPrivate));
 
713
 
 
714
        parent_class = g_type_class_peek_parent (klass);
 
715
        object_class->finalize = brasero_burn_uri_finalize;
 
716
 
 
717
        job_class->start = brasero_burn_uri_start;
 
718
        job_class->stop = brasero_burn_uri_stop;
 
719
}
 
720
 
 
721
static void
 
722
brasero_burn_uri_init (BraseroBurnURI *obj)
 
723
{
 
724
        BraseroBurnURIPrivate *priv = BRASERO_BURN_URI_PRIVATE (obj);
 
725
 
 
726
        priv->mutex = g_mutex_new ();
 
727
        priv->cond = g_cond_new ();
 
728
}
 
729
 
 
730
static BraseroBurnResult
 
731
brasero_burn_uri_export_caps (BraseroPlugin *plugin, gchar **error)
 
732
{
 
733
        GSList *caps;
 
734
 
 
735
        brasero_plugin_define (plugin,
 
736
                               /* Translators: this is the name of the plugin
 
737
                                * which will be translated only when it needs
 
738
                                * displaying. */
 
739
                               N_("CD/DVD Creator Folder"),
 
740
                               _("Allows to burn files added to \"CD/DVD Creator Folder\" in Nautilus"),
 
741
                               "Philippe Rouquier",
 
742
                               11);
 
743
 
 
744
        caps = brasero_caps_image_new (BRASERO_PLUGIN_IO_ACCEPT_FILE,
 
745
                                       BRASERO_IMAGE_FORMAT_ANY);
 
746
        brasero_plugin_process_caps (plugin, caps);
 
747
        g_slist_free (caps);
 
748
 
 
749
        caps = brasero_caps_data_new (BRASERO_IMAGE_FS_ANY);
 
750
        brasero_plugin_process_caps (plugin, caps);
 
751
        g_slist_free (caps);
 
752
 
 
753
        brasero_plugin_set_process_flags (plugin, BRASERO_PLUGIN_RUN_PREPROCESSING);
 
754
 
 
755
        return BRASERO_BURN_OK;
 
756
}