control_generic.c 7.0 KB

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