Skip to content

Latest commit

 

History

History
278 lines (240 loc) · 6.29 KB

music_cmd.c

File metadata and controls

278 lines (240 loc) · 6.29 KB
 
Oct 21, 1999
Oct 21, 1999
1
/*
Dec 31, 2011
Dec 31, 2011
2
SDL_mixer: An audio mixer library based on the SDL library
Jan 2, 2017
Jan 2, 2017
3
Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
Oct 21, 1999
Oct 21, 1999
4
Dec 31, 2011
Dec 31, 2011
5
6
7
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Oct 21, 1999
Oct 21, 1999
8
Dec 31, 2011
Dec 31, 2011
9
10
11
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
Oct 21, 1999
Oct 21, 1999
12
Dec 31, 2011
Dec 31, 2011
13
14
15
16
17
18
19
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Oct 21, 1999
Oct 21, 1999
20
*/
Apr 30, 2006
Apr 30, 2006
21
#include "SDL_config.h"
Dec 14, 2001
Dec 14, 2001
22
Oct 21, 1999
Oct 21, 1999
23
24
/* This file supports an external command for playing music */
Oct 17, 2017
Oct 17, 2017
25
#ifdef MUSIC_CMD
Oct 21, 1999
Oct 21, 1999
26
27
28
29
30
31
32
33
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
Dec 20, 2001
Dec 20, 2001
34
#include <ctype.h>
Oct 17, 2017
Oct 17, 2017
35
36
37
38
#include <limits.h>
#if defined(__linux__) && defined(__arm__)
# include <linux/limits.h>
#endif
Oct 21, 1999
Oct 21, 1999
39
40
41
#include "music_cmd.h"
Oct 17, 2017
Oct 17, 2017
42
43
44
45
46
47
typedef struct {
char *file;
pid_t pid;
} MusicCMD;
Oct 21, 1999
Oct 21, 1999
48
49
/* Load a music stream from the given file */
Oct 17, 2017
Oct 17, 2017
50
static void *MusicCMD_CreateFromFile(const char *file)
Oct 21, 1999
Oct 21, 1999
51
{
May 22, 2013
May 22, 2013
52
53
54
MusicCMD *music;
/* Allocate and fill the music structure */
Oct 17, 2017
Oct 17, 2017
55
56
music = (MusicCMD *)SDL_calloc(1, sizeof *music);
if (music == NULL) {
May 22, 2013
May 22, 2013
57
Mix_SetError("Out of memory");
Oct 17, 2017
Oct 17, 2017
58
return NULL;
May 22, 2013
May 22, 2013
59
60
61
62
63
}
music->file = SDL_strdup(file);
music->pid = 0;
/* We're done */
Oct 17, 2017
Oct 17, 2017
64
return music;
Oct 21, 1999
Oct 21, 1999
65
66
67
68
69
}
/* Parse a command line buffer into arguments */
static int ParseCommandLine(char *cmdline, char **argv)
{
May 22, 2013
May 22, 2013
70
71
72
73
char *bufp;
int argc;
argc = 0;
Oct 17, 2017
Oct 17, 2017
74
for (bufp = cmdline; *bufp;) {
May 22, 2013
May 22, 2013
75
/* Skip leading whitespace */
Oct 17, 2017
Oct 17, 2017
76
while (isspace(*bufp)) {
May 22, 2013
May 22, 2013
77
78
79
++bufp;
}
/* Skip over argument */
Oct 17, 2017
Oct 17, 2017
80
if (*bufp == '"') {
May 22, 2013
May 22, 2013
81
++bufp;
Oct 17, 2017
Oct 17, 2017
82
83
if (*bufp) {
if (argv) {
May 22, 2013
May 22, 2013
84
85
86
87
88
argv[argc] = bufp;
}
++argc;
}
/* Skip over word */
Oct 17, 2017
Oct 17, 2017
89
while (*bufp && (*bufp != '"')) {
May 22, 2013
May 22, 2013
90
91
92
++bufp;
}
} else {
Oct 17, 2017
Oct 17, 2017
93
94
if (*bufp) {
if (argv) {
May 22, 2013
May 22, 2013
95
96
97
98
99
argv[argc] = bufp;
}
++argc;
}
/* Skip over word */
Oct 17, 2017
Oct 17, 2017
100
while (*bufp && ! isspace(*bufp)) {
May 22, 2013
May 22, 2013
101
102
103
++bufp;
}
}
Oct 17, 2017
Oct 17, 2017
104
105
if (*bufp) {
if (argv) {
May 22, 2013
May 22, 2013
106
107
108
109
110
*bufp = '\0';
}
++bufp;
}
}
Oct 17, 2017
Oct 17, 2017
111
if (argv) {
May 22, 2013
May 22, 2013
112
113
114
argv[argc] = NULL;
}
return(argc);
Oct 21, 1999
Oct 21, 1999
115
116
117
118
}
static char **parse_args(char *command, char *last_arg)
{
May 22, 2013
May 22, 2013
119
120
121
122
123
int argc;
char **argv;
/* Parse the command line */
argc = ParseCommandLine(command, NULL);
Oct 17, 2017
Oct 17, 2017
124
if (last_arg) {
May 22, 2013
May 22, 2013
125
126
127
++argc;
}
argv = (char **)SDL_malloc((argc+1)*(sizeof *argv));
Oct 17, 2017
Oct 17, 2017
128
if (argv == NULL) {
May 22, 2013
May 22, 2013
129
130
131
132
133
return(NULL);
}
argc = ParseCommandLine(command, argv);
/* Add last command line argument */
Oct 17, 2017
Oct 17, 2017
134
if (last_arg) {
May 22, 2013
May 22, 2013
135
136
137
138
139
140
argv[argc++] = last_arg;
}
argv[argc] = NULL;
/* We're ready! */
return(argv);
Oct 21, 1999
Oct 21, 1999
141
142
143
}
/* Start playback of a given music stream */
Oct 17, 2017
Oct 17, 2017
144
static int MusicCMD_Play(void *context)
Oct 21, 1999
Oct 21, 1999
145
{
Oct 17, 2017
Oct 17, 2017
146
147
148
149
150
151
152
MusicCMD *music = (MusicCMD *)context;
if (!music_cmd) {
Mix_SetError("You must call Mix_SetMusicCMD() first");
return -1;
}
Nov 6, 2009
Nov 6, 2009
153
#ifdef HAVE_FORK
May 22, 2013
May 22, 2013
154
music->pid = fork();
Nov 6, 2009
Nov 6, 2009
155
#else
May 22, 2013
May 22, 2013
156
music->pid = vfork();
Nov 6, 2009
Nov 6, 2009
157
#endif
May 22, 2013
May 22, 2013
158
switch(music->pid) {
Oct 17, 2017
Oct 17, 2017
159
160
/* Failed fork() system call */
case -1:
May 22, 2013
May 22, 2013
161
Mix_SetError("fork() failed");
Oct 17, 2017
Oct 17, 2017
162
return -1;
May 22, 2013
May 22, 2013
163
Oct 17, 2017
Oct 17, 2017
164
165
166
/* Child process - executes here */
case 0: {
char **argv;
Oct 13, 2017
Oct 13, 2017
167
Oct 17, 2017
Oct 17, 2017
168
169
170
171
172
/* Unblock signals in case we're called from a thread */
{
sigset_t mask;
sigemptyset(&mask);
sigprocmask(SIG_SETMASK, &mask, NULL);
May 22, 2013
May 22, 2013
173
174
}
Oct 17, 2017
Oct 17, 2017
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/* Execute the command */
argv = parse_args(music_cmd, music->file);
if (argv != NULL) {
execvp(argv[0], argv);
/* exec() failed */
perror(argv[0]);
}
_exit(-1);
}
break;
/* Parent process - executes here */
default:
May 22, 2013
May 22, 2013
189
190
break;
}
Oct 17, 2017
Oct 17, 2017
191
return 0;
Oct 21, 1999
Oct 21, 1999
192
193
}
Oct 17, 2017
Oct 17, 2017
194
195
/* Return non-zero if a stream is currently playing */
static SDL_bool MusicCMD_IsPlaying(void *context)
Oct 21, 1999
Oct 21, 1999
196
{
Oct 17, 2017
Oct 17, 2017
197
MusicCMD *music = (MusicCMD *)context;
May 22, 2013
May 22, 2013
198
199
int status;
Oct 17, 2017
Oct 17, 2017
200
201
202
203
if (music->pid > 0) {
waitpid(music->pid, &status, WNOHANG);
if (kill(music->pid, 0) == 0) {
return SDL_TRUE;
May 22, 2013
May 22, 2013
204
205
}
}
Oct 17, 2017
Oct 17, 2017
206
return SDL_FALSE;
Oct 21, 1999
Oct 21, 1999
207
208
209
}
/* Pause playback of a given music stream */
Oct 17, 2017
Oct 17, 2017
210
static void MusicCMD_Pause(void *context)
Oct 21, 1999
Oct 21, 1999
211
{
Oct 17, 2017
Oct 17, 2017
212
213
MusicCMD *music = (MusicCMD *)context;
if (music->pid > 0) {
May 22, 2013
May 22, 2013
214
215
kill(music->pid, SIGSTOP);
}
Oct 21, 1999
Oct 21, 1999
216
217
218
}
/* Resume playback of a given music stream */
Oct 17, 2017
Oct 17, 2017
219
static void MusicCMD_Resume(void *context)
Oct 21, 1999
Oct 21, 1999
220
{
Oct 17, 2017
Oct 17, 2017
221
222
MusicCMD *music = (MusicCMD *)context;
if (music->pid > 0) {
May 22, 2013
May 22, 2013
223
224
kill(music->pid, SIGCONT);
}
Oct 21, 1999
Oct 21, 1999
225
226
}
Oct 17, 2017
Oct 17, 2017
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
/* Stop playback of a stream previously started with MusicCMD_Start() */
static void MusicCMD_Stop(void *context)
{
MusicCMD *music = (MusicCMD *)context;
int status;
if (music->pid > 0) {
while (kill(music->pid, 0) == 0) {
kill(music->pid, SIGTERM);
sleep(1);
waitpid(music->pid, &status, WNOHANG);
}
music->pid = 0;
}
}
Oct 21, 1999
Oct 21, 1999
243
/* Close the given music stream */
Oct 17, 2017
Oct 17, 2017
244
void MusicCMD_Delete(void *context)
Oct 21, 1999
Oct 21, 1999
245
{
Oct 17, 2017
Oct 17, 2017
246
MusicCMD *music = (MusicCMD *)context;
May 22, 2013
May 22, 2013
247
248
SDL_free(music->file);
SDL_free(music);
Oct 21, 1999
Oct 21, 1999
249
250
}
Oct 17, 2017
Oct 17, 2017
251
Mix_MusicInterface Mix_MusicInterface_CMD =
Oct 21, 1999
Oct 21, 1999
252
{
Oct 17, 2017
Oct 17, 2017
253
254
255
256
257
"CMD",
MIX_MUSIC_CMD,
MUS_CMD,
SDL_FALSE,
SDL_FALSE,
May 22, 2013
May 22, 2013
258
Oct 17, 2017
Oct 17, 2017
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
NULL, /* Load */
NULL, /* Open */
NULL, /* CreateFromRW */
MusicCMD_CreateFromFile,
NULL, /* SetVolume */
MusicCMD_Play,
MusicCMD_IsPlaying,
NULL, /* GetAudio */
NULL, /* Seek */
MusicCMD_Pause,
MusicCMD_Resume,
MusicCMD_Stop,
MusicCMD_Delete,
NULL, /* Close */
NULL, /* Unload */
};
#endif /* MUSIC_CMD */
Oct 21, 1999
Oct 21, 1999
277
Oct 17, 2017
Oct 17, 2017
278
/* vi: set ts=4 sw=4 expandtab: */