rendered paste body/* xine_driver.c - Xine audio driver See README for Copyright and License*/#include "audio.h"#include "xine_driver.h"#include <stdlib.h>static xine_t *xine;static xine_stream_t *stream;static xine_stream_t *mstream;static xine_audio_port_t *ao_port;static xine_event_queue_t *event_queue;static char *audio_output;const char *AUDIO_get_driver(AUDIO_SESSION *s){ return audio_output;}int AUDIO_get_drivers(AUDIO_SESSION *s,char *buffer){ const char *const *driver_ids; int i,length; driver_ids = xine_list_audio_output_plugins (xine); length = sprintf(buffer,"%s,", "auto"); for(i=0;driver_ids[i];i++){ length += sprintf(buffer+length,"%s,", driver_ids[i]); } return 0;}int AUDIO_is_audio(AUDIO_SESSION *s,const char *url){ char *cptr; int rv; if(!url || !mstream){ printf("AUDIO_is_audio error\n"); return 1; } /* First Pass file filter */ cptr = strrchr(url,'.'); if(cptr){ /* In order from MOST likely to LEAST likely */ if(!strcasecmp(cptr,".jpg"))return 1; if(!strcasecmp(cptr,".png"))return 1; if(!strcasecmp(cptr,".gif"))return 1; if(!strcasecmp(cptr,".jpeg"))return 1; } if(!xine_open(mstream,url))return 1; /* Second Pass file filter */ /* FIXME: Find a better/faster way of filtering streams */ // Note: INFO_AUDIO_HANDLED is true for pictures rv = xine_get_stream_info(mstream,XINE_STREAM_INFO_AUDIO_HANDLED); xine_close(mstream); return !rv;}int AUDIO_get_metadata(AUDIO_SESSION *s, const char *url, AUDIO_metadata *mdata){ const char *info; int length=0; if(!mstream){ printf("AUDIO_get_metedata: No metadata stream loaded\n"); return 1; } /* Clear out the meta struct */ AUDIO_zero_metadata(mdata); if(!xine_open(mstream,url)){ printf("AUDIO_get_metedata: Could not open stream = '%s'\n",url); return 1; } /* Copy metadata into meta data struct */ info=xine_get_meta_info (mstream,XINE_META_INFO_TITLE ); if(info)strncpy(mdata->title,info,LONG_FIELD); info =xine_get_meta_info (mstream,XINE_META_INFO_ARTIST ); if(info)strncpy(mdata->artist,info,LONG_FIELD); info = xine_get_meta_info (mstream,XINE_META_INFO_ALBUM ); if(info)strncpy(mdata->album,info,LONG_FIELD); info = xine_get_meta_info (mstream,XINE_META_INFO_YEAR ); if(info)mdata->year = atoi(info); info = xine_get_meta_info (mstream,XINE_META_INFO_TRACK_NUMBER); /* info = "[Track No]/[Track Count]" */ if(info)mdata->track = atoi(info); xine_get_pos_length (mstream,NULL,NULL,&length); mdata->length = length / 1000; // xine gives us ms info = xine_get_meta_info (mstream,XINE_META_INFO_DISCNUMBER); if(info)mdata->disc = atoi(info); mdata->title [LONG_FIELD-1]=0; mdata->artist[LONG_FIELD-1]=0; mdata->album [LONG_FIELD-1]=0; xine_close(mstream); return 0;}int AUDIO_driver_init(AUDIO_SESSION *s, const char *audiodriver){ printf("XINE_driver - init, ao=%s\n",audiodriver); char configfile[256]; audio_output = NULL; xine = NULL; xine = xine_new(); sprintf(configfile, "%s/%s", getenv("HOME"), ".xine/config"); xine_config_load(xine,configfile); xine_init(xine); /* Open playback stream */ ao_port = xine_open_audio_driver(xine , audiodriver, NULL); stream = xine_stream_new(xine, ao_port,NULL); /* Register stream with event callback */ event_queue = xine_event_new_queue(stream); xine_event_create_listener_thread(event_queue, XINE_DRIVER_event_listener,s); /* Open a stream with no drivers for meta data collection */ mstream = xine_stream_new(xine, NULL,NULL); printf("Status: %i\n",xine_get_error(mstream)); if(!mstream){ printf("AUDIO init error\n"); return 1; } audio_output = strdup(audiodriver); return 0;}int AUDIO_play(AUDIO_SESSION *s,char *url, int seek){ int rv=0; if(url== NULL) goto just_play; xine_close(stream); // will this stop the leak? rv = xine_open(stream, url); /* XINE uses negative logic, 1=OK, 0=BAD */ if(!rv){ fprintf(stderr,"ERROR: AUDIO_play: Cannot open stream: %s\n",url); fprintf(stderr,"ERROR: AUDIO_play: Xine Error %i\n", xine_get_error(stream)); fprintf(stderr,"ERROR: AUDIO_play: Xine Status %i\n", xine_get_status(stream)); return 1; } if(s->url){ free(s->url); } s->url = strdup(url); /* Get the stream length for our audio session */ int blah; xine_get_pos_length(stream,&blah,&blah,&s->length); s->length = (s->length+500)/1000; // Xine returns in milliseconds time(&s->start_time); just_play: /* NULL position */ if(seek < 0 ) seek = 0; rv = xine_play(stream, 0, seek*1000); if(!rv){ fprintf(stderr,"ERROR: AUDIO_play: Cannot play stream: %s\n",url); return 1; } s->playing = 1; /* Dont inform the GUI if we are just seeking */ if(!seek && s->AUDIO_UI_caller){ s->AUDIO_UI_caller(AUDIO_START,s->cdata); } return 0;}int AUDIO_pause(AUDIO_SESSION *s){ int param; param = xine_get_param(stream,XINE_PARAM_SPEED); if(param == XINE_SPEED_PAUSE){ xine_set_param(stream,XINE_PARAM_SPEED,XINE_SPEED_NORMAL); return 0; }else if (param == XINE_SPEED_NORMAL){ xine_set_param(stream,XINE_PARAM_SPEED,XINE_SPEED_PAUSE); return 0; } return 1;}int AUDIO_stop(AUDIO_SESSION *s){ xine_stop(stream); s->playing =0; if(s->AUDIO_UI_caller)s->AUDIO_UI_caller(AUDIO_STOP,s->cdata); return 0;} int AUDIO_seek(AUDIO_SESSION *s, int time){ int rv = 0; int pos = 0; rv = AUDIO_get_position(s,&pos); rv = AUDIO_play(s,NULL,pos+time); return rv;}int AUDIO_driver_dinit(AUDIO_SESSION *s){ printf("audi dinit\n"); // xine_event_dispose_queue(event_queue); if(s==NULL)return 0; if(mstream)xine_dispose(mstream); if(stream)xine_dispose(stream); if(xine && ao_port){ xine_close_audio_driver(xine, ao_port); xine_exit(xine); } if(audio_output) free(audio_output); return 0;}int AUDIO_get_position(AUDIO_SESSION *s,int *pos_time){ int bl,ah; int rv; rv = xine_get_pos_length(stream,&bl,pos_time,&ah); /* Xine returns the time in milliseconds, so divide and round off*/ // 1 000 = 1s, 1 555 = 2s *pos_time = (*pos_time+500)/1000; return !rv;}static void XINE_DRIVER_event_listener(void *user_data, const xine_event_t *event) { AUDIO_SESSION *s; s = (AUDIO_SESSION*)user_data; switch(event->type) { case XINE_EVENT_UI_PLAYBACK_FINISHED: s->playing = 0; xine_close(stream); if(s->AUDIO_UI_caller) s->AUDIO_UI_caller(AUDIO_END,s->cdata); break; }}