1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
3
* Copyright (C) 2012 Jonathan Matthew
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, or (at your option)
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.
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.
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.
30
#include <glib/gi18n.h>
32
#include <gst/cdda/gstcddabasesrc.h>
35
#include "rb-audiocd-info.h"
38
read_gst_disc_info (RBAudioCDInfo *info, GError **error)
50
source = gst_element_make_from_uri (GST_URI_SRC, "cdda://", NULL);
52
/* if cdparanoiasrc wasn't in base and installed by default
53
* everywhere, plugin install might be worth trying here.
55
g_set_error_literal (error,
57
GST_CORE_ERROR_MISSING_PLUGIN,
58
_("Could not find a GStreamer CD source plugin"));
62
g_object_set (source, "device", info->device, NULL);
63
pipeline = gst_pipeline_new (NULL);
64
sink = gst_element_factory_make ("fakesink", NULL);
65
gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL);
66
gst_element_link (source, sink);
68
if (g_object_class_find_property (G_OBJECT_GET_CLASS (source), "paranoia-mode"))
69
g_object_set (source, "paranoia-mode", 0, NULL);
71
gst_element_set_state (pipeline, GST_STATE_PAUSED);
73
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
75
while (done == FALSE) {
79
msg = gst_bus_timed_pop (bus, 3 * GST_SECOND);
83
switch (GST_MESSAGE_TYPE (msg)) {
85
gst_message_parse_tag (msg, &tags);
87
gst_tag_list_get_string (tags,
88
GST_TAG_CDDA_MUSICBRAINZ_DISCID,
89
&info->musicbrainz_disc_id);
90
gst_tag_list_get_string (tags,
91
GST_TAG_CDDA_MUSICBRAINZ_DISCID_FULL,
92
&info->musicbrainz_full_disc_id);
94
gst_tag_list_free (tags);
97
case GST_MESSAGE_STATE_CHANGED:
98
if (GST_MESSAGE_SRC (msg) == GST_OBJECT (pipeline)) {
103
gst_message_parse_state_changed (msg, &oldstate, &newstate, &pending);
104
if (newstate == GST_STATE_PAUSED && pending == GST_STATE_VOID_PENDING)
108
case GST_MESSAGE_ERROR:
109
gst_message_parse_error (msg, error, NULL);
116
gst_message_unref (msg);
119
if (*error == NULL) {
120
format = gst_format_get_by_nick ("track");
122
gst_element_query_duration (source, &out_format, &num_tracks);
123
info->num_tracks = num_tracks;
125
info->tracks = g_new0 (RBAudioCDTrack, num_tracks);
126
for (i = 0; i < num_tracks; i++) {
127
RBAudioCDTrack *track = &info->tracks[i];
128
GstCddaBaseSrcTrack *gst_track = &GST_CDDA_BASE_SRC (source)->tracks[i];
129
guint64 duration = 0;
131
track->is_audio = gst_track->is_audio;
132
track->track_num = gst_track->num;
134
gst_tag_list_get_uint64 (gst_track->tags, GST_TAG_DURATION, &duration);
135
track->duration = (duration / GST_MSECOND);
139
gst_element_set_state (pipeline, GST_STATE_NULL);
140
gst_object_unref (bus);
141
gst_object_unref (pipeline);
142
return (*error == NULL);
146
read_gvfs_disc_info (RBAudioCDInfo *info)
150
GFileEnumerator *tracks;
155
dev = g_path_get_basename (info->device);
156
uri = g_strdup_printf ("cdda://%s", dev);
159
cdda = g_file_new_for_uri (uri);
162
fileinfo = g_file_query_info (cdda, "xattr::*", G_FILE_QUERY_INFO_NONE, NULL, NULL);
163
if (fileinfo == NULL) {
164
g_object_unref (cdda);
168
attr = g_file_info_get_attribute_string (fileinfo, "xattr::org.gnome.audio.title");
170
info->album = g_strdup (attr);
172
attr = g_file_info_get_attribute_string (fileinfo, "xattr::org.gnome.audio.artist");
174
info->album_artist = g_strdup (attr);
176
attr = g_file_info_get_attribute_string (fileinfo, "xattr::org.gnome.audio.genre");
178
info->genre = g_strdup (attr);
181
tracks = g_file_enumerate_children (cdda, G_FILE_ATTRIBUTE_STANDARD_NAME ",xattr::*", G_FILE_QUERY_INFO_NONE, NULL, NULL);
182
if (tracks != NULL) {
183
for (fileinfo = g_file_enumerator_next_file (tracks, NULL, NULL);
185
fileinfo = g_file_enumerator_next_file (tracks, NULL, NULL)) {
190
name = g_file_info_get_name (fileinfo);
191
if (name == NULL || sscanf (name, "Track %d.wav", &track_num) != 1) {
195
if (track_num < 1 || track_num > info->num_tracks) {
198
g_assert (track_num == info->tracks[track_num-1].track_num);
200
attr = g_file_info_get_attribute_string (fileinfo, "xattr::org.gnome.audio.title");
202
info->tracks[track_num - 1].title = g_strdup (attr);
204
attr = g_file_info_get_attribute_string (fileinfo, "xattr::org.gnome.audio.artist");
206
info->tracks[track_num - 1].artist = g_strdup (attr);
210
g_object_unref (tracks);
212
g_object_unref (cdda);
216
audiocd_info_thread (GSimpleAsyncResult *result, GObject *object, GCancellable *cancellable)
219
GError *error = NULL;
221
info = g_simple_async_result_get_op_res_gpointer (result);
223
if (read_gst_disc_info (info, &error)) {
224
read_gvfs_disc_info (info);
226
rb_audiocd_info_free (info);
227
g_simple_async_result_set_op_res_gpointer (result, NULL, NULL);
228
g_simple_async_result_take_error (result, error);
233
rb_audiocd_info_free (RBAudioCDInfo *info)
237
g_free (info->device);
238
g_free (info->musicbrainz_disc_id);
239
g_free (info->musicbrainz_full_disc_id);
240
g_free (info->album);
241
g_free (info->genre);
242
g_free (info->album_artist);
244
for (i = 0; i < info->num_tracks; i++) {
245
g_free (info->tracks[i].artist);
246
g_free (info->tracks[i].title);
248
g_free (info->tracks);
253
rb_audiocd_info_get (const char *device,
254
GCancellable *cancellable,
255
GAsyncReadyCallback callback,
258
GSimpleAsyncResult *result;
261
result = g_simple_async_result_new (NULL, callback, user_data, rb_audiocd_info_get);
262
g_simple_async_result_set_check_cancellable (result, cancellable);
264
info = g_new0 (RBAudioCDInfo, 1);
265
info->device = g_strdup (device);
266
g_simple_async_result_set_op_res_gpointer (result, info, NULL);
268
g_simple_async_result_run_in_thread (result, audiocd_info_thread, G_PRIORITY_DEFAULT, cancellable);
272
rb_audiocd_info_finish (GAsyncResult *result,
275
g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL, rb_audiocd_info_get),
277
if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
280
return g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));