music_cmd.c
上传用户:nini_0081
上传日期:2022-07-21
资源大小:2628k
文件大小:5k
源码类别:

多媒体编程

开发平台:

DOS

  1. /*
  2.     SDL_mixer:  An audio mixer library based on the SDL library
  3.     Copyright (C) 1997-2009 Sam Lantinga
  4.     This library is free software; you can redistribute it and/or
  5.     modify it under the terms of the GNU Library General Public
  6.     License as published by the Free Software Foundation; either
  7.     version 2 of the License, or (at your option) any later version.
  8.     This library is distributed in the hope that it will be useful,
  9.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11.     Library General Public License for more details.
  12.     You should have received a copy of the GNU Library General Public
  13.     License along with this library; if not, write to the Free
  14.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  15.     Sam Lantinga
  16.     slouken@libsdl.org
  17. */
  18. #include "SDL_config.h"
  19. /* This file supports an external command for playing music */
  20. #ifdef CMD_MUSIC
  21. #include <sys/types.h>
  22. #include <sys/wait.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <unistd.h>
  26. #include <string.h>
  27. #include <signal.h>
  28. #include <ctype.h>
  29. #include "SDL_mixer.h"
  30. #include "music_cmd.h"
  31. /* Unimplemented */
  32. void MusicCMD_SetVolume(int volume)
  33. {
  34. Mix_SetError("No way to modify external player volume");
  35. }
  36. /* Load a music stream from the given file */
  37. MusicCMD *MusicCMD_LoadSong(const char *cmd, const char *file)
  38. {
  39. MusicCMD *music;
  40. /* Allocate and fill the music structure */
  41. music = (MusicCMD *)malloc(sizeof *music);
  42. if ( music == NULL ) {
  43. Mix_SetError("Out of memory");
  44. return(NULL);
  45. }
  46. strncpy(music->file, file, (sizeof music->file)-1);
  47. music->file[(sizeof music->file)-1] = '';
  48. strncpy(music->cmd, cmd, (sizeof music->cmd)-1);
  49. music->cmd[(sizeof music->cmd)-1] = '';
  50. music->pid = 0;
  51. /* We're done */
  52. return(music);
  53. }
  54. /* Parse a command line buffer into arguments */
  55. static int ParseCommandLine(char *cmdline, char **argv)
  56. {
  57. char *bufp;
  58. int argc;
  59. argc = 0;
  60. for ( bufp = cmdline; *bufp; ) {
  61. /* Skip leading whitespace */
  62. while ( isspace(*bufp) ) {
  63. ++bufp;
  64. }
  65. /* Skip over argument */
  66. if ( *bufp == '"' ) {
  67. ++bufp;
  68. if ( *bufp ) {
  69. if ( argv ) {
  70. argv[argc] = bufp;
  71. }
  72. ++argc;
  73. }
  74. /* Skip over word */
  75. while ( *bufp && (*bufp != '"') ) {
  76. ++bufp;
  77. }
  78. } else {
  79. if ( *bufp ) {
  80. if ( argv ) {
  81. argv[argc] = bufp;
  82. }
  83. ++argc;
  84. }
  85. /* Skip over word */
  86. while ( *bufp && ! isspace(*bufp) ) {
  87. ++bufp;
  88. }
  89. }
  90. if ( *bufp ) {
  91. if ( argv ) {
  92. *bufp = '';
  93. }
  94. ++bufp;
  95. }
  96. }
  97. if ( argv ) {
  98. argv[argc] = NULL;
  99. }
  100. return(argc);
  101. }
  102. static char **parse_args(char *command, char *last_arg)
  103. {
  104. int argc;
  105. char **argv;
  106. /* Parse the command line */
  107. argc = ParseCommandLine(command, NULL);
  108. if ( last_arg ) {
  109. ++argc;
  110. }
  111. argv = (char **)malloc((argc+1)*(sizeof *argv));
  112. if ( argv == NULL ) {
  113. return(NULL);
  114. }
  115. argc = ParseCommandLine(command, argv);
  116. /* Add last command line argument */
  117. if ( last_arg ) {
  118. argv[argc++] = last_arg;
  119. }
  120. argv[argc] = NULL;
  121. /* We're ready! */
  122. return(argv);
  123. }
  124. /* Start playback of a given music stream */
  125. void MusicCMD_Start(MusicCMD *music)
  126. {
  127. #ifdef HAVE_FORK
  128. music->pid = fork();
  129. #else
  130. music->pid = vfork();
  131. #endif
  132. switch(music->pid) {
  133.     /* Failed fork() system call */
  134.     case -1:
  135. Mix_SetError("fork() failed");
  136. return;
  137.     /* Child process - executes here */
  138.     case 0: {
  139.     char command[PATH_MAX];
  140.     char **argv;
  141.     /* Unblock signals in case we're called from a thread */
  142.     {
  143. sigset_t mask;
  144. sigemptyset(&mask);
  145. sigprocmask(SIG_SETMASK, &mask, NULL);
  146.     }
  147.     /* Execute the command */
  148.     strcpy(command, music->cmd);
  149.     argv = parse_args(command, music->file);
  150.     if ( argv != NULL ) {
  151. execvp(argv[0], argv);
  152.     }
  153.     /* exec() failed */
  154.     perror(argv[0]);
  155.     _exit(-1);
  156. }
  157. break;
  158.     /* Parent process - executes here */
  159.     default:
  160. break;
  161. }
  162. return;
  163. }
  164. /* Stop playback of a stream previously started with MusicCMD_Start() */
  165. void MusicCMD_Stop(MusicCMD *music)
  166. {
  167. int status;
  168. if ( music->pid > 0 ) {
  169. while ( kill(music->pid, 0) == 0 ) {
  170. kill(music->pid, SIGTERM);
  171. sleep(1);
  172. waitpid(music->pid, &status, WNOHANG);
  173. }
  174. music->pid = 0;
  175. }
  176. }
  177. /* Pause playback of a given music stream */
  178. void MusicCMD_Pause(MusicCMD *music)
  179. {
  180. if ( music->pid > 0 ) {
  181. kill(music->pid, SIGSTOP);
  182. }
  183. }
  184. /* Resume playback of a given music stream */
  185. void MusicCMD_Resume(MusicCMD *music)
  186. {
  187. if ( music->pid > 0 ) {
  188. kill(music->pid, SIGCONT);
  189. }
  190. }
  191. /* Close the given music stream */
  192. void MusicCMD_FreeSong(MusicCMD *music)
  193. {
  194. free(music);
  195. }
  196. /* Return non-zero if a stream is currently playing */
  197. int MusicCMD_Active(MusicCMD *music)
  198. {
  199. int status;
  200. int active;
  201. active = 0;
  202. if ( music->pid > 0 ) {
  203. waitpid(music->pid, &status, WNOHANG);
  204. if ( kill(music->pid, 0) == 0 ) {
  205. active = 1;
  206. }
  207. }
  208. return(active);
  209. }
  210. #endif /* CMD_MUSIC */