~ubuntu-branches/ubuntu/saucy/xmms2/saucy-proposed

« back to all changes in this revision

Viewing changes to src/clients/vistest/ripper.c

  • Committer: Bazaar Package Importer
  • Author(s): Florian Ragwitz
  • Date: 2009-05-02 08:31:32 UTC
  • mto: (1.1.6 upstream) (6.1.3 sid)
  • mto: This revision was merged to the branch mainline in revision 23.
  • Revision ID: james.westby@ubuntu.com-20090502083132-y0ulwiqbk4lxfd4z
ImportĀ upstreamĀ versionĀ 0.6DrMattDestruction

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/********************************************************************
 
2
 
 
3
Derived from work with the following disclamer below:
 
4
 
 
5
 
 
6
Copyright (c) 2002-2004 Xiph.org Foundation
 
7
 
 
8
Redistribution and use in source and binary forms, with or without
 
9
modification, are permitted provided that the following conditions
 
10
are met:
 
11
 
 
12
- Redistributions of source code must retain the above copyright
 
13
notice, this list of conditions and the following disclaimer.
 
14
 
 
15
- Redistributions in binary form must reproduce the above copyright
 
16
notice, this list of conditions and the following disclaimer in the
 
17
documentation and/or other materials provided with the distribution.
 
18
 
 
19
- Neither the name of the Xiph.org Foundation nor the names of its
 
20
contributors may be used to endorse or promote products derived from
 
21
this software without specific prior written permission.
 
22
 
 
23
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
24
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
25
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 
26
A PARTICULAR PURPOSE ARE DISCLAIMED.    IN NO EVENT SHALL THE FOUNDATION
 
27
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
28
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
29
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
30
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
31
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
32
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
33
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
34
 
 
35
 ********************************************************************/
 
36
 
 
37
 
 
38
/* Note that this is POSIX, not ANSI, code */
 
39
 
 
40
#include <stdio.h>
 
41
#include <stdlib.h>
 
42
#include <string.h>
 
43
#include <signal.h>
 
44
#include <time.h>
 
45
#include <math.h>
 
46
#include <vorbis/vorbisenc.h>
 
47
 
 
48
#ifdef _WIN32 /* We need the following two to set stdout to binary */
 
49
#include <io.h>
 
50
#include <fcntl.h>
 
51
#endif
 
52
 
 
53
#if defined(__MACOS__) && defined(__MWERKS__)
 
54
#include <console.h>                    /* CodeWarrior's Mac "command-line" support */
 
55
#endif
 
56
#include <xmmsclient/xmmsclient.h>
 
57
 
 
58
#define x_exit(msg) \
 
59
        printf ("Error: %s\n", msg); \
 
60
        exit (EXIT_FAILURE);
 
61
 
 
62
#define READ 512
 
63
signed char readbuffer[READ*4]; /* out of the data segment, not the stack */
 
64
 
 
65
/* XMMS2 */
 
66
xmmsc_connection_t *x_connection;
 
67
int x_vis;
 
68
int intr = 0;
 
69
 
 
70
void
 
71
quit (int signum)
 
72
{
 
73
        intr = 1;
 
74
}
 
75
 
 
76
void
 
77
xmms2_quit ()
 
78
{
 
79
        xmmsc_visualization_shutdown (x_connection, x_vis);
 
80
        if (x_connection) {
 
81
                xmmsc_unref (x_connection);
 
82
        }
 
83
}
 
84
 
 
85
void xmms2_init ()
 
86
{
 
87
        xmmsc_result_t *res;
 
88
        char *path = getenv ("XMMS_PATH");
 
89
        xmmsv_t *cfg;
 
90
 
 
91
        x_connection = xmmsc_init ("xmms2-ripper");
 
92
 
 
93
        if (!x_connection || !xmmsc_connect (x_connection, path)){
 
94
                printf ("%s\n", xmmsc_get_last_error (x_connection));
 
95
                x_exit ("couldn't connect to xmms2d!");
 
96
        }
 
97
 
 
98
        res = xmmsc_visualization_init (x_connection);
 
99
        xmmsc_result_wait (res);
 
100
        if (xmmsc_result_iserror (res)) {
 
101
                puts (xmmsc_result_get_error (res));
 
102
                exit (EXIT_FAILURE);
 
103
        }
 
104
        x_vis = xmmsc_visualization_init_handle (res);
 
105
 
 
106
        cfg = xmmsv_build_dict (XMMSV_DICT_ENTRY_STR ("type", "pcm"),
 
107
                                XMMSV_DICT_ENTRY_STR ("stereo", "1"),
 
108
                                XMMSV_DICT_ENTRY_STR ("pcm.hardwire", "1"),
 
109
                                XMMSV_DICT_END);
 
110
 
 
111
        res = xmmsc_visualization_properties_set (x_connection, x_vis, cfg);
 
112
        xmmsc_result_wait (res);
 
113
        if (xmmsc_result_iserror (res)) {
 
114
                x_exit (xmmsc_result_get_error (res));
 
115
        }
 
116
        xmmsc_result_unref (res);
 
117
 
 
118
        while (!xmmsc_visualization_started (x_connection, x_vis)) {
 
119
                res = xmmsc_visualization_start (x_connection, x_vis);
 
120
                if (xmmsc_visualization_errored (x_connection, x_vis)) {
 
121
                        printf ("Couldn't start visualization transfer: %s\n",
 
122
                                xmmsc_get_last_error (x_connection));
 
123
                        exit (EXIT_FAILURE);
 
124
                }
 
125
                if (res) {
 
126
                        xmmsc_result_wait (res);
 
127
                        xmmsc_visualization_start_handle (x_connection, res);
 
128
                        xmmsc_result_unref (res);
 
129
                }
 
130
        }
 
131
 
 
132
        atexit (xmms2_quit);
 
133
}
 
134
 
 
135
int main ()
 
136
{
 
137
        ogg_stream_state os; /* take physical pages, weld into a logical
 
138
                                                                                                        stream of packets */
 
139
        ogg_page         og; /* one Ogg bitstream page. Vorbis packets are inside */
 
140
        ogg_packet       op; /* one raw packet of data for decode */
 
141
 
 
142
        vorbis_info      vi; /* struct that stores all the static vorbis bitstream
 
143
                                                                                                        settings */
 
144
        vorbis_comment   vc; /* struct that stores all the user comments */
 
145
 
 
146
        vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
 
147
        vorbis_block     vb; /* local working space for packet->PCM decode */
 
148
 
 
149
        struct sigaction siga;
 
150
        int eos = 0, ret;
 
151
        char stat = '-';
 
152
        int stats;
 
153
 
 
154
#if defined(macintosh) && defined(__MWERKS__)
 
155
        int argc = 0;
 
156
        char **argv = NULL;
 
157
        argc = ccommand (&argv); /* get a "command line" from the Mac user */
 
158
#endif
 
159
 
 
160
#ifdef _WIN32 /* We need to set stdout to binary mode. Damn windows. */
 
161
        /* if we were writing a file, it would also need to in
 
162
                 binary mode, eg, fopen("file.wav","wb"); */
 
163
        _setmode (_fileno (stdout), _O_BINARY);
 
164
#endif
 
165
 
 
166
        siga.sa_handler = quit;
 
167
        sigemptyset (&siga.sa_mask);
 
168
        siga.sa_flags = SA_RESTART;
 
169
 
 
170
        /********** Init xmms2 **************/
 
171
        xmms2_init ();
 
172
 
 
173
        /********** Encode setup ************/
 
174
 
 
175
        vorbis_info_init (&vi);
 
176
 
 
177
        /* TODO: command line quality setting */
 
178
        ret = vorbis_encode_init_vbr (&vi, 2, 44100, 0.4);
 
179
        if (ret) {
 
180
                x_exit ("Setting up vorbis format failed!");
 
181
        }
 
182
 
 
183
        /* add a comment */
 
184
        vorbis_comment_init (&vc);
 
185
        vorbis_comment_add_tag (&vc, "ENCODER", "xmms2");
 
186
 
 
187
        /* set up the analysis state and auxiliary encoding storage */
 
188
        vorbis_analysis_init (&vd, &vi);
 
189
        vorbis_block_init (&vd, &vb);
 
190
 
 
191
        /* set up our packet->stream encoder */
 
192
        /* pick a random serial number; that way we can more likely build
 
193
                 chained streams just by concatenation */
 
194
        srand (time (NULL));
 
195
        ogg_stream_init (&os, rand ());
 
196
 
 
197
        /* Vorbis streams begin with three headers; the initial header (with
 
198
                 most of the codec setup parameters) which is mandated by the Ogg
 
199
                 bitstream spec.        The second header holds any comment fields.     The
 
200
                 third header holds the bitstream codebook.     We merely need to
 
201
                 make the headers, then pass them to libvorbis one at a time;
 
202
                 libvorbis handles the additional Ogg bitstream constraints */
 
203
        {
 
204
                ogg_packet header;
 
205
                ogg_packet header_comm;
 
206
                ogg_packet header_code;
 
207
 
 
208
                vorbis_analysis_headerout (&vd, &vc, &header, &header_comm, &header_code);
 
209
                ogg_stream_packetin (&os, &header); /* automatically placed in its own
 
210
                                             page */
 
211
                ogg_stream_packetin (&os, &header_comm);
 
212
                ogg_stream_packetin (&os, &header_code);
 
213
 
 
214
        /* This ensures the actual
 
215
         * audio data will start on a new page, as per spec
 
216
         */
 
217
                while (1) {
 
218
                        int result = ogg_stream_flush (&os, &og);
 
219
                        if (!result) {
 
220
                                break;
 
221
                        }
 
222
                        fwrite (og.header, 1, og.header_len, stdout);
 
223
                        fwrite (og.body, 1, og.body_len, stdout);
 
224
                }
 
225
        }
 
226
 
 
227
        sigaction(SIGINT, &siga, (struct sigaction*)NULL);
 
228
 
 
229
        fprintf (stderr, "Ready to encode...  ");
 
230
        stats = -1;
 
231
        while (!eos) {
 
232
                long i;
 
233
                long bytes = xmmsc_visualization_chunk_get (x_connection, x_vis, (short*)readbuffer, -1, 1000) * sizeof(short);
 
234
                if (bytes == 0) {
 
235
                        continue;
 
236
                }
 
237
                if (bytes < 0 || intr) {
 
238
                        /*       Tell the library we're at end of stream so that it can handle
 
239
                                 the last frame and mark end of stream in the output properly */
 
240
                        vorbis_analysis_wrote (&vd, 0);
 
241
                        eos = 1;
 
242
                } else {
 
243
                        if (stats == -1) {
 
244
                                fprintf (stderr, "\rEncoding:  ");
 
245
                        }
 
246
                        /* data to encode */
 
247
                        if (++stats == 10) {
 
248
                                fprintf (stderr, "\b%c", stat);
 
249
                                switch (stat) {
 
250
                                        case '-':  stat = '\\'; break;
 
251
                                        case '\\': stat = '|'; break;
 
252
                                        case '|':  stat = '/'; break;
 
253
                                        default:   stat = '-'; break;
 
254
                                }
 
255
                                stats = 0;
 
256
                        }
 
257
 
 
258
                        /* expose the buffer to submit data */
 
259
                        float **buffer = vorbis_analysis_buffer (&vd, READ);
 
260
 
 
261
                        /* uninterleave samples */
 
262
                        for (i = 0; i < bytes/4; i++) {
 
263
                                buffer[0][i] = ((readbuffer[i*4+1] << 8) |
 
264
                                                    (0x00ff & (int)readbuffer[i*4]))
 
265
                                                /32768.f;
 
266
                                buffer[1][i] = ((readbuffer[i*4+3] << 8) |
 
267
                                                    (0x00ff & (int)readbuffer[i*4+2]))
 
268
                                                /32768.f;
 
269
                        }
 
270
 
 
271
                        /* tell the library how much we actually submitted */
 
272
                        vorbis_analysis_wrote (&vd, i);
 
273
                }
 
274
 
 
275
                /* vorbis does some data preanalysis, then divvies up blocks for
 
276
                         more involved (potentially parallel) processing. Get a single
 
277
                         block for encoding now */
 
278
                while (vorbis_analysis_blockout (&vd, &vb) == 1) {
 
279
 
 
280
                        /* analysis, assume we want to use bitrate management */
 
281
                        vorbis_analysis (&vb, NULL);
 
282
                        vorbis_bitrate_addblock (&vb);
 
283
 
 
284
                        while (vorbis_bitrate_flushpacket (&vd, &op)) {
 
285
 
 
286
                                /* weld the packet into the bitstream */
 
287
                                ogg_stream_packetin (&os, &op);
 
288
 
 
289
                                /* write out pages (if any) */
 
290
                                while (!ogg_page_eos (&og)) {
 
291
                                        int result = ogg_stream_pageout (&os, &og);
 
292
                                        if (result == 0) {
 
293
                                                break;
 
294
                                        }
 
295
                                        fwrite (og.header, 1, og.header_len, stdout);
 
296
                                        fwrite (og.body, 1, og.body_len, stdout);
 
297
                                }
 
298
                        }
 
299
                }
 
300
        }
 
301
 
 
302
        /* clean up and exit.   vorbis_info_clear () must be called last */
 
303
 
 
304
        ogg_stream_clear (&os);
 
305
        vorbis_block_clear (&vb);
 
306
        vorbis_dsp_clear (&vd);
 
307
        vorbis_comment_clear (&vc);
 
308
        vorbis_info_clear (&vi);
 
309
 
 
310
        /* ogg_page and ogg_packet structs always point to storage in
 
311
                 libvorbis.     They're never freed or manipulated directly */
 
312
 
 
313
        fprintf (stderr, "\rDone.           \n");
 
314
        return (0);
 
315
}