Random work from the last mounth...
[dictix.git] / libdictix / dix-tag-writer.c
blobf538a261eccd525db66eae492671fbcb00ec82f4
1 /**
2 * Dictix / DixTagWriter - dix-tag-writer.c
4 * Copyright (C) Martin Blanchard 2011 <tinram@gmx.fr>
6 * This program 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.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <glib.h>
29 #include <glib/gi18n.h>
30 #include <gio/gio.h>
31 #include <gst/gst.h>
32 #include <gst/pbutils/pbutils.h>
34 #include "dix-tag-writer.h"
36 enum {
37 PROP_0,
38 PROP_FILE_URI
41 struct _DixTagWriterPrivate
43 gchar *uri;
45 GstBus *bus;
47 GstTagList *tags;
50 #define DIX_TAG_WRITER_GET_PRIVATE(obj) \
51 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), DIX_TYPE_TAG_WRITER, DixTagWriterPrivate))
53 G_DEFINE_TYPE (DixTagWriter, dix_tag_writer, GST_TYPE_PIPELINE)
55 static void
56 dix_tag_writer_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
58 DixTagWriter *writer = (DixTagWriter *) object;
59 DixTagWriterPrivate *priv = writer->priv;
61 switch (prop_id) {
62 case PROP_FILE_URI:
63 priv->uri = g_strdup (g_value_get_string (value));
65 break;
66 default:
67 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
71 static void
72 dix_tag_writer_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
74 DixTagWriter *writer = (DixTagWriter *) object;
75 DixTagWriterPrivate *priv = writer->priv;
77 switch (prop_id) {
78 case PROP_FILE_URI:
79 g_value_set_string (value, priv->uri);
81 break;
82 default:
83 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
87 static void
88 dix_tag_writer_finalize (GObject *object)
90 DixTagWriter *writer = (DixTagWriter *) object;
91 DixTagWriterPrivate *priv = writer->priv;
93 g_free (priv->uri);
94 priv->uri = NULL;
96 if (priv->tags != NULL) {
97 gst_tag_list_free (priv->tags);
99 priv->tags = NULL;
101 G_OBJECT_CLASS (dix_tag_writer_parent_class)->finalize (object);
104 static void
105 dix_tag_writer_class_init (DixTagWriterClass* klass)
107 GObjectClass *gobject_class = (GObjectClass *) klass;
109 gobject_class->set_property = dix_tag_writer_set_property;
110 gobject_class->get_property = dix_tag_writer_get_property;
111 gobject_class->finalize = dix_tag_writer_finalize;
113 g_object_class_install_property (gobject_class,
114 PROP_FILE_URI,
115 g_param_spec_string ("file-uri",
116 "FLAC audio file uri",
117 "Uri of the flac audio file we're about to write to",
118 NULL,
119 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
121 g_type_class_add_private (gobject_class, sizeof (DixTagWriterPrivate));
124 static void
125 dix_tag_writer_init (DixTagWriter* writer)
127 DixTagWriterPrivate *priv = DIX_TAG_WRITER_GET_PRIVATE (writer);
128 writer->priv = priv;
130 gst_object_set_name (GST_OBJECT(writer), "DictixTagWriter");
132 priv->uri = NULL;
134 priv->tags = gst_tag_list_new ();
137 DixTagWriter*
138 dix_tag_writer_new (const gchar* uri)
140 g_return_val_if_fail ((uri != NULL), NULL);
141 if (g_str_has_suffix (uri, ".flac") == FALSE) {
142 g_warning ("TagWriter only support FLAC audio file.\n");
144 return NULL;
147 return g_object_new (DIX_TYPE_TAG_WRITER, "file-uri", uri, NULL);
150 void
151 dix_tag_writer_save (DixTagWriter *writer)
153 g_return_if_fail (DIX_IS_TAG_WRITER (writer));
154 DixTagWriterPrivate *priv = writer->priv;
155 GError *error = NULL;
156 gchar *filename = NULL;
157 gchar *path = NULL;
158 gchar *basename = NULL;
159 gchar *hidden = NULL;
160 GstElement *source = NULL;
161 GstElement *decoder = NULL;
162 GstElement *setter = NULL;
163 GstElement *sink = NULL;
164 GFile *file = NULL;
165 GOutputStream *stream = NULL;
166 gboolean done = FALSE;
167 GstMessage *message;
168 GFile *old = NULL;
169 GFile *new = NULL;
171 if (G_UNLIKELY (priv->uri == NULL)) {
172 g_warning ("No file specified...\n");
174 return;
177 if (priv->tags == NULL) {
178 return;
181 filename = g_filename_from_uri (priv->uri, NULL, NULL);
182 path = g_path_get_dirname (filename);
183 basename = g_path_get_basename (filename);
184 hidden = g_build_filename (path,
185 g_strconcat (".", basename, NULL),
186 NULL);
188 file = g_file_new_for_path (hidden);
189 stream = G_OUTPUT_STREAM (g_file_create (file,
190 G_FILE_CREATE_PRIVATE,
191 NULL,
192 &error));
193 if (error != NULL) {
194 g_warning ("%s\n", error->message);
196 return;
199 if (G_LIKELY (priv->bus == NULL)) {
200 source = gst_element_factory_make ("giosrc", "DictixTagWriterSource");
201 if (source == NULL) {
202 return;
204 g_object_set (G_OBJECT (source), "location", priv->uri, NULL);
205 gst_bin_add (GST_BIN (writer), source);
207 decoder = gst_element_factory_make ("flacdec", "DictixTagWriterDecoder");
208 if (decoder == NULL) {
209 gst_object_unref (source);
211 return;
213 gst_bin_add (GST_BIN (writer), decoder);
214 gst_element_link (source, decoder);
216 setter = gst_element_factory_make ("flactag", "DictixTagWriterSetter");
217 if (setter == NULL) {
218 gst_object_unref (source);
219 gst_object_unref (decoder);
221 return;
223 gst_bin_add (GST_BIN (writer), setter);
224 gst_element_link (decoder, setter);
226 sink = gst_element_factory_make ("giostreamsink", "DictixTagWriterSink");
227 if (sink == NULL) {
228 gst_object_unref (source);
229 gst_object_unref (decoder);
230 gst_object_unref (setter);
232 return;
234 gst_bin_add (GST_BIN (writer), sink);
235 gst_element_link (setter, sink);
237 priv->bus = gst_element_get_bus (GST_ELEMENT (writer));
240 g_object_set (sink, "stream", G_OUTPUT_STREAM (stream), NULL);
242 gst_tag_setter_merge_tags (GST_TAG_SETTER (setter),
243 priv->tags,
244 GST_TAG_MERGE_REPLACE);
246 gst_element_set_state (GST_ELEMENT (writer), GST_STATE_PLAYING);
248 while (done) {
249 message = gst_bus_timed_pop (priv->bus, GST_CLOCK_TIME_NONE);
251 switch (GST_MESSAGE_TYPE (message)) {
252 case GST_MESSAGE_ERROR: {
253 /* TODO: Handle that... */
255 break;
256 } case GST_MESSAGE_EOS: {
257 done = TRUE;
259 break;
260 } default : {
261 break;
265 gst_message_unref (message);
268 gst_element_set_state (GST_ELEMENT (writer), GST_STATE_NULL);
270 g_output_stream_close (stream, NULL, NULL);
271 g_object_unref (stream);
273 old = g_file_new_for_uri (priv->uri);
274 new = g_file_new_for_path (hidden);
276 g_file_copy_attributes (old,
277 new,
278 G_FILE_COPY_ALL_METADATA,
279 NULL,
280 NULL);
281 g_file_move (new,
282 old,
283 G_FILE_COPY_OVERWRITE,
284 NULL,
285 NULL,
286 NULL,
287 &error);
289 g_free (filename);
290 g_free (path);
291 g_free (basename);
292 g_free (hidden);
295 void
296 dix_tag_writer_set_title (DixTagWriter *writer, const gchar *title)
298 g_return_if_fail (DIX_IS_TAG_WRITER (writer));
299 g_return_if_fail (title != NULL);
300 DixTagWriterPrivate *priv = writer->priv;
302 if (G_UNLIKELY (priv->bus != NULL)) {
303 return;
306 if (! g_utf8_validate (title, -1, NULL)) {
307 g_warning ("Title should be an valid utf8 string");
309 return;
312 gst_tag_list_add (priv->tags,
313 GST_TAG_MERGE_REPLACE_ALL,
314 GST_TAG_TITLE,
315 g_strdup (title),
316 NULL);