playlist.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <thread.h>
  4. #include <draw.h>
  5. #include <keyboard.h>
  6. #include <mouse.h>
  7. #include <control.h>
  8. #include "playlist.h"
  9. #include "../debug.h"
  10. char *playlistfile = "/mnt/playlist";
  11. char *playctlfile = "/mnt/playctl";
  12. char *playvolfile = "/mnt/playvol";
  13. char *volumefile = "/dev/audioctl";
  14. Playlist playlist;
  15. int playctlfd;
  16. void
  17. playlistproc(void*)
  18. {
  19. int fd, m, n, nf;
  20. static char buf[8192+1];
  21. char *p, *q, *fields[4];
  22. threadsetname("playlistproc");
  23. fd = open(playlistfile, OREAD);
  24. if(fd < 0)
  25. sysfatal("%s: %r", playlistfile);
  26. p = buf;
  27. n = 0;
  28. if(debug & DBGPLAY)
  29. fprint(2, "playlistproc: starting\n");
  30. for(;;){
  31. m = read(fd, buf+n, sizeof buf - 1 - n);
  32. if(m == 0){
  33. if(debug & DBGPLAY)
  34. fprint(2, "playlistproc: empty read\n");
  35. continue;
  36. }
  37. if(m < 0){
  38. rerrstr(buf, sizeof(buf));
  39. if(strcmp(buf, "reading past eof"))
  40. sysfatal("%s: %r", playlistfile);
  41. for(n = 0; n < playlist.nentries; n++){
  42. free(playlist.entry[n].file);
  43. free(playlist.entry[n].onum);
  44. }
  45. if(debug & DBGPLAY)
  46. fprint(2, "playlistproc: trunc\n");
  47. playlist.nentries = 0;
  48. free(playlist.entry);
  49. playlist.entry = nil;
  50. updateplaylist(1);
  51. seek(fd, 0, 0);
  52. p = buf;
  53. n = 0;
  54. continue;
  55. }
  56. if(debug & DBGPLAY)
  57. fprint(2, "playlistproc: read %d bytes\n", m);
  58. n += m;
  59. p[n] = '\0';
  60. while(q = strchr(p, '\n')){
  61. *q = 0;
  62. nf = tokenize(p, fields, nelem(fields));
  63. if(nf){
  64. playlist.entry = realloc(playlist.entry, (playlist.nentries+1)*sizeof playlist.entry[0]);
  65. if(playlist.entry == nil)
  66. sysfatal("realloc %r");
  67. playlist.entry[playlist.nentries].file = strdup(fields[0]);
  68. if(nf > 1){
  69. playlist.entry[playlist.nentries].onum = strdup(fields[1]);
  70. if(debug & DBGPLAY)
  71. fprint(2, "playlistproc: [%d]: %q %q\n", playlist.nentries,
  72. playlist.entry[playlist.nentries].file,
  73. playlist.entry[playlist.nentries].onum);
  74. }else{
  75. playlist.entry[playlist.nentries].onum = nil;
  76. if(debug & DBGPLAY)
  77. fprint(2, "playlistproc: [%d]: %q nil\n", playlist.nentries,
  78. playlist.entry[playlist.nentries].file);
  79. }
  80. updateplaylist(0); // this will also update nentries
  81. }
  82. q++;
  83. n -= q-p;
  84. p = q;
  85. }
  86. if(n)
  87. memmove(buf, p, n);
  88. p = buf;
  89. }
  90. }
  91. void
  92. sendplaylist(char *file, char *onum)
  93. {
  94. static int fd = -1;
  95. char *b;
  96. if(file == nil){
  97. if(fd >= 0)
  98. close(fd);
  99. fd = open(playlistfile, OWRITE|OTRUNC);
  100. if(fd < 0)
  101. sysfatal("%s: truncate: %r", playlistfile);
  102. return;
  103. }
  104. if(fd < 0){
  105. fd = open(playlistfile, OWRITE);
  106. if(fd < 0)
  107. sysfatal("%s: %r", playlistfile);
  108. }
  109. b = smprint("%q %q\n", file, onum);
  110. if(debug & DBGPLAY)
  111. fprint(2, "sendplaylist @%s@\n", b);
  112. if(write(fd , b, strlen(b)) != strlen(b))
  113. sysfatal("sendplaylist: %r");
  114. }
  115. void
  116. playctlproc(void*a)
  117. {
  118. int fd, n, nf;
  119. static char buf[512+1];
  120. char *fields[4];
  121. Channel *chan;
  122. threadsetname("playctlproc");
  123. chan = a;
  124. fd = open(playctlfile, OREAD);
  125. if(fd < 0)
  126. sysfatal("%s: %r", playctlfile);
  127. for(;;){
  128. n = read(fd, buf, sizeof buf -1);
  129. if(n == 0)
  130. continue;
  131. if(n < 0)
  132. sysfatal("%s: %r", playctlfile);
  133. buf[n] = '\0';
  134. nf = tokenize(buf, fields, nelem(fields));
  135. if(nf == 0)
  136. continue;
  137. switch (nf){
  138. default:
  139. sysfatal("playctlproc: [%d]: %s", nf, fields[0]);
  140. case 3:
  141. chanprint(chan, "playctlproc: error %lud %q", strtoul(fields[1], nil, 0), fields[2]);
  142. if(strcmp(fields[0], "error") == 0)
  143. break;
  144. // fall through
  145. case 2:
  146. chanprint(chan, "playctlproc: %s %lud", fields[0], strtoul(fields[1], nil, 0));
  147. }
  148. }
  149. }
  150. void
  151. sendplayctl(char *fmt, ...)
  152. {
  153. va_list arg;
  154. static int fd = -1;
  155. va_start(arg, fmt);
  156. if(debug & DBGPLAY){
  157. fprint(2, "sendplayctl: fmt=%s: ", fmt);
  158. fprint(2, fmt, arg);
  159. fprint(2, "\n");
  160. }
  161. fprint(fd, fmt, arg);
  162. va_end(arg);
  163. }
  164. void
  165. setvolume(char *volume)
  166. {
  167. static int fd;
  168. if(fd == 0){
  169. fd = open(playvolfile, OWRITE);
  170. if(fd < 0){
  171. fprint(2, "can't open %s, (%r) opening %s instead\n", playvolfile, "/dev/volume");
  172. if((fd = open("/dev/volume", OWRITE)) < 0){
  173. fprint(2, "setvolume: open: %r\n");
  174. return;
  175. }
  176. }
  177. }
  178. if(fd < 0)
  179. return;
  180. fprint(fd, "volume %s", volume);
  181. }
  182. void
  183. volumeproc(void *arg)
  184. {
  185. int fd, n, nf, nnf, i, nlines;
  186. static char buf[1024];
  187. char *lines[32];
  188. char *fields[8];
  189. char *subfields[8];
  190. Channel *ctl;
  191. int volume, minvolume, maxvolume, nvolume;
  192. ctl = arg;
  193. threadsetname("volumeproc");
  194. fd = open(volumefile, OREAD);
  195. if(fd < 0){
  196. fprint(2, "%s: %r\n", volumefile);
  197. threadexits(nil);
  198. }
  199. for(;;){
  200. n = read(fd, buf, sizeof buf -1);
  201. if(n == 0)
  202. continue;
  203. if(n < 0){
  204. fprint(2, "volumeproc: read: %r\n");
  205. threadexits("volumeproc");
  206. }
  207. buf[n] = '\0';
  208. nlines = getfields(buf, lines, nelem(lines), 1, "\n");
  209. for(i = 0; i < nlines; i++){
  210. nf = tokenize(lines[i], fields, nelem(fields));
  211. if(nf == 0)
  212. continue;
  213. if(nf != 6 || strcmp(fields[0], "volume") || strcmp(fields[1], "out"))
  214. continue;
  215. minvolume = strtol(fields[3], nil, 0);
  216. maxvolume = strtol(fields[4], nil, 0);
  217. if(minvolume >= maxvolume)
  218. continue;
  219. nnf = tokenize(fields[2], subfields, nelem(subfields));
  220. if(nnf <= 0 || nnf > 8){
  221. fprint(2, "volume format error\n");
  222. threadexits(nil);
  223. }
  224. volume = 0;
  225. nvolume = 0;
  226. for(i = 0; i < nnf; i++){
  227. volume += strtol(subfields[i], nil, 0);
  228. nvolume++;
  229. }
  230. volume /= nvolume;
  231. volume = 100*(volume - minvolume)/(maxvolume-minvolume);
  232. chanprint(ctl, "volume value %d", volume);
  233. }
  234. }
  235. }
  236. void
  237. playvolproc(void*a)
  238. {
  239. int fd, n, nf, volume, nvolume, i;
  240. static char buf[256+1];
  241. char *fields[3], *subfields[9];
  242. Channel *chan;
  243. threadsetname("playvolproc");
  244. chan = a;
  245. fd = open(playvolfile, OREAD);
  246. if(fd < 0)
  247. sysfatal("%s: %r", playvolfile);
  248. for(;;){
  249. n = read(fd, buf, sizeof buf -1);
  250. if(n == 0)
  251. continue;
  252. if(n < 0)
  253. sysfatal("%s: %r", playvolfile);
  254. buf[n] = '\0';
  255. if(debug) fprint(2, "volumestring: %s\n", buf);
  256. nf = tokenize(buf, fields, nelem(fields));
  257. if(nf == 0)
  258. continue;
  259. if(nf != 2 || strcmp(fields[0], "volume"))
  260. sysfatal("playvolproc: [%d]: %s", nf, fields[0]);
  261. nvolume = tokenize(fields[1], subfields, nelem(subfields));
  262. if(nvolume <= 0 || nvolume > 8){
  263. fprint(2, "volume format error\n");
  264. threadexits(nil);
  265. }
  266. volume = 0;
  267. for(i = 0; i < nvolume; i++)
  268. volume += strtol(subfields[i], nil, 0);
  269. volume /= nvolume;
  270. chanprint(chan, "volume value %d", volume);
  271. }
  272. }