~ubuntu-branches/ubuntu/utopic/mpd/utopic-proposed

« back to all changes in this revision

Viewing changes to src/EncoderPlugin.hxx

  • Committer: Package Import Robot
  • Author(s): Steve Kowalik
  • Date: 2013-11-12 18:17:40 UTC
  • mfrom: (2.2.36 sid)
  • Revision ID: package-import@ubuntu.com-20131112181740-72aa4zihehoobedp
Tags: 0.18.3-1ubuntu1
* Merge from Debian unstable.  Remaining changes:
  - Add libmp3lame-dev to Build-Depends, and enable LAME.
  - Read the user for the daemon from the config file in the init script.
  - Move avahi-daemon from Suggests to Recommends.
  - Added apport hook to include user configuration file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2003-2013 The Music Player Daemon Project
 
3
 * http://www.musicpd.org
 
4
 *
 
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 of the License, or
 
8
 * (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License along
 
16
 * with this program; if not, write to the Free Software Foundation, Inc.,
 
17
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
18
 */
 
19
 
 
20
#ifndef MPD_ENCODER_PLUGIN_HXX
 
21
#define MPD_ENCODER_PLUGIN_HXX
 
22
 
 
23
#include <assert.h>
 
24
#include <stdbool.h>
 
25
#include <stddef.h>
 
26
 
 
27
struct EncoderPlugin;
 
28
struct AudioFormat;
 
29
struct config_param;
 
30
struct Tag;
 
31
class Error;
 
32
 
 
33
struct Encoder {
 
34
        const EncoderPlugin &plugin;
 
35
 
 
36
#ifndef NDEBUG
 
37
        bool open, pre_tag, tag, end;
 
38
#endif
 
39
 
 
40
        explicit Encoder(const EncoderPlugin &_plugin)
 
41
                :plugin(_plugin)
 
42
#ifndef NDEBUG
 
43
                , open(false)
 
44
#endif
 
45
        {}
 
46
};
 
47
 
 
48
struct EncoderPlugin {
 
49
        const char *name;
 
50
 
 
51
        Encoder *(*init)(const config_param &param,
 
52
                         Error &error);
 
53
 
 
54
        void (*finish)(Encoder *encoder);
 
55
 
 
56
        bool (*open)(Encoder *encoder,
 
57
                     AudioFormat &audio_format,
 
58
                     Error &error);
 
59
 
 
60
        void (*close)(Encoder *encoder);
 
61
 
 
62
        bool (*end)(Encoder *encoder, Error &error);
 
63
 
 
64
        bool (*flush)(Encoder *encoder, Error &error);
 
65
 
 
66
        bool (*pre_tag)(Encoder *encoder, Error &error);
 
67
 
 
68
        bool (*tag)(Encoder *encoder, const Tag *tag,
 
69
                    Error &error);
 
70
 
 
71
        bool (*write)(Encoder *encoder,
 
72
                      const void *data, size_t length,
 
73
                      Error &error);
 
74
 
 
75
        size_t (*read)(Encoder *encoder, void *dest, size_t length);
 
76
 
 
77
        const char *(*get_mime_type)(Encoder *encoder);
 
78
};
 
79
 
 
80
/**
 
81
 * Creates a new encoder object.
 
82
 *
 
83
 * @param plugin the encoder plugin
 
84
 * @param param optional configuration
 
85
 * @param error location to store the error occurring, or nullptr to ignore errors.
 
86
 * @return an encoder object on success, nullptr on failure
 
87
 */
 
88
static inline Encoder *
 
89
encoder_init(const EncoderPlugin &plugin, const config_param &param,
 
90
             Error &error_r)
 
91
{
 
92
        return plugin.init(param, error_r);
 
93
}
 
94
 
 
95
/**
 
96
 * Frees an encoder object.
 
97
 *
 
98
 * @param encoder the encoder
 
99
 */
 
100
static inline void
 
101
encoder_finish(Encoder *encoder)
 
102
{
 
103
        assert(!encoder->open);
 
104
 
 
105
        encoder->plugin.finish(encoder);
 
106
}
 
107
 
 
108
/**
 
109
 * Opens an encoder object.  You must call this prior to using it.
 
110
 * Before you free it, you must call encoder_close().  You may open
 
111
 * and close (reuse) one encoder any number of times.
 
112
 *
 
113
 * After this function returns successfully and before the first
 
114
 * encoder_write() call, you should invoke encoder_read() to obtain
 
115
 * the file header.
 
116
 *
 
117
 * @param encoder the encoder
 
118
 * @param audio_format the encoder's input audio format; the plugin
 
119
 * may modify the struct to adapt it to its abilities
 
120
 * @return true on success
 
121
 */
 
122
static inline bool
 
123
encoder_open(Encoder *encoder, AudioFormat &audio_format,
 
124
             Error &error)
 
125
{
 
126
        assert(!encoder->open);
 
127
 
 
128
        bool success = encoder->plugin.open(encoder, audio_format, error);
 
129
#ifndef NDEBUG
 
130
        encoder->open = success;
 
131
        encoder->pre_tag = encoder->tag = encoder->end = false;
 
132
#endif
 
133
        return success;
 
134
}
 
135
 
 
136
/**
 
137
 * Closes an encoder object.  This disables the encoder, and readies
 
138
 * it for reusal by calling encoder_open() again.
 
139
 *
 
140
 * @param encoder the encoder
 
141
 */
 
142
static inline void
 
143
encoder_close(Encoder *encoder)
 
144
{
 
145
        assert(encoder->open);
 
146
 
 
147
        if (encoder->plugin.close != nullptr)
 
148
                encoder->plugin.close(encoder);
 
149
 
 
150
#ifndef NDEBUG
 
151
        encoder->open = false;
 
152
#endif
 
153
}
 
154
 
 
155
/**
 
156
 * Ends the stream: flushes the encoder object, generate an
 
157
 * end-of-stream marker (if applicable), make everything which might
 
158
 * currently be buffered available by encoder_read().
 
159
 *
 
160
 * After this function has been called, the encoder may not be usable
 
161
 * for more data, and only encoder_read() and encoder_close() can be
 
162
 * called.
 
163
 *
 
164
 * @param encoder the encoder
 
165
 * @return true on success
 
166
 */
 
167
static inline bool
 
168
encoder_end(Encoder *encoder, Error &error)
 
169
{
 
170
        assert(encoder->open);
 
171
        assert(!encoder->end);
 
172
 
 
173
#ifndef NDEBUG
 
174
        encoder->end = true;
 
175
#endif
 
176
 
 
177
        /* this method is optional */
 
178
        return encoder->plugin.end != nullptr
 
179
                ? encoder->plugin.end(encoder, error)
 
180
                : true;
 
181
}
 
182
 
 
183
/**
 
184
 * Flushes an encoder object, make everything which might currently be
 
185
 * buffered available by encoder_read().
 
186
 *
 
187
 * @param encoder the encoder
 
188
 * @return true on success
 
189
 */
 
190
static inline bool
 
191
encoder_flush(Encoder *encoder, Error &error)
 
192
{
 
193
        assert(encoder->open);
 
194
        assert(!encoder->pre_tag);
 
195
        assert(!encoder->tag);
 
196
        assert(!encoder->end);
 
197
 
 
198
        /* this method is optional */
 
199
        return encoder->plugin.flush != nullptr
 
200
                ? encoder->plugin.flush(encoder, error)
 
201
                : true;
 
202
}
 
203
 
 
204
/**
 
205
 * Prepare for sending a tag to the encoder.  This is used by some
 
206
 * encoders to flush the previous sub-stream, in preparation to begin
 
207
 * a new one.
 
208
 *
 
209
 * @param encoder the encoder
 
210
 * @param tag the tag object
 
211
 * @return true on success
 
212
 */
 
213
static inline bool
 
214
encoder_pre_tag(Encoder *encoder, Error &error)
 
215
{
 
216
        assert(encoder->open);
 
217
        assert(!encoder->pre_tag);
 
218
        assert(!encoder->tag);
 
219
        assert(!encoder->end);
 
220
 
 
221
        /* this method is optional */
 
222
        bool success = encoder->plugin.pre_tag != nullptr
 
223
                ? encoder->plugin.pre_tag(encoder, error)
 
224
                : true;
 
225
 
 
226
#ifndef NDEBUG
 
227
        encoder->pre_tag = success;
 
228
#endif
 
229
        return success;
 
230
}
 
231
 
 
232
/**
 
233
 * Sends a tag to the encoder.
 
234
 *
 
235
 * Instructions: call encoder_pre_tag(); then obtain flushed data with
 
236
 * encoder_read(); finally call encoder_tag().
 
237
 *
 
238
 * @param encoder the encoder
 
239
 * @param tag the tag object
 
240
 * @return true on success
 
241
 */
 
242
static inline bool
 
243
encoder_tag(Encoder *encoder, const Tag *tag, Error &error)
 
244
{
 
245
        assert(encoder->open);
 
246
        assert(!encoder->pre_tag);
 
247
        assert(encoder->tag);
 
248
        assert(!encoder->end);
 
249
 
 
250
#ifndef NDEBUG
 
251
        encoder->tag = false;
 
252
#endif
 
253
 
 
254
        /* this method is optional */
 
255
        return encoder->plugin.tag != nullptr
 
256
                ? encoder->plugin.tag(encoder, tag, error)
 
257
                : true;
 
258
}
 
259
 
 
260
/**
 
261
 * Writes raw PCM data to the encoder.
 
262
 *
 
263
 * @param encoder the encoder
 
264
 * @param data the buffer containing PCM samples
 
265
 * @param length the length of the buffer in bytes
 
266
 * @return true on success
 
267
 */
 
268
static inline bool
 
269
encoder_write(Encoder *encoder, const void *data, size_t length,
 
270
              Error &error)
 
271
{
 
272
        assert(encoder->open);
 
273
        assert(!encoder->pre_tag);
 
274
        assert(!encoder->tag);
 
275
        assert(!encoder->end);
 
276
 
 
277
        return encoder->plugin.write(encoder, data, length, error);
 
278
}
 
279
 
 
280
/**
 
281
 * Reads encoded data from the encoder.
 
282
 *
 
283
 * Call this repeatedly until no more data is returned.
 
284
 *
 
285
 * @param encoder the encoder
 
286
 * @param dest the destination buffer to copy to
 
287
 * @param length the maximum length of the destination buffer
 
288
 * @return the number of bytes written to #dest
 
289
 */
 
290
static inline size_t
 
291
encoder_read(Encoder *encoder, void *dest, size_t length)
 
292
{
 
293
        assert(encoder->open);
 
294
        assert(!encoder->pre_tag || !encoder->tag);
 
295
 
 
296
#ifndef NDEBUG
 
297
        if (encoder->pre_tag) {
 
298
                encoder->pre_tag = false;
 
299
                encoder->tag = true;
 
300
        }
 
301
#endif
 
302
 
 
303
        return encoder->plugin.read(encoder, dest, length);
 
304
}
 
305
 
 
306
/**
 
307
 * Get mime type of encoded content.
 
308
 *
 
309
 * @param plugin the encoder plugin
 
310
 * @return an constant string, nullptr on failure
 
311
 */
 
312
static inline const char *
 
313
encoder_get_mime_type(Encoder *encoder)
 
314
{
 
315
        /* this method is optional */
 
316
        return encoder->plugin.get_mime_type != nullptr
 
317
                ? encoder->plugin.get_mime_type(encoder)
 
318
                : nullptr;
 
319
}
 
320
 
 
321
#endif