PageRenderTime 25ms CodeModel.GetById 11ms RepoModel.GetById 1ms app.codeStats 0ms

/tags/rel-0-99-75/alsaplayer/input/cdda/cdda_engine.c

#
C | 1247 lines | 898 code | 188 blank | 161 comment | 160 complexity | d8757d76bca16370eac99c62b815b2ec MD5 | raw file
Possible License(s): GPL-2.0, GPL-3.0
  1. /*
  2. * cdda_engine.c (C) 1999-2003 by Andy Lo A Foe <andy@alsaplayer.org>
  3. * CDDB lookup code by Anders Rune Jensen
  4. *
  5. * Based on code from dagrab 0.3 by Marcello Urbani <murbani@numerica.it>
  6. *
  7. * This plugin reads music CD's in digital form, allowing for exceptional
  8. * quality playback of CD audio. It is used in the alsaplayer project
  9. * by Andy Lo A Foe. If you use use this please be so kind as to put a
  10. * pointer to the web page at http://www.alsa-project.org/~andy
  11. *
  12. * This program is free software; you can redistribute it and/or modify
  13. * it under the terms of the GNU General Public License as published by
  14. * the Free Software Foundation; either version 2 of the License, or
  15. * (at your option) any later version.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with this program; if not, write to the Free Software
  24. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  25. *
  26. */
  27. #include "config.h"
  28. #include "cdda.h"
  29. #include "prefs.h"
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <unistd.h>
  33. #include <fcntl.h>
  34. #include <time.h>
  35. #include <string.h>
  36. #include <dirent.h>
  37. #include <pwd.h>
  38. #include <endian.h>
  39. #include <inttypes.h>
  40. #ifdef HAVE_LINUX_CDROM_H
  41. #include <linux/cdrom.h>
  42. #endif
  43. #include <sys/ioctl.h>
  44. #include <sys/time.h>
  45. #include <sys/vfs.h>
  46. #include <sys/stat.h>
  47. #include <sys/types.h>
  48. #include <sys/param.h>
  49. #include <pthread.h>
  50. #include "input_plugin.h"
  51. #include "alsaplayer_error.h"
  52. #include "AlsaPlayer.h"
  53. #include "control.h"
  54. #include "prefs.h"
  55. #include "utilities.h"
  56. #define BUFFER_SIZE 4096
  57. #define DEFAULT_DEVICE "/dev/cdrom"
  58. #define FRAME_LEN 4
  59. #define N_BUF 8
  60. #define OVERLAY 3
  61. #define KEYLEN 12
  62. #define OFS 12
  63. #define RETRYS 20
  64. #define IFRAMESIZE (CD_FRAMESIZE_RAW/sizeof(int))
  65. #define BLEN 255
  66. /* global variables */
  67. static char *REAL_PATH = NULL;
  68. typedef struct
  69. {
  70. char *artist;
  71. char *album;
  72. char *track;
  73. } track;
  74. track tracks[100];
  75. struct cd_trk_list {
  76. int min;
  77. int max;
  78. int *l_min;
  79. int *l_sec;
  80. int *l_frame;
  81. int *starts;
  82. char *types;
  83. };
  84. struct cdda_local_data {
  85. char device_path[1024];
  86. struct cd_trk_list tl;
  87. int cdrom_fd;
  88. int samplerate;
  89. int track_length;
  90. int track_start;
  91. int rel_pos;
  92. int track_nr;
  93. };
  94. //static cd_trk_list tl, old_tl;
  95. typedef unsigned short Word;
  96. typedef unsigned char unchar;
  97. int cddb_sum (int n);
  98. static int cd_get_tochdr(int cdrom_fd, struct cdrom_tochdr *Th)
  99. {
  100. return ioctl(cdrom_fd, CDROMREADTOCHDR,Th);
  101. }
  102. static int cd_get_tocentry(int cdrom_fd, int trk, struct cdrom_tocentry *Te, int mode)
  103. {
  104. Te->cdte_track=trk;
  105. Te->cdte_format=mode;
  106. return ioctl(cdrom_fd,CDROMREADTOCENTRY,Te);
  107. }
  108. static int cd_read_audio(int cdrom_fd, int lba, int num, unsigned char *buf)
  109. {
  110. struct cdrom_read_audio ra;
  111. ra.addr.lba = lba;
  112. ra.addr_format = CDROM_LBA;
  113. ra.nframes = num;
  114. ra.buf = buf;
  115. if (ioctl(cdrom_fd, CDROMREADAUDIO, &ra)) {
  116. alsaplayer_error("CDDA: read raw ioctl failed at lba %d length %d",
  117. lba, num);
  118. perror("CDDA");
  119. return 1;
  120. }
  121. return 0;
  122. }
  123. static char *resttime(int sec)
  124. {
  125. static char buf[BLEN+1];
  126. snprintf(buf, BLEN, "%02d:%02d:%02d", sec/3600, (sec/60)%60, sec%60);
  127. return buf;
  128. }
  129. void toc_fail(struct cd_trk_list *tl)
  130. {
  131. free(tl->starts);
  132. free(tl->types);
  133. free(tl->l_min);
  134. free(tl->l_sec);
  135. free(tl->l_frame);
  136. tl->starts = NULL;
  137. tl->types = NULL;
  138. tl->l_min = NULL;
  139. tl->l_sec = NULL;
  140. tl->l_frame = NULL;
  141. }
  142. static int cd_getinfo(int *cdrom_fd, char *cd_dev, struct cd_trk_list *tl)
  143. {
  144. int i;
  145. struct cdrom_tochdr Th;
  146. struct cdrom_tocentry Te;
  147. if ((*cdrom_fd=open(cd_dev,O_RDONLY | O_NONBLOCK))==-1){
  148. alsaplayer_error("CDDA: error opening device %s",cd_dev);
  149. return 1;
  150. }
  151. if(cd_get_tochdr(*cdrom_fd, &Th)){
  152. alsaplayer_error("CDDA: read TOC ioctl failed");
  153. return 1;
  154. }
  155. tl->min=Th.cdth_trk0; /* first track */
  156. tl->max=Th.cdth_trk1; /* last track */
  157. if((tl->starts=(int *)malloc((tl->max-tl->min+2)*sizeof(int)))==NULL){
  158. alsaplayer_error("CDDA: list data allocation failed");
  159. return 1;
  160. }
  161. if((tl->types=(char *)malloc(tl->max-tl->min+2))==NULL){
  162. alsaplayer_error("CDDA: list data allocation failed");
  163. return 1;
  164. }
  165. /* length */
  166. if((tl->l_min=(int *)malloc((tl->max-tl->min+2)*sizeof(int)))==NULL){
  167. alsaplayer_error("CDDA: list data allocation failed");
  168. return 1;
  169. }
  170. if((tl->l_sec=(int *)malloc((tl->max-tl->min+2)*sizeof(int)))==NULL){
  171. alsaplayer_error("CDDA: list data allocation failed");
  172. return 1;
  173. }
  174. if((tl->l_frame=(int *)malloc((tl->max-tl->min+2)*sizeof(int)))==NULL){
  175. alsaplayer_error("CDDA: list data allocation failed");
  176. return 1;
  177. }
  178. i=CDROM_LEADOUT;
  179. if(cd_get_tocentry(*cdrom_fd, i,&Te,CDROM_LBA)){
  180. alsaplayer_error("CDDA: read TOC entry ioctl failed");
  181. toc_fail(tl);
  182. return 1;
  183. }
  184. tl->starts[tl->max]=Te.cdte_addr.lba;
  185. tl->types[tl->max]=Te.cdte_ctrl&CDROM_DATA_TRACK;
  186. if(cd_get_tocentry(*cdrom_fd, i,&Te,CDROM_MSF)){
  187. alsaplayer_error("CDDA: read TOC entry ioctl failed");
  188. toc_fail(tl);
  189. return 1;
  190. }
  191. /* length info */
  192. tl->l_min[tl->max] = Te.cdte_addr.msf.minute;
  193. tl->l_sec[tl->max] = Te.cdte_addr.msf.second;
  194. tl->l_frame[tl->max] = Te.cdte_addr.msf.frame;
  195. for (i=tl->max;i>=tl->min;i--)
  196. {
  197. if(cd_get_tocentry(*cdrom_fd, i,&Te,CDROM_LBA)){
  198. alsaplayer_error("CDDA: read TOC entry ioctl failed");
  199. toc_fail(tl);
  200. return 1;
  201. }
  202. tl->starts[i-1]=Te.cdte_addr.lba;
  203. tl->types[i-1]=Te.cdte_ctrl&CDROM_DATA_TRACK;
  204. if(cd_get_tocentry(*cdrom_fd, i,&Te,CDROM_MSF)){
  205. alsaplayer_error("CDDA: read TOC entry ioctl failed");
  206. toc_fail(tl);
  207. return 1;
  208. }
  209. /* length info */
  210. tl->l_min[i-1] = Te.cdte_addr.msf.minute;
  211. tl->l_sec[i-1] = Te.cdte_addr.msf.second;
  212. tl->l_frame[i-1] = Te.cdte_addr.msf.frame;
  213. }
  214. return 0;
  215. }
  216. #if 0
  217. static void cd_disp_TOC(struct cd_trk_list *tl)
  218. {
  219. int i, len;
  220. alsaplayer_error("%5s %8s %8s %5s %9s %4s","track","start","length","type",
  221. "duration", "MB");
  222. for (i=tl->min;i<=tl->max;i++)
  223. {
  224. len = tl->starts[i + 1 - tl->min] - tl->starts[i - tl->min];
  225. alsaplayer_error("%5d %8d %8d %5s %9s %4d",i,
  226. tl->starts[i-tl->min]+CD_MSF_OFFSET, len,
  227. tl->types[i-tl->min]?"data":"audio",resttime(len / 75),
  228. (len * CD_FRAMESIZE_RAW) >> (20)); // + opt_mono));
  229. }
  230. alsaplayer_error("%5d %8d %8s %s",CDROM_LEADOUT,
  231. tl->starts[i-tl->min]+CD_MSF_OFFSET,"-","leadout");
  232. }
  233. static int cd_jc1(int *p1,int *p2) //nuova
  234. /* looks for offset in p1 where can find a subset of p2 */
  235. {
  236. int *p,n;
  237. p=p1+opt_ibufsize-IFRAMESIZE-1;n=0;
  238. while(n<IFRAMESIZE*opt_overlap && *p==*--p)n++;
  239. if (n>=IFRAMESIZE*opt_overlap) /* jitter correction is useless on silence */
  240. {
  241. n=(opt_bufstep)*CD_FRAMESIZE_RAW;
  242. }
  243. else /* jitter correction */
  244. {
  245. n=0;p=p1+opt_ibufsize-opt_keylen/sizeof(int)-1;
  246. while((n<IFRAMESIZE*(1+opt_overlap)) && memcmp(p,p2,opt_keylen))
  247. {p--;n++;};
  248. /* {p-=6;n+=6;}; //should be more accurate, but doesn't work well*/
  249. if(n>=IFRAMESIZE*(1+opt_overlap)){ /* no match */
  250. return -1;
  251. };
  252. n=sizeof(int)*(p-p1);
  253. }
  254. return n;
  255. }
  256. static int cd_jc(int *p1,int *p2)
  257. {
  258. int n,d;
  259. n=0;
  260. do
  261. d=cd_jc1(p1,p2+n);
  262. while((d==-1)&&(n++<opt_ofs));n--;
  263. if (d==-1) return (d);
  264. else return (d-n*sizeof(int));
  265. }
  266. #endif
  267. /*
  268. * create_socket - create a socket to communicate with the remote server
  269. * return the fd' int on success, or -1 on error.
  270. */
  271. int create_socket (unchar *unchar_address, int int_port)
  272. {
  273. int sock, len;
  274. struct hostent *remote;
  275. struct sockaddr_in server;
  276. ushort port = (ushort) (int_port);
  277. ulong address, temp;
  278. /* get the "remote" server information */
  279. remote = gethostbyname (unchar_address);
  280. if (! remote)
  281. {
  282. alsaplayer_error("%s\n", strerror (errno));
  283. return (-1);
  284. }
  285. bcopy ((char *) remote->h_addr, (char *) &temp, remote->h_length);
  286. /* convert the 32bit long value from *network byte order* to the *host byte order* */
  287. address = ntohl (temp);
  288. /* create the address of the CDDB server, filling the server's mem_area with 0 values */
  289. len = sizeof (struct sockaddr_in);
  290. memset (&server, 0, len);
  291. server.sin_family = AF_INET; /* set the address as being in the internet domain */
  292. server.sin_port = htons (port); /* set the port address of the server */
  293. server.sin_addr.s_addr = htonl (address);
  294. /* create a socket in the INET domain */
  295. sock = socket (AF_INET, SOCK_STREAM, 0);
  296. if (sock < 0)
  297. {
  298. alsaplayer_error("socket error\n");
  299. return (-1);
  300. }
  301. /* connect to the server */
  302. if (connect (sock, (struct sockaddr *) &server, sizeof (server)) < 0)
  303. {
  304. alsaplayer_error("%s\n", strerror (errno));
  305. return (-1);
  306. }
  307. return (sock);
  308. }
  309. /*
  310. * sent_to_server - send a message to the server, and return the server response
  311. * on success, or NULL on error
  312. */
  313. char * send_to_server (int server_fd, char *message)
  314. {
  315. ssize_t total;
  316. int len = BUFFER_SIZE * 8;
  317. char *response, temp[len];
  318. /* write 'message' to the server */
  319. if (send (server_fd, message, strlen (message), MSG_DONTWAIT) < 0)
  320. {
  321. alsaplayer_error("%s: %s\n", message, strerror (errno));
  322. return (NULL);
  323. }
  324. #ifdef DEBUG
  325. /* print the message sent to the server */
  326. alsaplayer_error("-> %s", message);
  327. #endif
  328. /* read the response from the server */
  329. total = 0;
  330. do
  331. {
  332. total += read (server_fd, temp + total, len - total);
  333. if (total < 0)
  334. {
  335. alsaplayer_error("%s\n", strerror (errno));
  336. return (NULL);
  337. }
  338. }
  339. while (total > 2 && temp[total - 2] != '\r');
  340. temp[total-2] = '\0'; /* temp[total-1] == \r; temp[total] == \n */
  341. response = strdup (temp); /* duplicate the response from the server */
  342. #ifdef DEBUG
  343. /* print the message sent to the server */
  344. alsaplayer_error("<- %s", response);
  345. #endif
  346. return (response);
  347. }
  348. /*
  349. * cddb_disc_id - generate the disc ID from the total music time
  350. * (routine token from the cddb.howto)
  351. */
  352. unsigned int cddb_disc_id (struct cd_trk_list *tl)
  353. {
  354. int i, t = 0, n = 0;
  355. /* n == total music time in seconds */
  356. i = 0;
  357. while (i < tl->max)
  358. {
  359. n += cddb_sum((tl->l_min[i] * 60) + tl->l_sec[i]);
  360. i++;
  361. }
  362. /* t == lead-out offset seconds - 1st music total time, in seconds */
  363. t = ((tl->l_min[tl->max] * 60) + tl->l_sec[tl->max])
  364. - ((tl->l_min[0] * 60) + tl->l_sec[0]);
  365. /*
  366. * mod 'n' with FFh and left-shift it by 24. 't' is left-shifted by 8.
  367. * the disc_id is then returned as these operations + total tracks
  368. * 'OR'ed together.
  369. */
  370. return ((n % 0xff) << 24 | t << 8 | tl->max);
  371. }
  372. /*
  373. * cddb_sum - adds the value of each digit in the decimal string representation
  374. * of the number. (routine token from the cddb.howto)
  375. */
  376. int cddb_sum (int n)
  377. {
  378. int ret = 0;
  379. while (n > 0)
  380. {
  381. ret = ret + (n % 10);
  382. n = n/10;
  383. }
  384. return (ret);
  385. }
  386. /*
  387. * save_to_disk - receive the subdir, cdID and the message, and save the
  388. * information into the cddb directory. This function returns the filename on
  389. * success, or NULL on error.
  390. */
  391. char * cddb_save_to_disk(char *subdir, int cdID, char *message)
  392. {
  393. FILE *destination;
  394. DIR *thedir;
  395. char *path, *retval;
  396. char new[strlen (message)], filename[strlen (message) + 9];
  397. int i = 0, j = 0;
  398. /* check if we already have the subdir created */
  399. path = (char *) malloc ((strlen (subdir) + strlen (REAL_PATH)) * sizeof (char));
  400. /* print the message sent to the server */
  401. sprintf(path, "%s", REAL_PATH);
  402. if (! (thedir=opendir(path))) { /* No cddb directory yet! */
  403. if ((mkdir(path, 0744)) < 0) {
  404. perror("mkdir");
  405. return (NULL);
  406. }
  407. } else {
  408. closedir(thedir);
  409. }
  410. /* cddb directory should be there at this point */
  411. sprintf (path, "%s/%s", REAL_PATH, subdir);
  412. if (global_verbose)
  413. alsaplayer_error("path = %s", path);
  414. /* check if we have the directory in the disk */
  415. if (! (thedir = opendir (path))) {
  416. /* given directory doesn't exist */
  417. if (global_verbose)
  418. printf ("directory %s doesn't exist, trying to create it.\n", path);
  419. /* try to create it.. */
  420. if ((mkdir (path, 0744)) < 0) {
  421. perror ("mkdir");
  422. return (NULL);
  423. } else {
  424. if (global_verbose)
  425. printf ("directory created successfully\n");
  426. }
  427. } else {
  428. closedir(thedir);
  429. }
  430. while (message[i] != '\n')
  431. i++;
  432. i++;
  433. for (; i < (int)strlen (message); i++, j++)
  434. new[j] = message[i];
  435. /* save it into the disc */
  436. sprintf (filename, "%s/%s/%08x", REAL_PATH, subdir, cdID);
  437. retval = strdup (filename);
  438. if (global_verbose)
  439. alsaplayer_error("filename = %s", filename);
  440. /* create the file */
  441. destination = fopen (filename, "w");
  442. if (! destination)
  443. {
  444. alsaplayer_error("error creating file");
  445. return (NULL);
  446. }
  447. /* copy the new string content into the file */
  448. for (i = 0; i < (int)strlen (new); i++)
  449. fputc (new[i], destination);
  450. /* free path's memory */
  451. free (path);
  452. /* close the file */
  453. fclose (destination);
  454. return (retval);
  455. }
  456. /*
  457. * search for the CD info in the hard disk CDDB, returning NULL on error or the
  458. * filename on success.
  459. */
  460. char * cddb_local_lookup (char *path, unsigned int cd_id)
  461. {
  462. int i, number, fd;
  463. char *name;
  464. char cdrom_id[9];
  465. struct dirent **directory;
  466. if (global_verbose)
  467. alsaplayer_error ("Searching for CDDB entries on %s ... ", path);
  468. /* try to open the given directory */
  469. if (! (opendir (path)))
  470. {
  471. return (NULL);
  472. }
  473. /* get the number of subdirectories in the 'path' dir */
  474. number = scandir (path, &directory, 0, alphasort);
  475. if (number < 0)
  476. {
  477. alsaplayer_error("scandir\n");
  478. return (NULL);
  479. }
  480. /* set the cdrom_id */
  481. sprintf (cdrom_id, "%08x", cd_id);
  482. cdrom_id[9] = '\0';
  483. for (i = 0; i < number; i++)
  484. {
  485. /* ignore '.' and '..' directories */
  486. if ((strcmp (directory[i]->d_name, ".")) && (strcmp (directory[i]->d_name, "..")))
  487. {
  488. name = malloc((strlen (path) + strlen (directory[i]->d_name) + 15) * sizeof(char));
  489. sprintf (name, "%s", path);
  490. strcat (name, "/");
  491. strncat (name, directory[i]->d_name, strlen (directory[i]->d_name));
  492. strcat (name, "/");
  493. strncat (name, cdrom_id, 8);
  494. if ((fd = open (name, O_RDONLY)) >= 0)
  495. {
  496. if (global_verbose)
  497. printf ("OK\n");
  498. close (fd);
  499. return (name);
  500. }
  501. free (name);
  502. }
  503. }
  504. if (global_verbose)
  505. printf ("not found\n");
  506. return (NULL);
  507. }
  508. /*
  509. * search for the song in the CDDB given address/port, returning it's name, or
  510. * NULL if not found.
  511. */
  512. char * cddb_lookup (char *address, char *char_port, int discID, struct cd_trk_list *tl)
  513. {
  514. int port = atoi (char_port);
  515. int server_fd, i, j, n;
  516. int total_secs = 0, counter = 0;
  517. char *answer = NULL, *username, *filename, categ[20], newID[9];
  518. char msg[BUFFER_SIZE], offsets[BUFFER_SIZE], tmpbuf[BUFFER_SIZE];
  519. char hostname[MAXHOSTNAMELEN], server[80];
  520. /* try to create a socket to the server */
  521. if (global_verbose)
  522. alsaplayer_error ("Opening Connection to %s:%d ... ", address, port);
  523. /* get the server fd from the create_socket function */
  524. server_fd = create_socket ((unchar *) address, port);
  525. if (server_fd < 0)
  526. return (NULL);
  527. else
  528. if (global_verbose)
  529. printf ("OK\n");
  530. /* get the initial message from the server */
  531. n = read (server_fd, server, BUFFER_SIZE);
  532. server[n-2] = '\0';
  533. if (global_verbose) {
  534. printf ("\n<- %s\n", server);
  535. printf ("Saying HELLO to CDDB server ...\n");
  536. }
  537. /* set some settings before saying HELLO to the CDDB server */
  538. username = getlogin ();
  539. if ((gethostname (hostname, sizeof (hostname))) < 0)
  540. snprintf (hostname, sizeof (hostname), "unknown");
  541. snprintf (msg, sizeof (msg), "cddb hello %s %s %s %s\r\n", username, hostname,PACKAGE, VERSION);
  542. answer = send_to_server (server_fd, msg);
  543. if (! answer)
  544. {
  545. alsaplayer_error("bad response from the server\n");
  546. close (server_fd);
  547. return (NULL);
  548. }
  549. /* set another settings before querying the CDDB database */
  550. tmpbuf[0] = '\0';
  551. for (i = 0; i < tl->max; i++)
  552. {
  553. /* put the frame offset of the starting location of each track in a string */
  554. snprintf (offsets, sizeof (offsets), "%s %d ", tmpbuf,
  555. tl->l_frame[i] + (75 * (tl->l_sec[i] + (60 * tl->l_min[i]))));
  556. strcpy (tmpbuf, offsets);
  557. counter += tl->l_frame[i] + (75 * tl->l_sec[i] + (60 * tl->l_min[i]));
  558. }
  559. total_secs = tl->l_sec[tl->max] + (tl->l_min[tl->max] * 60);
  560. /* send it */
  561. snprintf (msg, sizeof (msg), "cddb query %08x %d %s %d\r\n", discID, tl->max, offsets, total_secs);
  562. answer = send_to_server (server_fd, msg);
  563. if (! answer)
  564. {
  565. alsaplayer_error("bad response from the server\n");
  566. close (server_fd);
  567. return (NULL);
  568. }
  569. /*
  570. * if answer == "200...", found exact match
  571. * if answer == "211...", found too many matches
  572. * if answer == "202...", found no matches
  573. */
  574. i = 0;
  575. if (! (strncmp (answer, "211", 3)))
  576. {
  577. /* seek the 2nd line */
  578. while (answer[i] != '\n')
  579. ++i;
  580. /* copy the 1st match to the category */
  581. j = 0;
  582. i++;
  583. while (answer[i] != ' ')
  584. categ[j++] = answer[i++];
  585. categ[j++] = '\0';
  586. /* get the new cdID given from the CDDB */
  587. j = 0;
  588. i++;
  589. while (answer[i] != ' ')
  590. newID[j++] = answer[i++];
  591. newID[j++] = '\0';
  592. }
  593. else if (! (strncmp (answer, "200", 3)))
  594. {
  595. /* get it from the 1st line */
  596. while (answer[i] != ' ')
  597. i++;
  598. i++;
  599. /* copy the match to the category */
  600. j = 0;
  601. while (answer[i] != ' ')
  602. categ[j++] = answer[i++];
  603. categ[j++] = '\0';
  604. /* copy the new cdID */
  605. j = 0;
  606. i++;
  607. while (answer[i] != ' ')
  608. newID[j++] = answer[i++];
  609. newID[j++] = '\0';
  610. }
  611. else
  612. {
  613. alsaplayer_error("Could not find any matches for %08x\n\n", discID);
  614. close (server_fd);
  615. return (NULL);
  616. }
  617. /* read from the server */
  618. sprintf (msg, "cddb read %s %s\r\n", categ, newID);
  619. answer = send_to_server(server_fd, msg);
  620. if (! answer)
  621. {
  622. alsaplayer_error("could not receive the informations from %s\n", address);
  623. close (server_fd);
  624. return (NULL);
  625. }
  626. /* save the output into the disc */
  627. if (global_verbose)
  628. {
  629. printf ("Saving CDDB information into %s/%s ...\n", REAL_PATH, newID);
  630. printf ("save_to_disk(%s)\n", answer);
  631. }
  632. filename = cddb_save_to_disk(categ, discID, answer);
  633. if (! filename)
  634. {
  635. alsaplayer_error("could not create the file %s/%s, check permission\n", categ, newID);
  636. close (server_fd);
  637. return (NULL);
  638. }
  639. if (global_verbose)
  640. puts ("");
  641. /* close the fd */
  642. close (server_fd);
  643. return (filename);
  644. }
  645. /*
  646. * open the filename and put music title's into the global variable
  647. */
  648. void cddb_read_file (char *file)
  649. {
  650. char line[BUFFER_SIZE], name[BUFFER_SIZE];
  651. char *token = NULL, *tmp;
  652. int i, index = 1;
  653. FILE *f;
  654. /* try to open the file */
  655. f = fopen (file, "r");
  656. if (! f)
  657. {
  658. alsaplayer_error("couldn't open file\n");
  659. abort ();
  660. }
  661. /* read it line by line */
  662. while (!feof (f))
  663. {
  664. if ((fgets (line, sizeof (line), f)))
  665. {
  666. if (! (strstr (line, "DTITLE=")))
  667. {
  668. /* check if is the music name.. */
  669. if ((strstr (line, "TTITLE")))
  670. {
  671. token = strtok (line, "=");
  672. if (! token) { printf ("error: TTITLE has no arguments\n"); continue; }
  673. token = strtok (NULL, "=");
  674. if (! token) { printf ("error: TTITLE has no arguments\n"); continue; }
  675. /* seek for the \r character */
  676. for (i = 0; i < (int)strlen (token); i++)
  677. {
  678. if ((token[i] == '\n') || (token[i] == '\r'))
  679. break;
  680. }
  681. token[i] = '\0';
  682. /* check if the last character is a space */
  683. //if (tracks[1].artist[strlen (tracks[1].artist)] == ' ')
  684. // snprintf (name, sizeof (name), "%s- %s", tracks[1].artist, token);
  685. //else
  686. sprintf (name, "%s", token);
  687. tracks[index].track = strdup (name);
  688. index++;
  689. }
  690. continue;
  691. }
  692. else
  693. {
  694. /* print the album name */
  695. tmp = strtok (line, "=");
  696. if (! tmp) { alsaplayer_error ("error: no arguments given on %s\n", line); continue; }
  697. tmp = strtok (NULL, "=");
  698. if (! tmp) { alsaplayer_error ("error: no arguments given on %s\n", line); continue; }
  699. tmp = strtok (tmp, "/");
  700. if (! tmp) { alsaplayer_error ("error: no arguments given on %s\n", line); continue; }
  701. tracks[1].artist = strdup (tmp);
  702. tracks[1].album = strdup (strtok (NULL, "/"));
  703. /* verify if we have not an empty space in the end of the string */
  704. if (tracks[1].artist[strlen (tracks[1].artist) - 1] == ' ')
  705. tracks[1].artist[strlen (tracks[1].artist) - 1] = '\0';
  706. if (global_verbose) {
  707. printf ("Artist: %s ", tracks[1].artist);
  708. printf ("Album name: %s\n", tracks[1].album);
  709. }
  710. }
  711. } /* if */
  712. } /* while */
  713. }
  714. void cddb_update_info(struct cd_trk_list *tl)
  715. {
  716. char *file_name = NULL;
  717. char *cddb_servername = NULL;
  718. char *cddb_serverport = NULL;
  719. int index;
  720. unsigned int cd_id = cddb_disc_id(tl);
  721. /* try to get the audio info from the hard disk.. */
  722. file_name = cddb_local_lookup(REAL_PATH, cd_id);
  723. if (file_name)
  724. {
  725. /* open the 'file_name' and search for album information */
  726. cddb_read_file (file_name);
  727. }
  728. else
  729. {
  730. /* if could not, try to get it from the internet connection.. */
  731. cddb_servername = prefs_get_string(ap_prefs, "cdda", "cddb_servername", "freedb.freedb.org");
  732. cddb_serverport = prefs_get_string(ap_prefs, "cdda", "cddb_serverport", "888");
  733. if (global_verbose)
  734. alsaplayer_error("CDDB server: %s:%s", cddb_servername, cddb_serverport);
  735. file_name = cddb_lookup(cddb_servername, cddb_serverport, cd_id, tl);
  736. if (file_name)
  737. {
  738. /* fine, now we have the hard disk access! so, let's use it's information */
  739. file_name = cddb_local_lookup(REAL_PATH, cd_id);
  740. if (file_name)
  741. cddb_read_file (file_name);
  742. else
  743. {
  744. for (index = 1; index <= tl->max; index++)
  745. tracks[index].track = strdup ("unrecognized song");
  746. }
  747. }
  748. else
  749. {
  750. for (index = 1; index <= tl->max; index++)
  751. tracks[index].track = strdup ("unrecognized song");
  752. }
  753. }
  754. }
  755. static int cdda_init(void)
  756. {
  757. char *prefsdir;
  758. prefsdir = get_prefsdir();
  759. REAL_PATH = (char *)malloc(strlen(prefsdir) + 8);
  760. if (REAL_PATH) {
  761. sprintf(REAL_PATH, "%s/cddb", prefsdir);
  762. return 1;
  763. }
  764. return 0;
  765. }
  766. static float cdda_can_handle(const char *name)
  767. {
  768. char *ext;
  769. ext = strrchr(name, '.');
  770. if (ext)
  771. if ((strcasecmp(ext, ".cdda") == 0)) {
  772. return 1.0;
  773. }
  774. return 0.0;
  775. }
  776. void cd_adder(void *data) {
  777. int i;
  778. intptr_t nr_tracks;
  779. char track_name[1024];
  780. if (!data)
  781. return;
  782. nr_tracks = (intptr_t)data;
  783. for (i=1;i <= nr_tracks;i++) {
  784. sprintf(track_name, "Track %02d.cdda", i);
  785. ap_add_path(global_session_id, track_name);
  786. }
  787. pthread_exit(NULL);
  788. }
  789. static int cdda_open(input_object *obj, const char *name)
  790. {
  791. struct cdda_local_data *data;
  792. const char *fname;
  793. char device_name[1024];
  794. if (!obj)
  795. return 0;
  796. fname = strrchr(name, '/');
  797. if (!fname)
  798. fname = name;
  799. else fname++; // Ignore '/'
  800. if (ap_prefs) {
  801. strcpy(device_name, prefs_get_string(ap_prefs, "cdda", "device", DEFAULT_DEVICE));
  802. } else {
  803. strcpy(device_name, DEFAULT_DEVICE);
  804. }
  805. #ifdef DEBUG
  806. alsaplayer_error("device = %s, name = %s\n", device_name, fname);
  807. #endif
  808. obj->local_data = malloc(sizeof(struct cdda_local_data));
  809. if (!obj->local_data) {
  810. return 0;
  811. }
  812. data = (struct cdda_local_data *)obj->local_data;
  813. if(cd_getinfo(&data->cdrom_fd, device_name, &data->tl)) {
  814. free(obj->local_data);
  815. obj->local_data = NULL;
  816. return 0;
  817. }
  818. #ifdef DEBUG
  819. cd_disp_TOC(&data->tl);
  820. alsaplayer_error("IFRAMESIZE = %d\n", IFRAMESIZE);
  821. #endif
  822. obj->nr_channels = 2;
  823. data->samplerate = 44100;
  824. data->track_length = 0;
  825. data->track_start = 0;
  826. data->rel_pos = 0;
  827. data->track_nr = 0;
  828. strcpy(data->device_path, device_name);
  829. if (prefs_get_bool(ap_prefs, "cdda", "do_cddb_lookup", 1)) {
  830. /* look up cd in cddb */
  831. cddb_update_info(&data->tl);
  832. }
  833. if (strcmp(fname, "CD.cdda") == 0) {
  834. pthread_t cd_add;
  835. pthread_create(&cd_add, NULL, (void *(*)(void *))cd_adder, (void *)(intptr_t)data->tl.max);
  836. pthread_detach(cd_add);
  837. return 1;
  838. } else if (sscanf(fname, "Track %02d.cdda", &data->track_nr) != 1 ||
  839. sscanf(fname, "Track%02d.cdda", &data->track_nr) != 1) {
  840. alsaplayer_error("Failed to read track number (%s)", fname);
  841. free(obj->local_data);
  842. obj->local_data = NULL;
  843. return 0;
  844. } else {
  845. #ifdef DEBUG
  846. alsaplayer_error("Found track number %d (%s)\n", data->track_nr, fname);
  847. #endif
  848. data->track_start = data->tl.starts[data->track_nr-1];
  849. data->track_length = data->tl.starts[data->track_nr] -
  850. data->tl.starts[data->track_nr-1];
  851. data->rel_pos = 0;
  852. }
  853. obj->flags = P_SEEK;
  854. return 1;
  855. }
  856. static void cdda_close(input_object *obj)
  857. {
  858. struct cdda_local_data *data;
  859. #ifdef DEBUG
  860. alsaplayer_error("In cdda_close()\n");
  861. #endif
  862. if (!obj)
  863. return;
  864. data = (struct cdda_local_data *)obj->local_data;
  865. if (!data) {
  866. return;
  867. }
  868. close(data->cdrom_fd);
  869. if (data->tl.starts) free(data->tl.starts);
  870. data->tl.starts = NULL;
  871. if (data->tl.types) free(data->tl.types);
  872. data->tl.types = NULL;
  873. /* length */
  874. if (data->tl.l_min) free(data->tl.l_min);
  875. data->tl.l_min = NULL;
  876. if (data->tl.l_sec) free(data->tl.l_sec);
  877. data->tl.l_sec = NULL;
  878. if (data->tl.l_frame) free(data->tl.l_frame);
  879. data->tl.l_frame = NULL;
  880. free(obj->local_data);
  881. obj->local_data = NULL;
  882. }
  883. static int cdda_play_frame(input_object *obj, char *buf)
  884. {
  885. struct cdda_local_data *data;
  886. unsigned char bla[CD_FRAMESIZE_RAW*FRAME_LEN];
  887. if (!obj)
  888. return 0;
  889. data = (struct cdda_local_data *)obj->local_data;
  890. if (!data) {
  891. return 0;
  892. }
  893. if (!data->track_length ||
  894. (data->rel_pos > data->track_length)) {
  895. #ifdef DEBUG
  896. alsaplayer_error("rel_pos = %d, start = %d, end = %d\n",
  897. data->rel_pos, data->track_start,
  898. data->track_start + data->track_length);
  899. #endif
  900. return 0;
  901. }
  902. memset(bla, 0, sizeof(bla));
  903. if (cd_read_audio(data->cdrom_fd, data->track_start + data->rel_pos, FRAME_LEN, bla)) {
  904. return 0;
  905. }
  906. data->rel_pos += FRAME_LEN;
  907. if (buf) {
  908. memcpy(buf, bla, (CD_FRAMESIZE_RAW * FRAME_LEN));
  909. #ifdef __BYTE_ORDER
  910. #if __BYTE_ORDER == __BIG_ENDIAN
  911. swab (buf, buf, (CD_FRAMESIZE_RAW * FRAME_LEN));
  912. #endif
  913. #endif
  914. }
  915. return 1;
  916. }
  917. static int cdda_frame_seek(input_object *obj, int index)
  918. {
  919. struct cdda_local_data *data;
  920. if (!obj)
  921. return 0;
  922. data = (struct cdda_local_data *)obj->local_data;
  923. if (data)
  924. data->rel_pos = (index * FRAME_LEN);
  925. return 1;
  926. }
  927. static int cdda_frame_size(input_object *obj)
  928. {
  929. int size = (CD_FRAMESIZE_RAW * FRAME_LEN);
  930. return size;
  931. }
  932. static int cdda_nr_frames(input_object *obj)
  933. {
  934. struct cdda_local_data *data;
  935. int nr_frames = 0;
  936. if (!obj)
  937. return 0;
  938. data = (struct cdda_local_data *)obj->local_data;
  939. if (data)
  940. nr_frames = data->track_length >> 2;
  941. return nr_frames;
  942. }
  943. static long cdda_frame_to_sec(input_object *obj, int frame)
  944. {
  945. unsigned long byte_count = FRAME_LEN * frame * CD_FRAMESIZE_RAW;
  946. return (byte_count / 1764); /* 44Khz stereo 16 bit, fixed */
  947. /* 1764 = 176400 / 100 voor de 100ste seconden representatie */
  948. }
  949. static int cdda_sample_rate(input_object *obj)
  950. {
  951. struct cdda_local_data *data;
  952. if (!obj)
  953. return 0;
  954. data = (struct cdda_local_data *)obj->local_data;
  955. return (data ? data->samplerate : 0);
  956. }
  957. static int cdda_channels(input_object *obj)
  958. {
  959. if (!obj)
  960. return 0;
  961. return obj->nr_channels;
  962. }
  963. static int cdda_stream_info(input_object *obj, stream_info *info)
  964. {
  965. struct cdda_local_data *data;
  966. struct cd_trk_list *tl;
  967. if (!obj)
  968. return 0;
  969. data = (struct cdda_local_data *)obj->local_data;
  970. if (!data || !info)
  971. return 0;
  972. tl = &data->tl;
  973. sprintf(info->stream_type, "CD Audio, 44KHz, stereo");
  974. sprintf(info->artist, "%s", tracks[1].artist);
  975. sprintf(info->album, "%s", tracks[1].album);
  976. info->status[0] = 0;
  977. if (data->track_nr < 0)
  978. info->title[0] = 0;
  979. else if (data->track_nr == 0)
  980. sprintf(info->title, "Full CD length playback");
  981. else
  982. sprintf(info->title, "%s", tracks[data->track_nr].track);
  983. //alsaplayer_error("title = %s\nalbum = %s\nartist = %s",
  984. // info->title, info->album, info->artist);
  985. return 1;
  986. }
  987. static int cdda_nr_tracks(input_object *obj)
  988. {
  989. struct cdda_local_data *data;
  990. if (!obj)
  991. return 0;
  992. data = (struct cdda_local_data *)obj->local_data;
  993. if (!data)
  994. return 0;
  995. return data->tl.max;
  996. }
  997. static void cdda_shutdown(void)
  998. {
  999. return;
  1000. }
  1001. static int cdda_track_seek(input_object *obj, int track)
  1002. {
  1003. return 1;
  1004. }
  1005. static input_plugin cdda_plugin;
  1006. /*
  1007. = {
  1008. INPUT_PLUGIN_VERSION,
  1009. 0,
  1010. "CDDA player v1.1",
  1011. "Andy Lo A Foe <andy@alsaplayer.org>",
  1012. NULL,
  1013. cdda_init,
  1014. cdda_shutdown,
  1015. NULL,
  1016. cdda_can_handle,
  1017. cdda_open,
  1018. cdda_close,
  1019. cdda_play_frame,
  1020. cdda_frame_seek,
  1021. cdda_frame_size,
  1022. cdda_nr_frames,
  1023. cdda_frame_to_sec,
  1024. cdda_sample_rate,
  1025. cdda_channels,
  1026. cdda_stream_info,
  1027. cdda_nr_tracks,
  1028. cdda_track_seek
  1029. };
  1030. */
  1031. #ifdef __cplusplus
  1032. extern "C" {
  1033. #endif
  1034. input_plugin *input_plugin_info(void)
  1035. {
  1036. memset(&cdda_plugin, 0, sizeof(input_plugin));
  1037. cdda_plugin.version = INPUT_PLUGIN_VERSION;
  1038. cdda_plugin.name = "CDDA player v1.2";
  1039. cdda_plugin.author = "Andy Lo A Foe <andy@alsaplayer.org>";
  1040. cdda_plugin.init = cdda_init;
  1041. cdda_plugin.shutdown = cdda_shutdown;
  1042. cdda_plugin.can_handle = cdda_can_handle;
  1043. cdda_plugin.open = cdda_open;
  1044. cdda_plugin.close = cdda_close;
  1045. cdda_plugin.play_frame = cdda_play_frame;
  1046. cdda_plugin.frame_seek = cdda_frame_seek;
  1047. cdda_plugin.frame_size = cdda_frame_size;
  1048. cdda_plugin.nr_frames = cdda_nr_frames;
  1049. cdda_plugin.frame_to_sec = cdda_frame_to_sec;
  1050. cdda_plugin.sample_rate = cdda_sample_rate;
  1051. cdda_plugin.channels = cdda_channels;
  1052. cdda_plugin.stream_info = cdda_stream_info;
  1053. cdda_plugin.nr_tracks = cdda_nr_tracks;
  1054. cdda_plugin.track_seek = cdda_track_seek;
  1055. return &cdda_plugin;
  1056. }
  1057. #ifdef __cplusplus
  1058. }
  1059. #endif