forked from enlightenment/efl
see how much morte code i had to add just to use eina_log gustavo? i
had to add eina_init() and shutdown and init refcounting and log domain creating and add a macro.. so i can finally use it? eina being included here actually was never needed... but since include was there i could use it... just saying - using eina_log is not convenient. it doesn't save time. it's benefits are dubious (knowing what envv ar to set to what values to get log output is black magic as u need to know specific log level values and log domain names which u only find out by digging thru code). my point -> if u want eina_log used more.. it needs to be AS EASY as the printf. :) SVN revision: 64937
This commit is contained in:
parent
44d95d00ea
commit
c7e7c3043e
|
@ -10,13 +10,16 @@
|
||||||
#include <remix/remix.h>
|
#include <remix/remix.h>
|
||||||
#include <alsa/asoundlib.h>
|
#include <alsa/asoundlib.h>
|
||||||
#include <Eina.h>
|
#include <Eina.h>
|
||||||
|
#ifdef HAVE_LIBSNDFILE
|
||||||
|
#include <sndfile.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define ALSA_PLAYER_BUFFERLEN 2048
|
#define ALSA_PLAYER_BUFFERLEN 2048
|
||||||
|
|
||||||
typedef struct _AlsaPlayerData AlsaPlayerData;
|
typedef struct _Alsa_Player_Data Alsa_Player_Data;
|
||||||
typedef short PLAYER_PCM;
|
typedef short PLAYER_PCM;
|
||||||
|
|
||||||
struct _AlsaPlayerData
|
struct _Alsa_Player_Data
|
||||||
{
|
{
|
||||||
RemixPCM databuffer[ALSA_PLAYER_BUFFERLEN];
|
RemixPCM databuffer[ALSA_PLAYER_BUFFERLEN];
|
||||||
snd_pcm_t *alsa_dev;
|
snd_pcm_t *alsa_dev;
|
||||||
|
@ -25,17 +28,28 @@ struct _AlsaPlayerData
|
||||||
unsigned int frequency;
|
unsigned int frequency;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int _log_dom = -1;
|
||||||
|
static int init_count = 0;
|
||||||
|
|
||||||
|
#ifdef WRN
|
||||||
|
# undef WRN
|
||||||
|
#endif
|
||||||
|
#define WRN(...) EINA_LOG_DOM_WARN(_log_dom, __VA_ARGS__)
|
||||||
|
|
||||||
|
//#define MIXDBG 1
|
||||||
|
|
||||||
/* Optimisation dependencies: none */
|
/* Optimisation dependencies: none */
|
||||||
static RemixBase *alsa_player_optimise(RemixEnv *env, RemixBase *base);
|
static RemixBase *alsa_player_optimise(RemixEnv *env, RemixBase *base);
|
||||||
|
|
||||||
static snd_pcm_t *
|
static snd_pcm_t *
|
||||||
alsa_open(int channels, unsigned samplerate)
|
alsa_open(int channels, unsigned int samplerate, unsigned int *real_samplerate)
|
||||||
{
|
{
|
||||||
const char *device = "default";
|
const char *device = "default";
|
||||||
snd_pcm_t *alsa_dev = NULL;
|
snd_pcm_t *alsa_dev = NULL;
|
||||||
snd_pcm_hw_params_t *hw_params;
|
snd_pcm_hw_params_t *hw_params;
|
||||||
snd_pcm_uframes_t alsa_buffer_frames;
|
snd_pcm_uframes_t alsa_buffer_frames;
|
||||||
snd_pcm_uframes_t alsa_period_size;
|
snd_pcm_uframes_t alsa_period_size;
|
||||||
|
unsigned int samplerate_ret = 0;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
alsa_buffer_frames = ALSA_PLAYER_BUFFERLEN;
|
alsa_buffer_frames = ALSA_PLAYER_BUFFERLEN;
|
||||||
|
@ -43,67 +57,76 @@ alsa_open(int channels, unsigned samplerate)
|
||||||
|
|
||||||
if ((err = snd_pcm_open(&alsa_dev, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0)
|
if ((err = snd_pcm_open(&alsa_dev, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0)
|
||||||
{
|
{
|
||||||
printf("cannot open alsa playback stream (%s)\n", snd_strerror(err));
|
WRN("cannot open alsa playback stream (%s)\n", snd_strerror(err));
|
||||||
goto catch_error;
|
|
||||||
}
|
|
||||||
if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0)
|
|
||||||
{
|
|
||||||
printf("cannot alloc snd hw params (%s)\n", snd_strerror(err));
|
|
||||||
goto catch_error;
|
goto catch_error;
|
||||||
}
|
}
|
||||||
|
snd_pcm_hw_params_alloca(&hw_params);
|
||||||
if ((err = snd_pcm_hw_params_any(alsa_dev, hw_params)) < 0)
|
if ((err = snd_pcm_hw_params_any(alsa_dev, hw_params)) < 0)
|
||||||
{
|
{
|
||||||
printf("cannot initialize snd hw params (%s)\n", snd_strerror(err));
|
WRN("cannot initialize snd hw params (%s)\n", snd_strerror(err));
|
||||||
goto catch_error;
|
goto catch_error;
|
||||||
}
|
}
|
||||||
if ((err = snd_pcm_hw_params_set_access(alsa_dev, hw_params,
|
if ((err = snd_pcm_hw_params_set_access(alsa_dev, hw_params,
|
||||||
SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
|
SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
|
||||||
{
|
{
|
||||||
printf("cannot set access type (%s)\n", snd_strerror(err));
|
WRN("cannot set interleaved access (%s)\n", snd_strerror(err));
|
||||||
goto catch_error;
|
goto catch_error;
|
||||||
}
|
}
|
||||||
if ((err = snd_pcm_hw_params_set_format(alsa_dev, hw_params,
|
if ((err = snd_pcm_hw_params_set_format(alsa_dev, hw_params,
|
||||||
SND_PCM_FORMAT_FLOAT)) < 0)
|
SND_PCM_FORMAT_FLOAT)) < 0)
|
||||||
{
|
{
|
||||||
// FIXME: handle if float format not possible
|
WRN("cannot set float sample format (%s)\n", snd_strerror(err));
|
||||||
printf("cannot set sample format (%s)\n", snd_strerror(err));
|
|
||||||
goto catch_error;
|
goto catch_error;
|
||||||
}
|
}
|
||||||
|
#ifdef MIXDBG // testing/debugging by making output samplerate be 48khz
|
||||||
|
samplerate_ret = 48000;
|
||||||
|
if ((err = snd_pcm_hw_params_set_rate_near(alsa_dev, hw_params,
|
||||||
|
&samplerate_ret, 0)) < 0)
|
||||||
|
{
|
||||||
|
WRN("cannot set sample rate (%s)\n", snd_strerror(err));
|
||||||
|
goto catch_error;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if ((err = snd_pcm_hw_params_set_rate_near(alsa_dev, hw_params,
|
if ((err = snd_pcm_hw_params_set_rate_near(alsa_dev, hw_params,
|
||||||
&samplerate, 0)) < 0)
|
&samplerate, 0)) < 0)
|
||||||
{
|
{
|
||||||
// FIXME: get actual sample rate and tell remix
|
WRN("cannot set sample rate (%s)\n", snd_strerror(err));
|
||||||
printf("cannot set sample rate (%s)\n", snd_strerror(err));
|
|
||||||
goto catch_error;
|
goto catch_error;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if ((err = snd_pcm_hw_params_set_channels(alsa_dev, hw_params, channels)) < 0)
|
if ((err = snd_pcm_hw_params_set_channels(alsa_dev, hw_params, channels)) < 0)
|
||||||
{
|
{
|
||||||
printf("cannot set channel count (%s)\n", snd_strerror(err));
|
WRN("cannot set channel count (%s)\n", snd_strerror(err));
|
||||||
goto catch_error;
|
goto catch_error;
|
||||||
}
|
}
|
||||||
if ((err = snd_pcm_hw_params_set_buffer_size_near(alsa_dev, hw_params,
|
if ((err = snd_pcm_hw_params_set_buffer_size_near(alsa_dev, hw_params,
|
||||||
&alsa_buffer_frames)) < 0)
|
&alsa_buffer_frames)) < 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "cannot set buffer size (%s)\n", snd_strerror(err));
|
WRN("cannot set buffer size (%s)\n", snd_strerror(err));
|
||||||
goto catch_error;
|
goto catch_error;
|
||||||
}
|
}
|
||||||
if ((err = snd_pcm_hw_params_set_period_size_near(alsa_dev, hw_params,
|
if ((err = snd_pcm_hw_params_set_period_size_near(alsa_dev, hw_params,
|
||||||
&alsa_period_size, 0)) < 0)
|
&alsa_period_size, 0)) < 0)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "cannot set period size (%s)\n", snd_strerror(err));
|
WRN("cannot set period size (%s)\n", snd_strerror(err));
|
||||||
goto catch_error;
|
goto catch_error;
|
||||||
}
|
}
|
||||||
if ((err = snd_pcm_hw_params(alsa_dev, hw_params)) < 0)
|
if ((err = snd_pcm_hw_params(alsa_dev, hw_params)) < 0)
|
||||||
{
|
{
|
||||||
printf("cannot set parameters (%s)\n", snd_strerror(err));
|
WRN("cannot set parameters (%s)\n", snd_strerror(err));
|
||||||
|
goto catch_error;
|
||||||
|
}
|
||||||
|
if ((err = snd_pcm_hw_params_get_rate(hw_params, &samplerate_ret, 0)) < 0)
|
||||||
|
{
|
||||||
|
WRN("cannot get samplerate (%s)\n", snd_strerror(err));
|
||||||
goto catch_error;
|
goto catch_error;
|
||||||
}
|
}
|
||||||
snd_pcm_hw_params_free(hw_params);
|
|
||||||
if ((err = snd_pcm_prepare(alsa_dev)) < 0)
|
if ((err = snd_pcm_prepare(alsa_dev)) < 0)
|
||||||
{
|
{
|
||||||
printf("cannot prepare audio for use (%s)\n", snd_strerror(err));
|
WRN("cannot prepare audio for use (%s)\n", snd_strerror(err));
|
||||||
goto catch_error;
|
goto catch_error;
|
||||||
}
|
}
|
||||||
|
if (real_samplerate) *real_samplerate = samplerate_ret;
|
||||||
|
|
||||||
catch_error:
|
catch_error:
|
||||||
if ((err < 0) && (alsa_dev != NULL))
|
if ((err < 0) && (alsa_dev != NULL))
|
||||||
|
@ -117,7 +140,8 @@ catch_error:
|
||||||
static RemixBase *
|
static RemixBase *
|
||||||
alsa_player_reset_device(RemixEnv *env, RemixBase *base)
|
alsa_player_reset_device(RemixEnv *env, RemixBase *base)
|
||||||
{
|
{
|
||||||
AlsaPlayerData *player_data = remix_base_get_instance_data(env, base);
|
Alsa_Player_Data *player_data = remix_base_get_instance_data(env, base);
|
||||||
|
unsigned int real_samplerate = 0;
|
||||||
|
|
||||||
if (player_data->alsa_dev)
|
if (player_data->alsa_dev)
|
||||||
{
|
{
|
||||||
|
@ -125,12 +149,19 @@ alsa_player_reset_device(RemixEnv *env, RemixBase *base)
|
||||||
snd_pcm_close(player_data->alsa_dev);
|
snd_pcm_close(player_data->alsa_dev);
|
||||||
}
|
}
|
||||||
player_data->alsa_dev = alsa_open(player_data->channels,
|
player_data->alsa_dev = alsa_open(player_data->channels,
|
||||||
player_data->frequency);
|
player_data->frequency,
|
||||||
|
&real_samplerate);
|
||||||
if (!player_data->alsa_dev)
|
if (!player_data->alsa_dev)
|
||||||
{
|
{
|
||||||
remix_set_error(env, REMIX_ERROR_SYSTEM);
|
remix_set_error(env, REMIX_ERROR_SYSTEM);
|
||||||
return RemixNone;
|
return RemixNone;
|
||||||
}
|
}
|
||||||
|
// printf("%i != %i\n", real_samplerate, player_data->frequency);
|
||||||
|
if (real_samplerate != player_data->frequency)
|
||||||
|
{
|
||||||
|
player_data->frequency = real_samplerate;
|
||||||
|
remix_set_samplerate(env, player_data->frequency);
|
||||||
|
}
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,13 +169,20 @@ static RemixBase *
|
||||||
alsa_player_init(RemixEnv *env, RemixBase *base, CDSet *parameters __UNUSED__)
|
alsa_player_init(RemixEnv *env, RemixBase *base, CDSet *parameters __UNUSED__)
|
||||||
{
|
{
|
||||||
CDSet *channels;
|
CDSet *channels;
|
||||||
AlsaPlayerData *player_data = calloc(1, sizeof(AlsaPlayerData));
|
Alsa_Player_Data *player_data = calloc(1, sizeof(Alsa_Player_Data));
|
||||||
|
|
||||||
if (!player_data)
|
if (!player_data)
|
||||||
{
|
{
|
||||||
remix_set_error(env, REMIX_ERROR_SYSTEM);
|
remix_set_error(env, REMIX_ERROR_SYSTEM);
|
||||||
return RemixNone;
|
return RemixNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init_count++;
|
||||||
|
if (init_count == 1)
|
||||||
|
{
|
||||||
|
eina_init();
|
||||||
|
_log_dom = eina_log_domain_register("remix-alsa", EINA_COLOR_CYAN);
|
||||||
|
}
|
||||||
|
|
||||||
remix_base_set_instance_data(env, base, player_data);
|
remix_base_set_instance_data(env, base, player_data);
|
||||||
channels = remix_get_channels(env);
|
channels = remix_get_channels(env);
|
||||||
|
@ -170,7 +208,7 @@ alsa_player_clone(RemixEnv *env, RemixBase *base __UNUSED__)
|
||||||
static int
|
static int
|
||||||
alsa_player_destroy(RemixEnv *env, RemixBase *base)
|
alsa_player_destroy(RemixEnv *env, RemixBase *base)
|
||||||
{
|
{
|
||||||
AlsaPlayerData *player_data = remix_base_get_instance_data(env, base);
|
Alsa_Player_Data *player_data = remix_base_get_instance_data(env, base);
|
||||||
|
|
||||||
if (player_data->alsa_dev)
|
if (player_data->alsa_dev)
|
||||||
{
|
{
|
||||||
|
@ -178,13 +216,20 @@ alsa_player_destroy(RemixEnv *env, RemixBase *base)
|
||||||
snd_pcm_close(player_data->alsa_dev);
|
snd_pcm_close(player_data->alsa_dev);
|
||||||
}
|
}
|
||||||
free(player_data);
|
free(player_data);
|
||||||
|
init_count--;
|
||||||
|
if (init_count == 0)
|
||||||
|
{
|
||||||
|
eina_log_domain_unregister(_log_dom);
|
||||||
|
_log_dom = -1;
|
||||||
|
eina_shutdown();
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
alsa_player_ready(RemixEnv *env, RemixBase *base)
|
alsa_player_ready(RemixEnv *env, RemixBase *base)
|
||||||
{
|
{
|
||||||
AlsaPlayerData *player_data = remix_base_get_instance_data(env, base);
|
Alsa_Player_Data *player_data = remix_base_get_instance_data(env, base);
|
||||||
RemixCount nr_channels;
|
RemixCount nr_channels;
|
||||||
CDSet *channels;
|
CDSet *channels;
|
||||||
int samplerate;
|
int samplerate;
|
||||||
|
@ -205,15 +250,39 @@ alsa_player_prepare(RemixEnv *env, RemixBase *base)
|
||||||
}
|
}
|
||||||
|
|
||||||
static RemixCount
|
static RemixCount
|
||||||
alsa_player_playbuffer(RemixEnv *env __UNUSED__, AlsaPlayerData *player, RemixPCM *data, RemixCount count)
|
alsa_player_playbuffer(RemixEnv *env __UNUSED__, Alsa_Player_Data *player, RemixPCM *data, RemixCount count)
|
||||||
{
|
{
|
||||||
|
#ifdef MIXDBG
|
||||||
|
{
|
||||||
|
static int total = 0;
|
||||||
|
static SNDFILE *sfile = NULL;
|
||||||
|
static SF_INFO sfinfo;
|
||||||
|
|
||||||
|
if (total == 0)
|
||||||
|
{
|
||||||
|
sfinfo.frames = 0;
|
||||||
|
sfinfo.samplerate = player->frequency;
|
||||||
|
sfinfo.channels = 2;
|
||||||
|
sfinfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16 | SF_ENDIAN_LITTLE;
|
||||||
|
sfinfo.sections = 0;
|
||||||
|
sfinfo.seekable = 0;
|
||||||
|
sfile = sf_open("out.wav", SFM_WRITE, &sfinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sfile)
|
||||||
|
{
|
||||||
|
sf_writef_float(sfile, data, count);
|
||||||
|
total += count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return snd_pcm_writei(player->alsa_dev, data, count);
|
return snd_pcm_writei(player->alsa_dev, data, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
static RemixCount
|
static RemixCount
|
||||||
alsa_player_chunk(RemixEnv *env, RemixChunk *chunk, RemixCount offset, RemixCount count, int channelname __UNUSED__, void *data)
|
alsa_player_chunk(RemixEnv *env, RemixChunk *chunk, RemixCount offset, RemixCount count, int channelname __UNUSED__, void *data)
|
||||||
{
|
{
|
||||||
AlsaPlayerData *player = data;
|
Alsa_Player_Data *player = data;
|
||||||
RemixCount remaining = count, written = 0, n, playcount;
|
RemixCount remaining = count, written = 0, n, playcount;
|
||||||
RemixPCM *d;
|
RemixPCM *d;
|
||||||
|
|
||||||
|
@ -237,7 +306,7 @@ alsa_player_chunk(RemixEnv *env, RemixChunk *chunk, RemixCount offset, RemixCoun
|
||||||
static RemixCount
|
static RemixCount
|
||||||
alsa_player_process(RemixEnv *env, RemixBase *base, RemixCount count, RemixStream *input, RemixStream *output __UNUSED__)
|
alsa_player_process(RemixEnv *env, RemixBase *base, RemixCount count, RemixStream *input, RemixStream *output __UNUSED__)
|
||||||
{
|
{
|
||||||
AlsaPlayerData *player_data = remix_base_get_instance_data(env, base);
|
Alsa_Player_Data *player_data = remix_base_get_instance_data(env, base);
|
||||||
RemixCount nr_channels = remix_stream_nr_channels(env, input);
|
RemixCount nr_channels = remix_stream_nr_channels(env, input);
|
||||||
RemixCount remaining = count, processed = 0, n, nn;
|
RemixCount remaining = count, processed = 0, n, nn;
|
||||||
|
|
||||||
|
@ -248,9 +317,9 @@ alsa_player_process(RemixEnv *env, RemixBase *base, RemixCount count, RemixStrea
|
||||||
}
|
}
|
||||||
else if ((nr_channels == 2) && (player_data->stereo == 1))
|
else if ((nr_channels == 2) && (player_data->stereo == 1))
|
||||||
{ /*STEREO*/
|
{ /*STEREO*/
|
||||||
while (processed < count)
|
while (remaining > 0)
|
||||||
{
|
{
|
||||||
n = MIN(remaining, ALSA_PLAYER_BUFFERLEN);
|
n = MIN(remaining, ALSA_PLAYER_BUFFERLEN / 2);
|
||||||
n = remix_stream_interleave_2(env, input,
|
n = remix_stream_interleave_2(env, input,
|
||||||
REMIX_CHANNEL_LEFT,
|
REMIX_CHANNEL_LEFT,
|
||||||
REMIX_CHANNEL_RIGHT,
|
REMIX_CHANNEL_RIGHT,
|
||||||
|
@ -262,8 +331,8 @@ alsa_player_process(RemixEnv *env, RemixBase *base, RemixCount count, RemixStrea
|
||||||
}
|
}
|
||||||
return processed;
|
return processed;
|
||||||
}
|
}
|
||||||
printf("[alsa_player_process] unsupported stream/output channel\n");
|
WRN("[alsa_player_process] unsupported stream/output channel"
|
||||||
printf("combination %ld / %d\n", nr_channels, player_data->stereo ? 2 : 1);
|
"combination %ld / %d\n", nr_channels, player_data->stereo ? 2 : 1);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue