1 /* EasyTAG - tag editor for audio files
2 * Copyright (C) 2014 David King <amigadave@amigadave.com>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 51
16 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 #include "flac_private.h"
20
21 #ifdef ENABLE_FLAC
22
23 #include <errno.h>
24 #include <unistd.h>
25
26 size_t
et_flac_read_func(void * ptr,size_t size,size_t nmemb,FLAC__IOHandle handle)27 et_flac_read_func (void *ptr,
28 size_t size,
29 size_t nmemb,
30 FLAC__IOHandle handle)
31 {
32 EtFlacReadState *state;
33 gssize bytes_read;
34
35 state = (EtFlacReadState *)handle;
36
37 state->eof = FALSE;
38
39 bytes_read = g_input_stream_read (G_INPUT_STREAM (state->istream), ptr,
40 size * nmemb, NULL, &state->error);
41
42 if (bytes_read == -1)
43 {
44 errno = EIO;
45 return 0;
46 }
47 else if (bytes_read == 0)
48 {
49 state->eof = TRUE;
50 }
51
52 return bytes_read;
53 }
54
55 size_t
et_flac_write_func(const void * ptr,size_t size,size_t nmemb,FLAC__IOHandle handle)56 et_flac_write_func (const void *ptr,
57 size_t size,
58 size_t nmemb,
59 FLAC__IOHandle handle)
60 {
61 EtFlacWriteState *state;
62 gsize bytes_written;
63
64 state = (EtFlacWriteState *)handle;
65
66 if (!g_output_stream_write_all (G_OUTPUT_STREAM (state->ostream), ptr,
67 size * nmemb, &bytes_written, NULL,
68 &state->error))
69 {
70 g_debug ("Only %" G_GSIZE_FORMAT " bytes out of %" G_GSIZE_FORMAT
71 " bytes of data were written", bytes_written,
72 size);
73 errno = EIO;
74 }
75
76 return bytes_written;
77 }
78
79 int
et_flac_seek_func(FLAC__IOHandle handle,FLAC__int64 offset,int whence)80 et_flac_seek_func (FLAC__IOHandle handle,
81 FLAC__int64 offset,
82 int whence)
83 {
84 GSeekType seektype;
85 EtFlacReadState *state;
86
87 state = (EtFlacReadState *)handle;
88
89 if (!g_seekable_can_seek (state->seekable))
90 {
91 errno = EBADF;
92 return -1;
93 }
94 else
95 {
96 switch (whence)
97 {
98 case SEEK_SET:
99 seektype = G_SEEK_SET;
100 break;
101 case SEEK_CUR:
102 seektype = G_SEEK_CUR;
103 break;
104 case SEEK_END:
105 seektype = G_SEEK_END;
106 break;
107 default:
108 errno = EINVAL;
109 return -1;
110 }
111
112 if (g_seekable_seek (state->seekable, offset, seektype, NULL,
113 &state->error))
114 {
115 return 0;
116 }
117 else
118 {
119 /* TODO: More suitable error. */
120 errno = EINVAL;
121 return -1;
122 }
123 }
124 }
125
126 FLAC__int64
et_flac_tell_func(FLAC__IOHandle handle)127 et_flac_tell_func (FLAC__IOHandle handle)
128 {
129 EtFlacReadState *state;
130
131 state = (EtFlacReadState *)handle;
132
133 if (!g_seekable_can_seek (state->seekable))
134 {
135 errno = EBADF;
136 return -1;
137 }
138 else
139 {
140 return g_seekable_tell (state->seekable);
141 }
142 }
143
144 int
et_flac_eof_func(FLAC__IOHandle handle)145 et_flac_eof_func (FLAC__IOHandle handle)
146 {
147 EtFlacReadState *state;
148
149 state = (EtFlacReadState *)handle;
150
151 /* EOF is not directly supported by GFileInputStream. */
152 return state->eof ? 1 : 0;
153 }
154
155 int
et_flac_read_close_func(FLAC__IOHandle handle)156 et_flac_read_close_func (FLAC__IOHandle handle)
157 {
158 EtFlacReadState *state;
159
160 state = (EtFlacReadState *)handle;
161
162 g_clear_object (&state->istream);
163 g_clear_error (&state->error);
164
165 /* Always return success. */
166 return 0;
167 }
168
169 int
et_flac_write_close_func(FLAC__IOHandle handle)170 et_flac_write_close_func (FLAC__IOHandle handle)
171 {
172 EtFlacWriteState *state;
173
174 state = (EtFlacWriteState *)handle;
175
176 g_clear_object (&state->file);
177 g_clear_object (&state->iostream);
178 g_clear_error (&state->error);
179
180 /* Always return success. */
181 return 0;
182 }
183
184 #endif /* ENABLE_FLAC */
185