Update play-audio to 0.2
Cleanups and stream type support
This commit is contained in:
parent
8c02de4bc0
commit
df22a55439
@ -1,6 +1,6 @@
|
|||||||
TERMUX_PKG_HOMEPAGE=http://termux.com
|
TERMUX_PKG_HOMEPAGE=http://termux.com
|
||||||
TERMUX_PKG_DESCRIPTION="Simple commandline audio player for Android"
|
TERMUX_PKG_DESCRIPTION="Simple commandline audio player for Android"
|
||||||
TERMUX_PKG_VERSION=0.1
|
TERMUX_PKG_VERSION=0.2
|
||||||
|
|
||||||
termux_step_make_install () {
|
termux_step_make_install () {
|
||||||
$CXX $CFLAGS $LDFLAGS \
|
$CXX $CFLAGS $LDFLAGS \
|
||||||
|
@ -5,13 +5,16 @@
|
|||||||
.Nd audio player using the Android media system
|
.Nd audio player using the Android media system
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm play-audio
|
.Nm play-audio
|
||||||
|
.Op Fl s Ar stream
|
||||||
.Op Ar files
|
.Op Ar files
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
The
|
The
|
||||||
.Nm play-audio
|
.Nm play-audio
|
||||||
utility plays the files listed as arguments, in order, using the Android media system.
|
utility plays one or more files listed as arguments using the Android media system.
|
||||||
.Pp
|
.Pp
|
||||||
The supported media formats may vary across difference devices and Android versions.
|
The supported media formats may vary across difference devices and Android versions.
|
||||||
|
.Pp
|
||||||
|
The audio stream type (which affects the volume) may be specified as 'alarm', 'media' (default), 'notification', 'ring', 'system' or 'voice'.
|
||||||
.Sh EXAMPLES
|
.Sh EXAMPLES
|
||||||
Play two ogg files in succession:
|
Play two ogg files in succession:
|
||||||
.Pp
|
.Pp
|
||||||
|
@ -13,10 +13,21 @@ class AudioPlayer {
|
|||||||
AudioPlayer();
|
AudioPlayer();
|
||||||
~AudioPlayer();
|
~AudioPlayer();
|
||||||
void play(char const* uri);
|
void play(char const* uri);
|
||||||
|
/**
|
||||||
|
* This allows setting the stream type (default:SL_ANDROID_STREAM_MEDIA):
|
||||||
|
* SL_ANDROID_STREAM_ALARM - same as android.media.AudioManager.STREAM_ALARM
|
||||||
|
* SL_ANDROID_STREAM_MEDIA - same as android.media.AudioManager.STREAM_MUSIC
|
||||||
|
* SL_ANDROID_STREAM_NOTIFICATION - same as android.media.AudioManager.STREAM_NOTIFICATION
|
||||||
|
* SL_ANDROID_STREAM_RING - same as android.media.AudioManager.STREAM_RING
|
||||||
|
* SL_ANDROID_STREAM_SYSTEM - same as android.media.AudioManager.STREAM_SYSTEM
|
||||||
|
* SL_ANDROID_STREAM_VOICE - same as android.media.AudioManager.STREAM_VOICE_CALL
|
||||||
|
*/
|
||||||
|
void setStreamType(SLint32 streamType) { this->androidStreamType = streamType; }
|
||||||
private:
|
private:
|
||||||
SLObjectItf mSlEngineObject{NULL};
|
SLObjectItf mSlEngineObject{NULL};
|
||||||
SLEngineItf mSlEngineInterface{NULL};
|
SLEngineItf mSlEngineInterface{NULL};
|
||||||
SLObjectItf mSlOutputMixObject{NULL};
|
SLObjectItf mSlOutputMixObject{NULL};
|
||||||
|
SLint32 androidStreamType{SL_ANDROID_STREAM_MEDIA};
|
||||||
};
|
};
|
||||||
|
|
||||||
class MutexWithCondition {
|
class MutexWithCondition {
|
||||||
@ -53,10 +64,8 @@ AudioPlayer::AudioPlayer() {
|
|||||||
result = (*mSlEngineObject)->GetInterface(mSlEngineObject, SL_IID_ENGINE, &mSlEngineInterface);
|
result = (*mSlEngineObject)->GetInterface(mSlEngineObject, SL_IID_ENGINE, &mSlEngineInterface);
|
||||||
assert(SL_RESULT_SUCCESS == result);
|
assert(SL_RESULT_SUCCESS == result);
|
||||||
|
|
||||||
SLuint32 const numWantedInterfaces = 1;
|
SLuint32 const numWantedInterfaces = 0;
|
||||||
SLInterfaceID wantedInterfaces[numWantedInterfaces]{ SL_IID_ENVIRONMENTALREVERB };
|
result = (*mSlEngineInterface)->CreateOutputMix(mSlEngineInterface, &mSlOutputMixObject, numWantedInterfaces, NULL, NULL);
|
||||||
SLboolean wantedInterfacesRequired[numWantedInterfaces]{ SL_BOOLEAN_TRUE };
|
|
||||||
result = (*mSlEngineInterface)->CreateOutputMix(mSlEngineInterface, &mSlOutputMixObject, numWantedInterfaces, wantedInterfaces, wantedInterfacesRequired);
|
|
||||||
assert(SL_RESULT_SUCCESS == result);
|
assert(SL_RESULT_SUCCESS == result);
|
||||||
|
|
||||||
result = (*mSlOutputMixObject)->Realize(mSlOutputMixObject, SL_BOOLEAN_FALSE);
|
result = (*mSlOutputMixObject)->Realize(mSlOutputMixObject, SL_BOOLEAN_FALSE);
|
||||||
@ -73,7 +82,7 @@ void opensl_prefetch_callback(SLPrefetchStatusItf caller, void* pContext, SLuint
|
|||||||
(*caller)->GetPrefetchStatus(caller, &status);
|
(*caller)->GetPrefetchStatus(caller, &status);
|
||||||
if (status == SL_PREFETCHSTATUS_UNDERFLOW) {
|
if (status == SL_PREFETCHSTATUS_UNDERFLOW) {
|
||||||
// Level is 0 but we have SL_PREFETCHSTATUS_UNDERFLOW, implying an error.
|
// Level is 0 but we have SL_PREFETCHSTATUS_UNDERFLOW, implying an error.
|
||||||
printf("- ERROR: Underflow when prefetching data and fill level zero\n");
|
printf("play-audio: underflow when prefetching data\n");
|
||||||
MutexWithCondition* cond = (MutexWithCondition*) pContext;
|
MutexWithCondition* cond = (MutexWithCondition*) pContext;
|
||||||
cond->lockAndSignal();
|
cond->lockAndSignal();
|
||||||
}
|
}
|
||||||
@ -95,16 +104,10 @@ void AudioPlayer::play(char const* uri)
|
|||||||
SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, mSlOutputMixObject};
|
SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, mSlOutputMixObject};
|
||||||
SLDataSink audioSnk = {&loc_outmix, NULL};
|
SLDataSink audioSnk = {&loc_outmix, NULL};
|
||||||
|
|
||||||
// SL_IID_ANDROIDCONFIGURATION is Android specific interface, SL_IID_VOLUME is general:
|
// SL_IID_ANDROIDCONFIGURATION is Android specific interface, SL_IID_PREFETCHSTATUS is general:
|
||||||
SLuint32 const numWantedInterfaces = 5;
|
SLuint32 const numWantedInterfaces = 2;
|
||||||
SLInterfaceID wantedInterfaces[numWantedInterfaces]{
|
SLInterfaceID wantedInterfaces[numWantedInterfaces]{ SL_IID_ANDROIDCONFIGURATION, SL_IID_PREFETCHSTATUS };
|
||||||
SL_IID_ANDROIDCONFIGURATION,
|
SLboolean wantedInterfacesRequired[numWantedInterfaces]{ SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE };
|
||||||
SL_IID_VOLUME,
|
|
||||||
SL_IID_PREFETCHSTATUS,
|
|
||||||
SL_IID_PLAYBACKRATE,
|
|
||||||
SL_IID_EFFECTSEND
|
|
||||||
};
|
|
||||||
SLboolean wantedInterfacesRequired[numWantedInterfaces]{ SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE };
|
|
||||||
|
|
||||||
SLObjectItf uriPlayerObject = NULL;
|
SLObjectItf uriPlayerObject = NULL;
|
||||||
SLresult result = (*mSlEngineInterface)->CreateAudioPlayer(mSlEngineInterface, &uriPlayerObject, &audioSrc, &audioSnk,
|
SLresult result = (*mSlEngineInterface)->CreateAudioPlayer(mSlEngineInterface, &uriPlayerObject, &audioSrc, &audioSnk,
|
||||||
@ -119,21 +122,7 @@ void AudioPlayer::play(char const* uri)
|
|||||||
result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_ANDROIDCONFIGURATION, &androidConfig);
|
result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_ANDROIDCONFIGURATION, &androidConfig);
|
||||||
assert(SL_RESULT_SUCCESS == result);
|
assert(SL_RESULT_SUCCESS == result);
|
||||||
|
|
||||||
// This allows setting the stream type (default:SL_ANDROID_STREAM_MEDIA):
|
result = (*androidConfig)->SetConfiguration(androidConfig, SL_ANDROID_KEY_STREAM_TYPE, &this->androidStreamType, sizeof(SLint32));
|
||||||
/* same as android.media.AudioManager.STREAM_VOICE_CALL */
|
|
||||||
// #define SL_ANDROID_STREAM_VOICE ((SLint32) 0x00000000)
|
|
||||||
/* same as android.media.AudioManager.STREAM_SYSTEM */
|
|
||||||
// #define SL_ANDROID_STREAM_SYSTEM ((SLint32) 0x00000001)
|
|
||||||
/* same as android.media.AudioManager.STREAM_RING */
|
|
||||||
// #define SL_ANDROID_STREAM_RING ((SLint32) 0x00000002)
|
|
||||||
/* same as android.media.AudioManager.STREAM_MUSIC */
|
|
||||||
// #define SL_ANDROID_STREAM_MEDIA ((SLint32) 0x00000003)
|
|
||||||
/* same as android.media.AudioManager.STREAM_ALARM */
|
|
||||||
// #define SL_ANDROID_STREAM_ALARM ((SLint32) 0x00000004)
|
|
||||||
/* same as android.media.AudioManager.STREAM_NOTIFICATION */
|
|
||||||
// #define SL_ANDROID_STREAM_NOTIFICATION ((SLint32) 0x00000005)
|
|
||||||
SLint32 androidStreamType = SL_ANDROID_STREAM_ALARM;
|
|
||||||
result = (*androidConfig)->SetConfiguration(androidConfig, SL_ANDROID_KEY_STREAM_TYPE, &androidStreamType, sizeof(SLint32));
|
|
||||||
assert(SL_RESULT_SUCCESS == result);
|
assert(SL_RESULT_SUCCESS == result);
|
||||||
|
|
||||||
// We now Realize(). Note that the android config needs to be done before, but getting the SLPrefetchStatusItf after.
|
// We now Realize(). Note that the android config needs to be done before, but getting the SLPrefetchStatusItf after.
|
||||||
@ -148,10 +137,6 @@ void AudioPlayer::play(char const* uri)
|
|||||||
result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_PLAY, &uriPlayerPlay);
|
result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_PLAY, &uriPlayerPlay);
|
||||||
assert(SL_RESULT_SUCCESS == result);
|
assert(SL_RESULT_SUCCESS == result);
|
||||||
|
|
||||||
SLPlaybackRateItf playbackRateInterface;
|
|
||||||
result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_PLAYBACKRATE, &playbackRateInterface);
|
|
||||||
assert(SL_RESULT_SUCCESS == result);
|
|
||||||
|
|
||||||
if (NULL == uriPlayerPlay) {
|
if (NULL == uriPlayerPlay) {
|
||||||
fprintf(stderr, "Cannot play '%s'\n", uri);
|
fprintf(stderr, "Cannot play '%s'\n", uri);
|
||||||
} else {
|
} else {
|
||||||
@ -194,19 +179,53 @@ int main(int argc, char** argv)
|
|||||||
{
|
{
|
||||||
bool help = false;
|
bool help = false;
|
||||||
int c;
|
int c;
|
||||||
while ((c = getopt(argc, argv, "h")) != -1) {
|
char* streamType = NULL;
|
||||||
|
while ((c = getopt(argc, argv, "hs:")) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'h': help = true; break;
|
case 'h':
|
||||||
|
case '?': help = true; break;
|
||||||
|
case 's': streamType = optarg; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (help || optind == argc) {
|
if (help || optind == argc) {
|
||||||
printf("usage: %s [files]\n", argv[0]);
|
printf("usage: play-audio [-s streamtype] [files]\n");
|
||||||
exit(0);
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioPlayer player;
|
AudioPlayer player;
|
||||||
for (int i = optind; i < argc; i++) player.play(argv[i]);
|
|
||||||
|
if (streamType != NULL) {
|
||||||
|
SLint32 streamTypeEnum;
|
||||||
|
if (strcmp("alarm", streamType) == 0) {
|
||||||
|
streamTypeEnum = SL_ANDROID_STREAM_ALARM;
|
||||||
|
} else if (strcmp("media", streamType) == 0) {
|
||||||
|
streamTypeEnum = SL_ANDROID_STREAM_MEDIA;
|
||||||
|
} else if (strcmp("notification", streamType) == 0) {
|
||||||
|
streamTypeEnum = SL_ANDROID_STREAM_NOTIFICATION;
|
||||||
|
} else if (strcmp("ring", streamType) == 0) {
|
||||||
|
streamTypeEnum = SL_ANDROID_STREAM_RING;
|
||||||
|
} else if (strcmp("system", streamType) == 0) {
|
||||||
|
streamTypeEnum = SL_ANDROID_STREAM_SYSTEM;
|
||||||
|
} else if (strcmp("voice", streamType) == 0) {
|
||||||
|
streamTypeEnum = SL_ANDROID_STREAM_VOICE;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "play-audio: invalid streamtype '%s'\n", streamType);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
player.setStreamType(streamTypeEnum);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = optind; i < argc; i++) {
|
||||||
|
if (access(argv[i], R_OK) != 0) {
|
||||||
|
fprintf(stderr, "play-audio: '%s' is not a readable file\n", argv[i]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = optind; i < argc; i++) {
|
||||||
|
player.play(argv[i]);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user