>void (*)(void))ev.data);
break;
default:
LOGFQUEUE("codec < default : %ld", ev.id);
}
}
}
/** --- Miscellaneous external interfaces -- **/
/* Initialize playback's codec interface */
void INIT_ATTR codec_thread_init(void)
{
/* Init API */
ci.dsp = dsp_get_config(CODEC_IDX_AUDIO);
ci.codec_get_buffer = codec_get_buffer_callback;
ci.pcmbuf_insert = codec_pcmbuf_insert_callback;
ci.set_elapsed = audio_codec_update_elapsed;
ci.read_filebuf = codec_filebuf_callback;
ci.request_buffer = codec_request_buffer_callback;
ci.advance_buffer = codec_advance_buffer_callback;
ci.seek_buffer = codec_seek_buffer_callback;
ci.seek_complete = codec_seek_complete_callback;
ci.set_offset = audio_codec_update_offset;
ci.configure = codec_configure_callback;
ci.get_command = codec_get_command_callback;
ci.loop_track = codec_loop_track_callback;
/* Init threading */
queue_init(&codec_queue, false);
codec_thread_id = create_thread(
codec_thread, codec_stack, sizeof(codec_stack), 0,
codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK)
IF_COP(, CPU));
queue_enable_queue_send(&codec_queue, &codec_queue_sender_list,
codec_thread_id);
}
#ifdef HAVE_PRIORITY_SCHEDULING
/* Obtain codec thread's current priority */
int codec_thread_get_priority(void)
{
return thread_get_priority(codec_thread_id);
}
/* Set the codec thread's priority and return the old value */
int codec_thread_set_priority(int priority)
{
return thread_set_priority(codec_thread_id, priority);
}
#endif /* HAVE_PRIORITY_SCHEDULING */
/** --- Functions for audio thread use --- **/
/* Load a decoder or encoder and set the format type */
bool codec_load(int hid, int cod_spec)
{
struct codec_load_info parm = { hid, cod_spec };
LOGFQUEUE("audio >| codec Q_CODEC_LOAD: %d, %d", hid, cod_spec);
return codec_queue_send(Q_CODEC_LOAD, (intptr_t)&parm) != 0;
}
/* Begin decoding the current file */
void codec_go(void)
{
LOGFQUEUE("audio >| codec Q_CODEC_RUN");
codec_queue_send(Q_CODEC_RUN, 0);
}
/* Instruct the codec to seek to the specified time (should be properly
paused or stopped first to avoid possible buffering deadlock) */
void codec_seek(long time)
{
LOGFQUEUE("audio > codec Q_CODEC_SEEK: %ld", time);
codec_queue_send(Q_CODEC_SEEK, time);
}
/* Pause the codec and make it wait for further instructions inside the
command callback */
bool codec_pause(void)
{
LOGFQUEUE("audio >| codec Q_CODEC_PAUSE");
return codec_queue_send(Q_CODEC_PAUSE, 0) != Q_NULL;
}
/* Stop codec if running - codec stays resident if loaded */
void codec_stop(void)
{
/* Wait until it's in the main loop */
LOGFQUEUE("audio >| codec Q_CODEC_STOP: 0");
while (codec_queue_send(Q_CODEC_STOP, 0) != Q_NULL);
}
#ifdef HAVE_RECORDING
/* Tells codec to take final encoding step and then exit -
Returns minimum buffer size required or 0 if complete */
size_t codec_finish_stream(void)
{
size_t size = 0;
LOGFQUEUE("audio >| codec Q_CODEC_STOP: &size");
if (codec_queue_send(Q_CODEC_STOP, (intptr_t)&size) != Q_NULL)
{
/* Sync to keep size in scope and get response */
LOGFQUEUE("audio >| codec Q_NULL");
codec_queue_send(Q_NULL, 0);
if (size == 0)
codec_stop(); /* Replied with 0 size */
}
/* else thread running in the main loop */
return size;
}
#endif /* HAVE_RECORDING */
/* Call the codec's exit routine and close all references */
void codec_unload(void)
{
codec_stop();
LOGFQUEUE("audio >| codec Q_CODEC_UNLOAD");
codec_queue_send(Q_CODEC_UNLOAD, 0);
}
/* Return the afmt type of the loaded codec - sticks until calling
codec_unload unless initial load failed */
int codec_loaded(void)
{
return codec_type;
}
|