static int pls_next_open(auds_t *auds, pls_t *pls) { size_t len=1024; char *line=(char *)malloc(len); int lsize,lp,i, findex; if(auds->auds) auds_close(auds->auds); auds->auds=NULL; if(!line) return -1; pls->index++; while((lsize=getline(&line,&len,pls->inf))>0){ if(strstr(line,"File")!=line) continue; str_termlf(line); for(i=4;i<lsize;i++){ if(line[i]!='=') continue; lp=i+1; line[i]=0; findex=atoi(line+4); if(pls->index!=findex) break; if((auds->auds=auds_open(line+lp, 0))) return 0; return -1; } } return -1; }
static int main_event_handler() { fd_set rdfds,wrfds; int fdmax=0; int i; struct timeval tout={.tv_sec=MAIN_EVENT_TIMEOUT, .tv_usec=0}; FD_ZERO(&rdfds); FD_ZERO(&wrfds); for(i=0;i<MAX_NUM_OF_FDS;i++){ if(raopld->fds[i].fd<0) continue; if(raopld->fds[i].flags&RAOP_FD_READ) FD_SET(raopld->fds[i].fd, &rdfds); if(raopld->fds[i].flags&RAOP_FD_WRITE) FD_SET(raopld->fds[i].fd, &wrfds); fdmax=(fdmax<raopld->fds[i].fd)?raopld->fds[i].fd:fdmax; } if(raopcl_wait_songdone(raopld->raopcl,0)) raopcl_aexbuf_time(raopld->raopcl, &tout); select(fdmax+1,&rdfds,&wrfds,NULL,&tout); for(i=0;i<MAX_NUM_OF_FDS;i++){ if(raopld->fds[i].fd<0) continue; if((raopld->fds[i].flags&RAOP_FD_READ) && FD_ISSET(raopld->fds[i].fd,&rdfds)){ //DBGMSG("rd event i=%d, flags=%d\n",i,raopld->fds[i].flags); if(raopld->fds[i].cbf && raopld->fds[i].cbf(raopld->fds[i].dp, RAOP_FD_READ)) return -1; } if((raopld->fds[i].flags&RAOP_FD_WRITE) && FD_ISSET(raopld->fds[i].fd,&wrfds)){ //DBGMSG("wr event i=%d, flags=%d\n",i,raopld->fds[i].flags); if(raopld->fds[i].cbf && raopld->fds[i].cbf(raopld->fds[i].dp, RAOP_FD_WRITE)) return -1; } } if(raopcl_wait_songdone(raopld->raopcl,0)){ raopcl_aexbuf_time(raopld->raopcl, &tout); if(!tout.tv_sec && !tout.tv_usec){ // AEX data buffer becomes empty, it means end of playing a song. printf("%s\n",RAOP_SONGDONE); fflush(stdout); raopcl_wait_songdone(raopld->raopcl,-1); // clear wait_songdone } } raopcl_pause_check(raopld->raopcl); return 0; } static int console_command(char *cstr) { int i; char *ps=NULL; if(strstr(cstr,"play")==cstr){ if(raopcl_get_pause(raopld->raopcl)) { raopcl_set_pause(raopld->raopcl,NO_PAUSE); return 0; } for(i=0;i<strlen(cstr);i++) { if(cstr[i]==' ') { ps=cstr+i+1; break; } } if(!ps) return 0; // if there is a new song name, open the song if(!(raopld->auds=auds_open(ps, 0))){ printf("%s\n",RAOP_ERROR); fflush(stdout); return -1; } raopcl_flush_stream(raopld->raopcl); return 0; }else if(!strcmp(cstr,"pause")){ if(raopcl_wait_songdone(raopld->raopcl,0)){ INFMSG("in this period, pause can't work\n"); return -2; } if(raopld->auds) { raopcl_set_pause(raopld->raopcl,OP_PAUSE); } }else if(!strcmp(cstr,"stop")){ if(raopcl_get_pause(raopld->raopcl)) raopcl_set_pause(raopld->raopcl,NO_PAUSE); if(raopld->auds) auds_close(raopld->auds); raopld->auds=NULL; }else if(!strcmp(cstr,"quit")){ return -2; }else if((ps=strstr(cstr,"volume"))){ i=atoi(ps+7); return raopcl_update_volume(raopld->raopcl,i); } return -1; }
int main(int argc, char *argv[]) { char *host=NULL; char *fname=NULL; int port=SERVER_PORT; int rval=-1,i; int size; int volume=100; __u8 *buf; int iact=0; struct sigaction act; /* Assign sig_term as our SIGTERM handler */ act.sa_sigaction = sig_action; sigemptyset(&act.sa_mask); // no other signals are blocked act.sa_flags = SA_SIGINFO; // use sa_sigaction instead of sa_handler sigaction(SIGTERM, &act, NULL); sigaction(SIGINT, &act, NULL); sigaction(SIGCHLD, &act, NULL); for(i=1;i<argc;i++){ if(!strcmp(argv[i],"-i")){ iact=1; continue; } if(!strcmp(argv[i],"--port")){ port=atoi(argv[++i]); continue; } if(!strcmp(argv[i],"--vol")){ volume=atoi(argv[++i]); continue; } if(!strcmp(argv[i],"--help") || !strcmp(argv[i],"-h")) return print_usage(argv); if(!host) {host=argv[i]; continue;} if(!fname) {fname=argv[i]; continue;} } if(!host) return print_usage(argv); if(!iact && !fname) return print_usage(argv); raopld=(raopld_t*)malloc(sizeof(raopld_t)); if(!raopld) goto erexit; memset(raopld,0,sizeof(raopld_t)); for(i=0;i<MAX_NUM_OF_FDS;i++) raopld->fds[i].fd=-1; raopld->raopcl=raopcl_open(); if(!raopld->raopcl) goto erexit; if(raopcl_connect(raopld->raopcl,host,port)) goto erexit; if(raopcl_update_volume(raopld->raopcl,volume)) goto erexit; printf("%s\n",RAOP_CONNECTED); fflush(stdout); if(fname && !(raopld->auds=auds_open(fname,0))) goto erexit; set_fd_event(0,RAOP_FD_READ,console_read,NULL); rval=0; while(!rval){ if(!raopld->auds){ // if audio data is not opened, just check events rval=main_event_handler(raopld); continue; } switch(raopcl_get_pause(raopld->raopcl)){ case OP_PAUSE: rval=main_event_handler(); continue; case NODATA_PAUSE: if(auds_poll_next_sample(raopld->auds)){ raopcl_set_pause(raopld->raopcl,NO_PAUSE); }else{ rval=main_event_handler(); continue; } case NO_PAUSE: if(!auds_poll_next_sample(raopld->auds)){ // no next data, turn into pause status raopcl_set_pause(raopld->raopcl,NODATA_PAUSE); continue; } if(auds_get_next_sample(raopld->auds, &buf, &size)){ auds_close(raopld->auds); raopld->auds=NULL; raopcl_wait_songdone(raopld->raopcl,1); } if(raopcl_send_sample(raopld->raopcl,buf,size)) break; do{ if((rval=main_event_handler())) break; }while(raopld->auds && raopcl_sample_remsize(raopld->raopcl)); break; default: rval=-1; break; } } rval=raopcl_close(raopld->raopcl); erexit: if(raopld->auds) auds_close(raopld->auds); if(raopld) free(raopld); return rval; }