|
Packit |
34410b |
/*
|
|
Packit |
34410b |
* Copyright (C) 2014 Intel Corporation
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
Packit |
34410b |
* you may not use this file except in compliance with the License.
|
|
Packit |
34410b |
* You may obtain a copy of the License at
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* http://www.apache.org/licenses/LICENSE-2.0
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
* Unless required by applicable law or agreed to in writing, software
|
|
Packit |
34410b |
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
Packit |
34410b |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
Packit |
34410b |
* See the License for the specific language governing permissions and
|
|
Packit |
34410b |
* limitations under the License.
|
|
Packit |
34410b |
*
|
|
Packit |
34410b |
*/
|
|
Packit |
34410b |
|
|
Packit |
34410b |
#define _GNU_SOURCE
|
|
Packit |
34410b |
#include <pthread.h>
|
|
Packit |
34410b |
#include <unistd.h>
|
|
Packit |
34410b |
#include <math.h>
|
|
Packit |
34410b |
|
|
Packit |
34410b |
#include "if-main.h"
|
|
Packit |
34410b |
#include "../hal-utils.h"
|
|
Packit |
34410b |
|
|
Packit |
34410b |
audio_hw_device_t *if_audio_sco = NULL;
|
|
Packit |
34410b |
static struct audio_stream_out *stream_out = NULL;
|
|
Packit |
34410b |
static struct audio_stream_in *stream_in = NULL;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static size_t buffer_size = 0;
|
|
Packit |
34410b |
static size_t buffer_size_in = 0;
|
|
Packit |
34410b |
static pthread_t play_thread = 0;
|
|
Packit |
34410b |
static pthread_mutex_t outstream_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
Packit |
34410b |
static pthread_mutex_t state_mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
enum state {
|
|
Packit |
34410b |
STATE_STOPPED,
|
|
Packit |
34410b |
STATE_STOPPING,
|
|
Packit |
34410b |
STATE_PLAYING,
|
|
Packit |
34410b |
STATE_SUSPENDED,
|
|
Packit |
34410b |
STATE_MAX
|
|
Packit |
34410b |
};
|
|
Packit |
34410b |
|
|
Packit |
34410b |
SINTMAP(audio_channel_mask_t, -1, "(AUDIO_CHANNEL_INVALID)")
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_FRONT_LEFT),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_FRONT_RIGHT),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_FRONT_CENTER),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_LOW_FREQUENCY),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_BACK_LEFT),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_BACK_RIGHT),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_FRONT_LEFT_OF_CENTER),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_FRONT_RIGHT_OF_CENTER),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_BACK_CENTER),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_SIDE_LEFT),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_SIDE_RIGHT),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_TOP_CENTER),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_TOP_FRONT_LEFT),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_TOP_FRONT_CENTER),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_TOP_FRONT_RIGHT),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_TOP_BACK_LEFT),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_TOP_BACK_CENTER),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_MONO),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_STEREO),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_QUAD),
|
|
Packit |
34410b |
#if ANDROID_VERSION < PLATFORM_VER(5, 0, 0)
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_SURROUND),
|
|
Packit |
34410b |
#else
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_QUAD_BACK),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_QUAD_SIDE),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_5POINT1_BACK),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_5POINT1_SIDE),
|
|
Packit |
34410b |
#endif
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_5POINT1),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_7POINT1),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_ALL),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_FRONT_LEFT),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_FRONT_LEFT),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_FRONT_LEFT),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_FRONT_LEFT),
|
|
Packit |
34410b |
DELEMENT(AUDIO_CHANNEL_OUT_FRONT_LEFT),
|
|
Packit |
34410b |
ENDMAP
|
|
Packit |
34410b |
|
|
Packit |
34410b |
SINTMAP(audio_format_t, -1, "(AUDIO_FORMAT_INVALID)")
|
|
Packit |
34410b |
DELEMENT(AUDIO_FORMAT_DEFAULT),
|
|
Packit |
34410b |
DELEMENT(AUDIO_FORMAT_PCM),
|
|
Packit |
34410b |
DELEMENT(AUDIO_FORMAT_MP3),
|
|
Packit |
34410b |
DELEMENT(AUDIO_FORMAT_AMR_NB),
|
|
Packit |
34410b |
DELEMENT(AUDIO_FORMAT_AMR_WB),
|
|
Packit |
34410b |
DELEMENT(AUDIO_FORMAT_AAC),
|
|
Packit |
34410b |
DELEMENT(AUDIO_FORMAT_HE_AAC_V1),
|
|
Packit |
34410b |
DELEMENT(AUDIO_FORMAT_HE_AAC_V2),
|
|
Packit |
34410b |
DELEMENT(AUDIO_FORMAT_VORBIS),
|
|
Packit |
34410b |
DELEMENT(AUDIO_FORMAT_MAIN_MASK),
|
|
Packit |
34410b |
DELEMENT(AUDIO_FORMAT_SUB_MASK),
|
|
Packit |
34410b |
DELEMENT(AUDIO_FORMAT_PCM_16_BIT),
|
|
Packit |
34410b |
DELEMENT(AUDIO_FORMAT_PCM_8_BIT),
|
|
Packit |
34410b |
DELEMENT(AUDIO_FORMAT_PCM_32_BIT),
|
|
Packit |
34410b |
DELEMENT(AUDIO_FORMAT_PCM_8_24_BIT),
|
|
Packit |
34410b |
ENDMAP
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static int current_state = STATE_STOPPED;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
#define SAMPLERATE 44100
|
|
Packit |
34410b |
static short sample[SAMPLERATE];
|
|
Packit |
34410b |
static uint16_t sample_pos;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static void init_p(int argc, const char **argv)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
int err;
|
|
Packit |
34410b |
const hw_module_t *module;
|
|
Packit |
34410b |
audio_hw_device_t *device;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
err = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, "sco", &module);
|
|
Packit |
34410b |
if (err) {
|
|
Packit |
34410b |
haltest_error("hw_get_module_by_class returned %d\n", err);
|
|
Packit |
34410b |
return;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
err = audio_hw_device_open(module, &device);
|
|
Packit |
34410b |
if (err) {
|
|
Packit |
34410b |
haltest_error("audio_hw_device_open returned %d\n", err);
|
|
Packit |
34410b |
return;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if_audio_sco = device;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static int feed_from_file(short *buffer, void *data)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
FILE *in = data;
|
|
Packit |
34410b |
return fread(buffer, buffer_size, 1, in);
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static int feed_from_generator(short *buffer, void *data)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
size_t i = 0;
|
|
Packit |
34410b |
float volume = 0.5;
|
|
Packit |
34410b |
float *freq = data;
|
|
Packit |
34410b |
float f = 1;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (freq)
|
|
Packit |
34410b |
f = *freq;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
/* buffer_size is in bytes but we are using buffer of shorts (2 bytes)*/
|
|
Packit |
34410b |
for (i = 0; i < buffer_size / sizeof(*buffer) - 1;) {
|
|
Packit |
34410b |
if (sample_pos >= SAMPLERATE)
|
|
Packit |
34410b |
sample_pos = sample_pos % SAMPLERATE;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
/* Use the same sample for both channels */
|
|
Packit |
34410b |
buffer[i++] = sample[sample_pos] * volume;
|
|
Packit |
34410b |
buffer[i++] = sample[sample_pos] * volume;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
sample_pos += f;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
return buffer_size;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static int feed_from_in(short *buffer, void *data)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
return stream_in->read(stream_in, buffer, buffer_size_in);
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static void prepare_sample(void)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
int x;
|
|
Packit |
34410b |
double s;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
haltest_info("Preparing audio sample...\n");
|
|
Packit |
34410b |
|
|
Packit |
34410b |
for (x = 0; x < SAMPLERATE; x++) {
|
|
Packit |
34410b |
/* prepare sinusoidal 1Hz sample */
|
|
Packit |
34410b |
s = (2.0 * 3.14159) * ((double)x / SAMPLERATE);
|
|
Packit |
34410b |
s = sin(s);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
/* remap <-1, 1> to signed 16bit PCM range */
|
|
Packit |
34410b |
sample[x] = s * 32767;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
sample_pos = 0;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static void mono_to_stereo_pcm16(const int16_t *in, int16_t *out, size_t samples)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
size_t i;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
for (i = 0; i < samples; i++) {
|
|
Packit |
34410b |
out[2 * i] = in[i];
|
|
Packit |
34410b |
out[2 * i + 1] = in[i];
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static void *playback_thread(void *data)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
int (*filbuff_cb) (short*, void*);
|
|
Packit |
34410b |
short buffer[buffer_size / sizeof(short)];
|
|
Packit |
34410b |
short buffer_in[buffer_size_in / sizeof(short)];
|
|
Packit |
34410b |
size_t len = 0;
|
|
Packit |
34410b |
ssize_t w_len = 0;
|
|
Packit |
34410b |
FILE *in = data;
|
|
Packit |
34410b |
void *cb_data = NULL;
|
|
Packit |
34410b |
float freq = 440.0;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
/* Use file or fall back to generator */
|
|
Packit |
34410b |
if (in) {
|
|
Packit |
34410b |
if (data == stream_in)
|
|
Packit |
34410b |
filbuff_cb = feed_from_in;
|
|
Packit |
34410b |
else {
|
|
Packit |
34410b |
filbuff_cb = feed_from_file;
|
|
Packit |
34410b |
cb_data = in;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
} else {
|
|
Packit |
34410b |
prepare_sample();
|
|
Packit |
34410b |
filbuff_cb = feed_from_generator;
|
|
Packit |
34410b |
cb_data = &fre;;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
pthread_mutex_lock(&state_mutex);
|
|
Packit |
34410b |
current_state = STATE_PLAYING;
|
|
Packit |
34410b |
pthread_mutex_unlock(&state_mutex);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
do {
|
|
Packit |
34410b |
pthread_mutex_lock(&state_mutex);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (current_state == STATE_STOPPING) {
|
|
Packit |
34410b |
haltest_info("Detected stopping\n");
|
|
Packit |
34410b |
pthread_mutex_unlock(&state_mutex);
|
|
Packit |
34410b |
break;
|
|
Packit |
34410b |
} else if (current_state == STATE_SUSPENDED) {
|
|
Packit |
34410b |
pthread_mutex_unlock(&state_mutex);
|
|
Packit |
34410b |
usleep(500);
|
|
Packit |
34410b |
continue;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
pthread_mutex_unlock(&state_mutex);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (data && data == stream_in) {
|
|
Packit |
34410b |
int chan_in = popcount(stream_in->common.get_channels(&stream_in->common));
|
|
Packit |
34410b |
int chan_out = popcount(stream_out->common.get_channels(&stream_out->common));
|
|
Packit |
34410b |
|
|
Packit |
34410b |
len = filbuff_cb(buffer_in, cb_data);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (chan_in == 1 && chan_out == 2) {
|
|
Packit |
34410b |
mono_to_stereo_pcm16(buffer_in,
|
|
Packit |
34410b |
buffer,
|
|
Packit |
34410b |
buffer_size_in / 2);
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
} else
|
|
Packit |
34410b |
len = filbuff_cb(buffer, cb_data);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
pthread_mutex_lock(&outstream_mutex);
|
|
Packit |
34410b |
if (!stream_out) {
|
|
Packit |
34410b |
pthread_mutex_unlock(&outstream_mutex);
|
|
Packit |
34410b |
break;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
w_len = stream_out->write(stream_out, buffer, buffer_size);
|
|
Packit |
34410b |
pthread_mutex_unlock(&outstream_mutex);
|
|
Packit |
34410b |
} while (len && w_len > 0);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (in && data != stream_in)
|
|
Packit |
34410b |
fclose(in);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
pthread_mutex_lock(&state_mutex);
|
|
Packit |
34410b |
current_state = STATE_STOPPED;
|
|
Packit |
34410b |
pthread_mutex_unlock(&state_mutex);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
haltest_info("Done playing.\n");
|
|
Packit |
34410b |
|
|
Packit |
34410b |
return NULL;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static void write_stereo_pcm16(const short *input, size_t len, FILE *out)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
short sample[2];
|
|
Packit |
34410b |
size_t i;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
for (i = 0; i < len / 2; i++) {
|
|
Packit |
34410b |
sample[0] = input[i];
|
|
Packit |
34410b |
sample[1] = input[i];
|
|
Packit |
34410b |
|
|
Packit |
34410b |
fwrite(sample, sizeof(sample), 1, out);
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static void *read_thread(void *data)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
int (*filbuff_cb) (short*, void*) = feed_from_in;
|
|
Packit |
34410b |
short buffer[buffer_size_in / sizeof(short)];
|
|
Packit |
34410b |
ssize_t len = 0;
|
|
Packit |
34410b |
void *cb_data = NULL;
|
|
Packit |
34410b |
FILE *out = data;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
pthread_mutex_lock(&state_mutex);
|
|
Packit |
34410b |
current_state = STATE_PLAYING;
|
|
Packit |
34410b |
pthread_mutex_unlock(&state_mutex);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
do {
|
|
Packit |
34410b |
pthread_mutex_lock(&state_mutex);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (current_state == STATE_STOPPING) {
|
|
Packit |
34410b |
haltest_info("Detected stopping\n");
|
|
Packit |
34410b |
pthread_mutex_unlock(&state_mutex);
|
|
Packit |
34410b |
break;
|
|
Packit |
34410b |
} else if (current_state == STATE_SUSPENDED) {
|
|
Packit |
34410b |
pthread_mutex_unlock(&state_mutex);
|
|
Packit |
34410b |
usleep(500);
|
|
Packit |
34410b |
continue;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
pthread_mutex_unlock(&state_mutex);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
len = filbuff_cb(buffer, cb_data);
|
|
Packit |
34410b |
if (len < 0) {
|
|
Packit |
34410b |
haltest_error("Error receiving SCO data");
|
|
Packit |
34410b |
break;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
haltest_info("Read %zd bytes\n", len);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (out) {
|
|
Packit |
34410b |
write_stereo_pcm16(buffer, len, out);
|
|
Packit |
34410b |
haltest_info("Written %zd bytes\n", len * 2);
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
} while (len);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (out)
|
|
Packit |
34410b |
fclose(out);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
pthread_mutex_lock(&state_mutex);
|
|
Packit |
34410b |
current_state = STATE_STOPPED;
|
|
Packit |
34410b |
pthread_mutex_unlock(&state_mutex);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
haltest_info("Done reading.\n");
|
|
Packit |
34410b |
|
|
Packit |
34410b |
return NULL;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static void play_p(int argc, const char **argv)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
const char *fname = NULL;
|
|
Packit |
34410b |
FILE *in = NULL;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
RETURN_IF_NULL(if_audio_sco);
|
|
Packit |
34410b |
RETURN_IF_NULL(stream_out);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (argc < 3) {
|
|
Packit |
34410b |
haltest_error("Invalid audio file path.\n");
|
|
Packit |
34410b |
haltest_info("Using sound generator.\n");
|
|
Packit |
34410b |
} else {
|
|
Packit |
34410b |
fname = argv[2];
|
|
Packit |
34410b |
in = fopen(fname, "r");
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (in == NULL) {
|
|
Packit |
34410b |
haltest_error("Cannot open file: %s\n", fname);
|
|
Packit |
34410b |
return;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
haltest_info("Playing file: %s\n", fname);
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (buffer_size == 0) {
|
|
Packit |
34410b |
haltest_error("Invalid buffer size. Was stream_out opened?\n");
|
|
Packit |
34410b |
goto fail;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
pthread_mutex_lock(&state_mutex);
|
|
Packit |
34410b |
if (current_state != STATE_STOPPED) {
|
|
Packit |
34410b |
haltest_error("Already playing or stream suspended!\n");
|
|
Packit |
34410b |
pthread_mutex_unlock(&state_mutex);
|
|
Packit |
34410b |
goto fail;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
pthread_mutex_unlock(&state_mutex);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (pthread_create(&play_thread, NULL, playback_thread, in) != 0) {
|
|
Packit |
34410b |
haltest_error("Cannot create playback thread!\n");
|
|
Packit |
34410b |
goto fail;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
return;
|
|
Packit |
34410b |
fail:
|
|
Packit |
34410b |
if (in)
|
|
Packit |
34410b |
fclose(in);
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static void loop_p(int argc, const char **argv)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
int chan_out, chan_in;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
RETURN_IF_NULL(if_audio_sco);
|
|
Packit |
34410b |
RETURN_IF_NULL(stream_out);
|
|
Packit |
34410b |
RETURN_IF_NULL(stream_in);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
chan_out = popcount(stream_out->common.get_channels(&stream_out->common));
|
|
Packit |
34410b |
chan_in = popcount(stream_in->common.get_channels(&stream_in->common));
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (!buffer_size || !buffer_size_in) {
|
|
Packit |
34410b |
haltest_error("Invalid buffer sizes. Streams opened\n");
|
|
Packit |
34410b |
return;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (buffer_size / chan_out != buffer_size_in / chan_in) {
|
|
Packit |
34410b |
haltest_error("read/write buffers differ, not supported\n");
|
|
Packit |
34410b |
return;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
pthread_mutex_lock(&state_mutex);
|
|
Packit |
34410b |
if (current_state != STATE_STOPPED) {
|
|
Packit |
34410b |
haltest_error("Already playing or stream suspended!\n");
|
|
Packit |
34410b |
pthread_mutex_unlock(&state_mutex);
|
|
Packit |
34410b |
return;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
pthread_mutex_unlock(&state_mutex);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (pthread_create(&play_thread, NULL, playback_thread,
|
|
Packit |
34410b |
stream_in) != 0)
|
|
Packit |
34410b |
haltest_error("Cannot create playback thread!\n");
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static void read_p(int argc, const char **argv)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
const char *fname = NULL;
|
|
Packit |
34410b |
FILE *out = NULL;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
RETURN_IF_NULL(if_audio_sco);
|
|
Packit |
34410b |
RETURN_IF_NULL(stream_in);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
pthread_mutex_lock(&state_mutex);
|
|
Packit |
34410b |
if (current_state != STATE_STOPPED) {
|
|
Packit |
34410b |
haltest_error("Already playing or stream suspended!\n");
|
|
Packit |
34410b |
pthread_mutex_unlock(&state_mutex);
|
|
Packit |
34410b |
return;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
pthread_mutex_unlock(&state_mutex);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (argc < 3) {
|
|
Packit |
34410b |
haltest_error("Invalid audio file path.\n");
|
|
Packit |
34410b |
haltest_info("Using read and through away\n");
|
|
Packit |
34410b |
} else {
|
|
Packit |
34410b |
fname = argv[2];
|
|
Packit |
34410b |
out = fopen(fname, "w");
|
|
Packit |
34410b |
if (!out) {
|
|
Packit |
34410b |
haltest_error("Cannot open file: %s\n", fname);
|
|
Packit |
34410b |
return;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
haltest_info("Reading to file: %s\n", fname);
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (!buffer_size_in) {
|
|
Packit |
34410b |
haltest_error("Invalid buffer size.\n");
|
|
Packit |
34410b |
goto failed;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (pthread_create(&play_thread, NULL, read_thread, out) != 0) {
|
|
Packit |
34410b |
haltest_error("Cannot create playback thread!\n");
|
|
Packit |
34410b |
goto failed;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
return;
|
|
Packit |
34410b |
failed:
|
|
Packit |
34410b |
if (out)
|
|
Packit |
34410b |
fclose(out);
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static void stop_p(int argc, const char **argv)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
RETURN_IF_NULL(if_audio_sco);
|
|
Packit |
34410b |
RETURN_IF_NULL(play_thread);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
pthread_mutex_lock(&state_mutex);
|
|
Packit |
34410b |
if (current_state == STATE_STOPPED || current_state == STATE_STOPPING) {
|
|
Packit |
34410b |
pthread_mutex_unlock(&state_mutex);
|
|
Packit |
34410b |
return;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (stream_out) {
|
|
Packit |
34410b |
pthread_mutex_lock(&outstream_mutex);
|
|
Packit |
34410b |
stream_out->common.standby(&stream_out->common);
|
|
Packit |
34410b |
pthread_mutex_unlock(&outstream_mutex);
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
current_state = STATE_STOPPING;
|
|
Packit |
34410b |
pthread_mutex_unlock(&state_mutex);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
pthread_join(play_thread, NULL);
|
|
Packit |
34410b |
play_thread = 0;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
haltest_info("Ended %s\n", __func__);
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static void open_output_stream_p(int argc, const char **argv)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
struct audio_config *config;
|
|
Packit |
34410b |
int err;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
RETURN_IF_NULL(if_audio_sco);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
pthread_mutex_lock(&state_mutex);
|
|
Packit |
34410b |
if (current_state == STATE_PLAYING) {
|
|
Packit |
34410b |
haltest_error("Already playing!\n");
|
|
Packit |
34410b |
pthread_mutex_unlock(&state_mutex);
|
|
Packit |
34410b |
return;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
pthread_mutex_unlock(&state_mutex);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (argc < 3) {
|
|
Packit |
34410b |
haltest_info("No sampling rate specified. Use default conf\n");
|
|
Packit |
34410b |
config = NULL;
|
|
Packit |
34410b |
} else {
|
|
Packit |
34410b |
config = calloc(1, sizeof(struct audio_config));
|
|
Packit |
34410b |
if (!config)
|
|
Packit |
34410b |
return;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
config->sample_rate = atoi(argv[2]);
|
|
Packit |
34410b |
config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
|
|
Packit |
34410b |
config->format = AUDIO_FORMAT_PCM_16_BIT;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
#if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
|
|
Packit |
34410b |
err = if_audio_sco->open_output_stream(if_audio_sco,
|
|
Packit |
34410b |
0,
|
|
Packit |
34410b |
AUDIO_DEVICE_OUT_ALL_SCO,
|
|
Packit |
34410b |
AUDIO_OUTPUT_FLAG_NONE,
|
|
Packit |
34410b |
config,
|
|
Packit |
34410b |
&stream_out, NULL);
|
|
Packit |
34410b |
#else
|
|
Packit |
34410b |
err = if_audio_sco->open_output_stream(if_audio_sco,
|
|
Packit |
34410b |
0,
|
|
Packit |
34410b |
AUDIO_DEVICE_OUT_ALL_SCO,
|
|
Packit |
34410b |
AUDIO_OUTPUT_FLAG_NONE,
|
|
Packit |
34410b |
config,
|
|
Packit |
34410b |
&stream_out);
|
|
Packit |
34410b |
#endif
|
|
Packit |
34410b |
if (err < 0) {
|
|
Packit |
34410b |
haltest_error("open output stream returned %d\n", err);
|
|
Packit |
34410b |
goto failed;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
buffer_size = stream_out->common.get_buffer_size(&stream_out->common);
|
|
Packit |
34410b |
if (buffer_size == 0)
|
|
Packit |
34410b |
haltest_error("Invalid buffer size received!\n");
|
|
Packit |
34410b |
else
|
|
Packit |
34410b |
haltest_info("Using buffer size: %zu\n", buffer_size);
|
|
Packit |
34410b |
failed:
|
|
Packit |
34410b |
if (config)
|
|
Packit |
34410b |
free(config);
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static void close_output_stream_p(int argc, const char **argv)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
RETURN_IF_NULL(if_audio_sco);
|
|
Packit |
34410b |
RETURN_IF_NULL(stream_out);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (play_thread)
|
|
Packit |
34410b |
stop_p(argc, argv);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if_audio_sco->close_output_stream(if_audio_sco, stream_out);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
stream_out = NULL;
|
|
Packit |
34410b |
buffer_size = 0;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static void open_input_stream_p(int argc, const char **argv)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
struct audio_config *config;
|
|
Packit |
34410b |
int err;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
RETURN_IF_NULL(if_audio_sco);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
pthread_mutex_lock(&state_mutex);
|
|
Packit |
34410b |
if (current_state == STATE_PLAYING) {
|
|
Packit |
34410b |
haltest_error("Already playing!\n");
|
|
Packit |
34410b |
pthread_mutex_unlock(&state_mutex);
|
|
Packit |
34410b |
return;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
pthread_mutex_unlock(&state_mutex);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (argc < 3) {
|
|
Packit |
34410b |
haltest_info("No sampling rate specified. Use default conf\n");
|
|
Packit |
34410b |
config = NULL;
|
|
Packit |
34410b |
} else {
|
|
Packit |
34410b |
config = calloc(1, sizeof(struct audio_config));
|
|
Packit |
34410b |
if (!config)
|
|
Packit |
34410b |
return;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
config->sample_rate = atoi(argv[2]);
|
|
Packit |
34410b |
config->channel_mask = AUDIO_CHANNEL_OUT_MONO;
|
|
Packit |
34410b |
config->format = AUDIO_FORMAT_PCM_16_BIT;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
#if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
|
|
Packit |
34410b |
err = if_audio_sco->open_input_stream(if_audio_sco,
|
|
Packit |
34410b |
0,
|
|
Packit |
34410b |
AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
|
|
Packit |
34410b |
config,
|
|
Packit |
34410b |
&stream_in, 0, NULL, 0);
|
|
Packit |
34410b |
#else
|
|
Packit |
34410b |
err = if_audio_sco->open_input_stream(if_audio_sco,
|
|
Packit |
34410b |
0,
|
|
Packit |
34410b |
AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET,
|
|
Packit |
34410b |
config,
|
|
Packit |
34410b |
&stream_in);
|
|
Packit |
34410b |
#endif
|
|
Packit |
34410b |
if (err < 0) {
|
|
Packit |
34410b |
haltest_error("open output stream returned %d\n", err);
|
|
Packit |
34410b |
goto failed;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
buffer_size_in = stream_in->common.get_buffer_size(&stream_in->common);
|
|
Packit |
34410b |
if (buffer_size_in == 0)
|
|
Packit |
34410b |
haltest_error("Invalid buffer size received!\n");
|
|
Packit |
34410b |
else
|
|
Packit |
34410b |
haltest_info("Using buffer size: %zu\n", buffer_size_in);
|
|
Packit |
34410b |
failed:
|
|
Packit |
34410b |
if (config)
|
|
Packit |
34410b |
free(config);
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static void close_input_stream_p(int argc, const char **argv)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
RETURN_IF_NULL(if_audio_sco);
|
|
Packit |
34410b |
RETURN_IF_NULL(stream_in);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (play_thread)
|
|
Packit |
34410b |
stop_p(argc, argv);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if_audio_sco->close_input_stream(if_audio_sco, stream_in);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
stream_in = NULL;
|
|
Packit |
34410b |
buffer_size_in = 0;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static void cleanup_p(int argc, const char **argv)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
int err;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
RETURN_IF_NULL(if_audio_sco);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
pthread_mutex_lock(&state_mutex);
|
|
Packit |
34410b |
if (current_state != STATE_STOPPED) {
|
|
Packit |
34410b |
pthread_mutex_unlock(&state_mutex);
|
|
Packit |
34410b |
close_output_stream_p(0, NULL);
|
|
Packit |
34410b |
} else {
|
|
Packit |
34410b |
pthread_mutex_unlock(&state_mutex);
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
err = audio_hw_device_close(if_audio_sco);
|
|
Packit |
34410b |
if (err < 0) {
|
|
Packit |
34410b |
haltest_error("audio_hw_device_close returned %d\n", err);
|
|
Packit |
34410b |
return;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if_audio_sco = NULL;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static void suspend_p(int argc, const char **argv)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
RETURN_IF_NULL(if_audio_sco);
|
|
Packit |
34410b |
RETURN_IF_NULL(stream_out);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
pthread_mutex_lock(&state_mutex);
|
|
Packit |
34410b |
if (current_state != STATE_PLAYING) {
|
|
Packit |
34410b |
pthread_mutex_unlock(&state_mutex);
|
|
Packit |
34410b |
return;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
current_state = STATE_SUSPENDED;
|
|
Packit |
34410b |
pthread_mutex_unlock(&state_mutex);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
pthread_mutex_lock(&outstream_mutex);
|
|
Packit |
34410b |
stream_out->common.standby(&stream_out->common);
|
|
Packit |
34410b |
pthread_mutex_unlock(&outstream_mutex);
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static void resume_p(int argc, const char **argv)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
RETURN_IF_NULL(if_audio_sco);
|
|
Packit |
34410b |
RETURN_IF_NULL(stream_out);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
pthread_mutex_lock(&state_mutex);
|
|
Packit |
34410b |
if (current_state == STATE_SUSPENDED)
|
|
Packit |
34410b |
current_state = STATE_PLAYING;
|
|
Packit |
34410b |
pthread_mutex_unlock(&state_mutex);
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static void get_latency_p(int argc, const char **argv)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
RETURN_IF_NULL(if_audio_sco);
|
|
Packit |
34410b |
RETURN_IF_NULL(stream_out);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
haltest_info("Output audio stream latency: %d\n",
|
|
Packit |
34410b |
stream_out->get_latency(stream_out));
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static void get_buffer_size_p(int argc, const char **argv)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
RETURN_IF_NULL(if_audio_sco);
|
|
Packit |
34410b |
RETURN_IF_NULL(stream_out);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
haltest_info("Current output buffer size: %zu\n",
|
|
Packit |
34410b |
stream_out->common.get_buffer_size(&stream_out->common));
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static void get_channels_p(int argc, const char **argv)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
audio_channel_mask_t channels;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
RETURN_IF_NULL(if_audio_sco);
|
|
Packit |
34410b |
RETURN_IF_NULL(stream_out);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
channels = stream_out->common.get_channels(&stream_out->common);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
haltest_info("Channels: %s\n", audio_channel_mask_t2str(channels));
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static void get_format_p(int argc, const char **argv)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
audio_format_t format;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
RETURN_IF_NULL(if_audio_sco);
|
|
Packit |
34410b |
RETURN_IF_NULL(stream_out);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
format = stream_out->common.get_format(&stream_out->common);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
haltest_info("Format: %s\n", audio_format_t2str(format));
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static void get_sample_rate_p(int argc, const char **argv)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
RETURN_IF_NULL(if_audio_sco);
|
|
Packit |
34410b |
RETURN_IF_NULL(stream_out);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
haltest_info("Current sample rate: %d\n",
|
|
Packit |
34410b |
stream_out->common.get_sample_rate(&stream_out->common));
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static void get_parameters_p(int argc, const char **argv)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
const char *keystr;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
RETURN_IF_NULL(if_audio_sco);
|
|
Packit |
34410b |
RETURN_IF_NULL(stream_out);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (argc < 3) {
|
|
Packit |
34410b |
haltest_info("No keys given.\n");
|
|
Packit |
34410b |
keystr = "";
|
|
Packit |
34410b |
} else {
|
|
Packit |
34410b |
keystr = argv[2];
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
haltest_info("Current parameters: %s\n",
|
|
Packit |
34410b |
stream_out->common.get_parameters(&stream_out->common,
|
|
Packit |
34410b |
keystr));
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static void set_parameters_p(int argc, const char **argv)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
RETURN_IF_NULL(if_audio_sco);
|
|
Packit |
34410b |
RETURN_IF_NULL(stream_out);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (argc < 3) {
|
|
Packit |
34410b |
haltest_error("No key=value; pairs given.\n");
|
|
Packit |
34410b |
return;
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
stream_out->common.set_parameters(&stream_out->common, argv[2]);
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static void set_sample_rate_p(int argc, const char **argv)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
RETURN_IF_NULL(if_audio_sco);
|
|
Packit |
34410b |
RETURN_IF_NULL(stream_out);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
if (argc < 3)
|
|
Packit |
34410b |
return;
|
|
Packit |
34410b |
|
|
Packit |
34410b |
stream_out->common.set_sample_rate(&stream_out->common, atoi(argv[2]));
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static void init_check_p(int argc, const char **argv)
|
|
Packit |
34410b |
{
|
|
Packit |
34410b |
RETURN_IF_NULL(if_audio_sco);
|
|
Packit |
34410b |
|
|
Packit |
34410b |
haltest_info("Init check result: %d\n",
|
|
Packit |
34410b |
if_audio_sco->init_check(if_audio_sco));
|
|
Packit |
34410b |
}
|
|
Packit |
34410b |
|
|
Packit |
34410b |
static struct method methods[] = {
|
|
Packit |
34410b |
STD_METHOD(init),
|
|
Packit |
34410b |
STD_METHOD(cleanup),
|
|
Packit |
34410b |
STD_METHODH(open_output_stream, "sample_rate"),
|
|
Packit |
34410b |
STD_METHOD(close_output_stream),
|
|
Packit |
34410b |
STD_METHODH(open_input_stream, "sampling rate"),
|
|
Packit |
34410b |
STD_METHOD(close_input_stream),
|
|
Packit |
34410b |
STD_METHODH(play, "<path to pcm file>"),
|
|
Packit |
34410b |
STD_METHOD(read),
|
|
Packit |
34410b |
STD_METHOD(loop),
|
|
Packit |
34410b |
STD_METHOD(stop),
|
|
Packit |
34410b |
STD_METHOD(suspend),
|
|
Packit |
34410b |
STD_METHOD(resume),
|
|
Packit |
34410b |
STD_METHOD(get_latency),
|
|
Packit |
34410b |
STD_METHOD(get_buffer_size),
|
|
Packit |
34410b |
STD_METHOD(get_channels),
|
|
Packit |
34410b |
STD_METHOD(get_format),
|
|
Packit |
34410b |
STD_METHOD(get_sample_rate),
|
|
Packit |
34410b |
STD_METHODH(get_parameters, "<closing>"),
|
|
Packit |
34410b |
STD_METHODH(set_parameters, "<closing=value>"),
|
|
Packit |
34410b |
STD_METHODH(set_sample_rate, "<sample rate>"),
|
|
Packit |
34410b |
STD_METHOD(init_check),
|
|
Packit |
34410b |
END_METHOD
|
|
Packit |
34410b |
};
|
|
Packit |
34410b |
|
|
Packit |
34410b |
const struct interface sco_if = {
|
|
Packit |
34410b |
.name = "sco",
|
|
Packit |
34410b |
.methods = methods
|
|
Packit |
34410b |
};
|