1 /* flac.c
2 * Copyright (C) 2004, 2005 Sylvain Cresto <scresto@gmail.com>
3 *
4 * This file is part of graveman!
5 *
6 * graveman! 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, or
9 * (at your option) any later version.
10 *
11 * graveman! 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 GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with program; see the file COPYING. If not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
19 * MA 02111-1307, USA.
20 *
21 * URL: http://www.nongnu.org/graveman/
22 *
23 */
24
25 #include "graveman.h"
26
27 #ifdef ENABLE_FLAC
28 #include <FLAC/metadata.h>
29
30 #define FLAC_ERROR_OPEN "An error occurred opening the input file"
31 #define FLAC_ERROR "ERROR"
32
33 /* extraction de la duree d'un fichier flac */
getFlacInfo(gchar * Afilename,guint32 * Alength,GError ** Aerror)34 gboolean getFlacInfo(gchar *Afilename, guint32 *Alength, GError **Aerror)
35 {
36 FLAC__StreamMetadata *Lblock;
37 FLAC__Metadata_Chain *Lchain = FLAC__metadata_chain_new();
38 FLAC__Metadata_Iterator *Literator = FLAC__metadata_iterator_new();
39
40 (*Alength)=0;
41
42 if (! Lchain) {
43 g_set_error(Aerror, GRAVEMAN_ERROR, _ERR_OUTOFMEMORY, _("FLAC: out of memory !"));
44 return FALSE;
45 }
46
47 if(!FLAC__metadata_chain_read(Lchain, Afilename)) {
48 g_set_error(Aerror, GRAVEMAN_ERROR, _ERR_INAPPROPRIATE_DATA, _("%s is not a valid .flac file !"), Afilename);
49 return FALSE;
50 }
51
52 FLAC__metadata_iterator_init(Literator, Lchain);
53 Lblock = FLAC__metadata_iterator_get_block(Literator);
54
55 if (Lblock->data.stream_info.sample_rate) {
56 (*Alength) = Lblock->data.stream_info.total_samples / Lblock->data.stream_info.sample_rate;
57 }
58
59 FLAC__metadata_iterator_delete(Literator);
60 FLAC__metadata_chain_delete(Lchain);
61
62 return TRUE;
63 }
64
65
66 /* transformation fichier son vers piste audio */
67
68 /* pour le moment on ne fais pas grand chose dans le callback ...
69 * plus tard il y aura une meilleur gestion des erreurs ! */
flac_callback(GIOChannel * Astd,GIOCondition Acond,gpointer Adata)70 gboolean flac_callback(GIOChannel *Astd, GIOCondition Acond, gpointer Adata)
71 {
72 GIOStatus Lstatus;
73 Tgrave *Lg = (Tgrave *)Adata;
74 gchar *Lbuffer = NULL;
75 gchar *s;
76 gint *Lcont = (gint *) sc_grave_get_data(Lg, "cont"); /* on traite encore des donnees ? */
77 GError **Lerreur = (GError **) sc_grave_get_data(Lg, "gerror"); /* pointeur erreur */
78
79
80 /* fin du callback lorsque l'on recoi un signal comme quoi le pipe est ferme */
81 if (Acond == G_IO_HUP || Acond == G_IO_ERR) {
82 *Lcont = 1;
83 return FALSE;
84 }
85
86 Lstatus = g_io_channel_read_line(Astd, &Lbuffer, NULL, NULL, NULL);
87 _DEB("%s\n", Lbuffer);
88 if (Lbuffer) {
89 if (!strncmp(Lbuffer, FLAC_ERROR_OPEN, strlen(FLAC_ERROR_OPEN))) {
90 g_set_error(Lerreur, GRAVEMAN_ERROR, _ERR_FLAC, _("An error occurred opening the input FLAC file, disk full ?"));
91 g_free(Lbuffer);
92 return FALSE;
93 } else if (strstr(Lbuffer, FLAC_ERROR)) {
94 g_set_error(Lerreur, GRAVEMAN_ERROR, _ERR_FLAC, s+strlen(FLAC_ERROR));
95 g_free(Lbuffer);
96 return FALSE;
97 }
98 }
99
100 g_free(Lbuffer);
101
102 return TRUE;
103 }
104
FlacToWav(Tgrave * Ag,gchar * AFichier,gchar * AVers,GError ** Aerror)105 gboolean FlacToWav(Tgrave *Ag, gchar *AFichier, gchar *AVers, GError **Aerror)
106 {
107 gchar *Lcommandline;
108 gchar **Lcmd;
109 gint *Lpid = (gint *) sc_grave_get_data(Ag, "pid");
110 gboolean *Labort = (gboolean *)sc_grave_get_data(Ag, "gabort");
111 gint *Lcont = (gint *) sc_grave_get_data(Ag, "cont");
112 gint g_out, g_err, Lnbrarg;
113 gchar *Lfic;
114 gchar *Lvers;
115 GIOChannel *Lcom, *Lcomerr;
116 GIOStatus Lstatus;
117 gboolean Lbolstatus;
118 guint Lcomevent, Lcomerrevent;
119
120 Lfic = sc_strescape(AFichier);
121 Lvers = sc_strescape(AVers);
122 Lcommandline = g_strdup_printf("%s %s -d \"%s\" -o \"%s\"", conf_get_string("flac"), conf_get_string("flacpara"), Lfic, Lvers);
123 g_free(Lvers); g_free(Lfic);
124 _DEB("execution [%s]\n", Lcommandline);
125
126 Lstatus = g_shell_parse_argv(Lcommandline, &Lnbrarg, &Lcmd, Aerror);
127 g_free(Lcommandline);
128 if (Lstatus == FALSE) {
129 return FALSE;
130 }
131
132 Lbolstatus = g_spawn_async_with_pipes(NULL, Lcmd, NULL, /* env argument */
133 (GSpawnFlags ) (G_SPAWN_DO_NOT_REAP_CHILD),
134 NULL, NULL, Lpid, NULL, &g_out, &g_err, Aerror);
135 g_strfreev(Lcmd);
136
137 if (Lbolstatus == FALSE) {
138 g_warning("ERROR EXECUTION !\n");
139 return FALSE;
140 }
141 Lcom = g_io_channel_unix_new( g_out );
142 g_io_channel_set_encoding (Lcom, NULL, NULL);
143 g_io_channel_set_flags( Lcom, G_IO_FLAG_NONBLOCK, NULL );
144 Lcomevent = g_io_add_watch (Lcom, (G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI),
145 flac_callback,
146 Ag);
147
148 Lcomerr = g_io_channel_unix_new( g_err );
149 g_io_channel_set_encoding (Lcomerr, NULL, NULL);
150 g_io_channel_set_flags( Lcomerr, G_IO_FLAG_NONBLOCK, NULL );
151 Lcomerrevent = g_io_add_watch (Lcomerr, (G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI),
152 flac_callback,
153 Ag);
154
155 while (*Lcont > 1 && *Labort == FALSE) {
156 gtk_main_iteration();
157 }
158 exit_prog(*Lpid, *Labort, Aerror, NULL);
159
160 g_source_remove(Lcomerrevent);
161 g_source_remove(Lcomevent);
162
163 g_io_channel_shutdown(Lcomerr, FALSE, NULL);
164 g_io_channel_unref(Lcomerr);
165 g_io_channel_shutdown(Lcom, FALSE, NULL);
166 g_io_channel_unref(Lcom);
167 g_spawn_close_pid(*Lpid);
168 *Lpid = 0;
169
170 /* l'utilisateur a annule l'operation */
171 if (*Labort==TRUE || *Aerror) return FALSE;
172
173 return TRUE;
174 }
175
176 #endif
177
178 /*
179 * vim:et:ts=8:sts=2:sw=2
180 */
181