~ubuntu-branches/ubuntu/lucid/mpg123/lucid

« back to all changes in this revision

Viewing changes to control_generic.c

Tags: upstream-0.60
ImportĀ upstreamĀ versionĀ 0.60

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
2
 
/*
3
 
 * Control interface to generic front ends.
4
 
 * written/copyrights 1997/99 by Andreas Neuhaus (and Michael Hipp)
5
 
 */
6
 
 
7
 
#include <stdio.h>
8
 
#include <stdlib.h>
9
 
#include <stdarg.h>
10
 
#include <sys/time.h>
11
 
#include <sys/types.h>
12
 
#include <sys/wait.h>
13
 
#include <unistd.h>
14
 
#include <fcntl.h>
15
 
#include <errno.h>
16
 
 
17
 
#include <sys/socket.h>
18
 
 
19
 
#include "mpg123.h"
20
 
 
21
 
#define MODE_STOPPED 0
22
 
#define MODE_PLAYING 1
23
 
#define MODE_PAUSED 2
24
 
 
25
 
extern struct audio_info_struct ai;
26
 
extern int buffer_pid;
27
 
extern int tabsel_123[2][3][16];
28
 
 
29
 
void generic_sendmsg (char *fmt, ...)
30
 
{
31
 
        va_list ap;
32
 
        printf("@");
33
 
        va_start(ap, fmt);
34
 
        vprintf(fmt, ap);
35
 
        va_end(ap);
36
 
        printf("\n");
37
 
}
38
 
 
39
 
static double compute_bpf (struct frame *fr)
40
 
{
41
 
        double bpf;
42
 
        switch(fr->lay) {
43
 
                case 1:
44
 
                        bpf = tabsel_123[fr->lsf][0][fr->bitrate_index];
45
 
                        bpf *= 12000.0 * 4.0;
46
 
                        bpf /= freqs[fr->sampling_frequency] << (fr->lsf);
47
 
                        break;
48
 
                case 2:
49
 
                case 3:
50
 
                        bpf = tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index];
51
 
                        bpf *= 144000;
52
 
                        bpf /= freqs[fr->sampling_frequency] << (fr->lsf);
53
 
                        break;
54
 
                default:
55
 
                        bpf = 1.0;
56
 
        }
57
 
        return bpf;
58
 
}
59
 
 
60
 
static double compute_tpf (struct frame *fr)
61
 
{
62
 
        static int bs[4] = { 0, 384, 1152, 1152 };
63
 
        double tpf;
64
 
 
65
 
        tpf = (double) bs[fr->lay];
66
 
        tpf /= freqs[fr->sampling_frequency] << (fr->lsf);
67
 
        return tpf;
68
 
}
69
 
 
70
 
void generic_sendstat (struct frame *fr, int no)
71
 
{
72
 
        long buffsize;
73
 
        double bpf, tpf, tim1, tim2;
74
 
        double dt = 0;
75
 
        int sno, rno;
76
 
 
77
 
        /* this and the 2 above functions are taken from common.c.
78
 
        / maybe the compute_* functions shouldn't be static there
79
 
        / so that they can also used here (performance problems?).
80
 
        / isn't there an easier way to compute the time? */
81
 
 
82
 
        buffsize = xfermem_get_usedspace(buffermem);
83
 
        if (!rd || !fr)
84
 
                return;
85
 
        bpf = compute_bpf(fr);
86
 
        tpf = compute_tpf(fr);
87
 
        if (buffsize > 0 && ai.rate > 0 && ai.channels > 0) {
88
 
                dt = (double) buffsize / ai.rate / ai.channels;
89
 
                if ((ai.format & AUDIO_FORMAT_MASK) == AUDIO_FORMAT_16)
90
 
                        dt *= .5;
91
 
        }
92
 
        rno = 0;
93
 
        sno = no;
94
 
        if (rd->filelen >= 0) {
95
 
                long t = rd->tell(rd);
96
 
                rno = (int)((double)(rd->filelen-t)/bpf);
97
 
                sno = (int)((double)t/bpf);
98
 
        }
99
 
        tim1 = sno * tpf - dt;
100
 
        tim2 = rno * tpf + dt;
101
 
 
102
 
        generic_sendmsg("F %d %d %3.2f %3.2f", sno, rno, tim1, tim2);
103
 
}
104
 
 
105
 
extern char *genre_table[];
106
 
extern int genre_count;
107
 
void generic_sendinfoid3 (char *buf)
108
 
{
109
 
        char info[200] = "", *c;
110
 
        int i;
111
 
        unsigned char genre;
112
 
        for (i=0, c=buf+3; i<124; i++, c++)
113
 
                info[i] = *c ? *c : ' ';
114
 
        info[i] = 0;
115
 
        genre = *c;
116
 
        generic_sendmsg("I ID3:%s%s", info, (genre<=genre_count) ? genre_table[genre] : "Unknown");
117
 
}
118
 
 
119
 
void generic_sendinfo (char *filename)
120
 
{
121
 
        char *s, *t;
122
 
        s = strrchr(filename, '/');
123
 
        if (!s)
124
 
                s = filename;
125
 
        else
126
 
                s++;
127
 
        t = strrchr(s, '.');
128
 
        if (t)
129
 
                *t = 0;
130
 
        generic_sendmsg("I %s", s);
131
 
}
132
 
 
133
 
void control_generic (struct frame *fr)
134
 
{
135
 
        struct timeval tv;
136
 
        fd_set fds;
137
 
        int n;
138
 
        int mode = MODE_STOPPED;
139
 
        int init = 0;
140
 
        int framecnt = 0;
141
 
 
142
 
        setlinebuf(stdout);
143
 
        printf("@R MPG123\n");
144
 
        while (1) {
145
 
                tv.tv_sec = 0;
146
 
                tv.tv_usec = 0;
147
 
                FD_ZERO(&fds);
148
 
                FD_SET(STDIN_FILENO, &fds);
149
 
 
150
 
                /* play frame if no command needs to be processed */
151
 
                if (mode == MODE_PLAYING) {
152
 
                        n = select(32, &fds, NULL, NULL, &tv);
153
 
                        if (n == 0) {
154
 
                                if (!read_frame(fr)) {
155
 
                                        mode = MODE_STOPPED;
156
 
                                        rd->close(rd);
157
 
                                        generic_sendmsg("P 0");
158
 
                                        continue;
159
 
                                }
160
 
                                play_frame(init,fr);
161
 
                                if (init) {
162
 
                                        static char *modes[4] = {"Stereo", "Joint-Stereo", "Dual-Channel", "Single-Channel"};
163
 
                                        generic_sendmsg("S %s %d %ld %s %d %d %d %d %d %d %d %d",
164
 
                                                fr->mpeg25 ? "2.5" : (fr->lsf ? "2.0" : "1.0"),
165
 
                                                fr->lay,
166
 
                                                freqs[fr->sampling_frequency],
167
 
                                                modes[fr->mode],
168
 
                                                fr->mode_ext,
169
 
                                                fr->framesize+4,
170
 
                                                fr->stereo,
171
 
                                                fr->copyright ? 1 : 0,
172
 
                                                fr->error_protection ? 1 : 0,
173
 
                                                fr->emphasis,
174
 
                                                tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index],
175
 
                                                fr->extension);
176
 
                                        init = 0;
177
 
                                }
178
 
                                framecnt++;
179
 
                                generic_sendstat(fr, framecnt);
180
 
                        }
181
 
                }
182
 
                else {
183
 
                        /* wait for command */
184
 
                        while (1) {
185
 
                                n = select(32, &fds, NULL, NULL, NULL);
186
 
                                if (n > 0)
187
 
                                        break;
188
 
                        }
189
 
                }
190
 
 
191
 
                /* exit on error */
192
 
                if (n < 0) {
193
 
                        fprintf(stderr, "Error waiting for command: %s\n", strerror(errno));
194
 
                        exit(1);
195
 
                }
196
 
 
197
 
                /* process command */
198
 
                if (n > 0) {
199
 
                        int len;
200
 
                        char buf[1024];
201
 
                        char *cmd;
202
 
 
203
 
                        /* read command */
204
 
                        len = read(STDIN_FILENO, buf, sizeof(buf)-1);
205
 
                        buf[len] = 0;
206
 
 
207
 
                        /* exit on error */
208
 
                        if (len < 0) {
209
 
                                fprintf(stderr, "Error reading command: %s\n", strerror(errno));
210
 
                                exit(1);
211
 
                        }
212
 
 
213
 
                        /* strip CR/LF at EOL */
214
 
                        while (len>0 && (buf[strlen(buf)-1] == '\n' || buf[strlen(buf)-1] == '\r')) {
215
 
                                buf[strlen(buf)-1] = 0;
216
 
                                len--;
217
 
                        }
218
 
 
219
 
                        /* continue if no command */
220
 
                        if (len == 0)
221
 
                                continue;
222
 
                        cmd = strtok(buf, " \t");
223
 
                        if (!cmd || !strlen(cmd))
224
 
                                continue;
225
 
 
226
 
                        /* QUIT */
227
 
                        if (!strcasecmp(cmd, "Q") || !strcasecmp(cmd, "QUIT"))
228
 
                                break;
229
 
 
230
 
                        /* LOAD */
231
 
                        if (!strcasecmp(cmd, "L") || !strcasecmp(cmd, "LOAD")) {
232
 
                                char *filename;
233
 
                                filename = strtok(NULL, "");
234
 
                                if (mode != MODE_STOPPED) {
235
 
                                        rd->close(rd);
236
 
                                        mode = MODE_STOPPED;
237
 
                                }
238
 
                                open_stream(filename, -1);
239
 
                                if (rd && rd->flags & READER_ID3TAG)
240
 
                                        generic_sendinfoid3((char *)rd->id3buf);
241
 
                                else
242
 
                                        generic_sendinfo(filename);
243
 
                                mode = MODE_PLAYING;
244
 
                                init = 1;
245
 
                                framecnt = 0;
246
 
                                read_frame_init();
247
 
                                continue;
248
 
                        }
249
 
 
250
 
                        /* STOP */
251
 
                        if (!strcasecmp(cmd, "S") || !strcasecmp(cmd, "STOP")) {
252
 
                                if (mode != MODE_STOPPED) {
253
 
                                        rd->close(rd);
254
 
                                        mode = MODE_STOPPED;
255
 
                                        generic_sendmsg("P 0");
256
 
                                }
257
 
                                continue;
258
 
                        }
259
 
 
260
 
                        /* PAUSE */
261
 
                        if (!strcasecmp(cmd, "P") || !strcasecmp(cmd, "PAUSE")) {
262
 
                                if (mode == MODE_STOPPED)
263
 
                                        continue;
264
 
                                if (mode == MODE_PLAYING) {
265
 
                                        mode = MODE_PAUSED;
266
 
                                        if (param.usebuffer)
267
 
                                                kill(buffer_pid, SIGSTOP);
268
 
                                        generic_sendmsg("P 1");
269
 
                                } else {
270
 
                                        mode = MODE_PLAYING;
271
 
                                        if (param.usebuffer)
272
 
                                                kill(buffer_pid, SIGCONT);
273
 
                                        generic_sendmsg("P 2");
274
 
                                }
275
 
                                continue;
276
 
                        }
277
 
 
278
 
                        /* JUMP */
279
 
                        if (!strcasecmp(cmd, "J") || !strcasecmp(cmd, "JUMP")) {
280
 
                                char *spos;
281
 
                                int pos, ok;
282
 
 
283
 
                                spos = strtok(NULL, " \t");
284
 
                                if (!spos)
285
 
                                        continue;
286
 
                                if (spos[0] == '-')
287
 
                                        pos = framecnt + atoi(spos);
288
 
                                else if (spos[0] == '+')
289
 
                                        pos = framecnt + atoi(spos+1);
290
 
                                else
291
 
                                        pos = atoi(spos);
292
 
 
293
 
                                if (mode == MODE_STOPPED)
294
 
                                        continue;
295
 
                                ok = 1;
296
 
                                if (pos < framecnt) {
297
 
                                        rd->rewind(rd);
298
 
                                        read_frame_init();
299
 
                                        for (framecnt=0; ok && framecnt<pos; framecnt++) {
300
 
                                                ok = read_frame(fr);
301
 
                                                if (fr->lay == 3)
302
 
                                                        set_pointer(512);
303
 
                                        }
304
 
                                } else {
305
 
                                        for (; ok && framecnt<pos; framecnt++) {
306
 
                                                ok = read_frame(fr);
307
 
                                                if (fr->lay == 3)
308
 
                                                        set_pointer(512);
309
 
                                        }
310
 
                                }
311
 
                                continue;
312
 
                        }
313
 
 
314
 
                        /* unknown command */
315
 
                        generic_sendmsg("E Unknown command '%s'", cmd);
316
 
 
317
 
                }
318
 
        }
319
 
 
320
 
        /* quit gracefully */
321
 
        if (param.usebuffer) {
322
 
                kill(buffer_pid, SIGINT);
323
 
                xfermem_done_writer(buffermem);
324
 
                waitpid(buffer_pid, NULL, 0);
325
 
                xfermem_done(buffermem);
326
 
        } else {
327
 
                audio_flush(param.outmode, &ai);
328
 
                free(pcm_sample);
329
 
        }
330
 
        if (param.outmode == DECODE_AUDIO)
331
 
                audio_close(&ai);
332
 
        if (param.outmode == DECODE_WAV)
333
 
                wav_close();
334
 
        exit(0);
335
 
}
336
 
 
337
 
/* EOF */