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