Update play-audio to 0.2
authorFredrik Fornwall <fredrik@fornwall.net>
Sun, 2 Aug 2015 12:49:24 +0000 (08:49 -0400)
committerFredrik Fornwall <fredrik@fornwall.net>
Sun, 2 Aug 2015 12:49:24 +0000 (08:49 -0400)
Cleanups and stream type support

packages/play-audio/build.sh
packages/play-audio/play-audio.1
packages/play-audio/play-audio.cpp

index a36c8ca..a8bed52 100644 (file)
@@ -1,6 +1,6 @@
 TERMUX_PKG_HOMEPAGE=http://termux.com
 TERMUX_PKG_DESCRIPTION="Simple commandline audio player for Android"
 TERMUX_PKG_HOMEPAGE=http://termux.com
 TERMUX_PKG_DESCRIPTION="Simple commandline audio player for Android"
-TERMUX_PKG_VERSION=0.1
+TERMUX_PKG_VERSION=0.2
 
 termux_step_make_install () {
        $CXX $CFLAGS $LDFLAGS \
 
 termux_step_make_install () {
        $CXX $CFLAGS $LDFLAGS \
index 727a355..8c1a073 100644 (file)
@@ -5,13 +5,16 @@
 .Nd audio player using the Android media system
 .Sh SYNOPSIS
 .Nm play-audio
 .Nd audio player using the Android media system
 .Sh SYNOPSIS
 .Nm play-audio
+.Op Fl s Ar stream
 .Op Ar files
 .Sh DESCRIPTION
 The
 .Nm play-audio
 .Op Ar files
 .Sh DESCRIPTION
 The
 .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
 The supported media formats may vary across difference devices and Android versions.
 .Pp
 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
 Play two ogg files in succession:
 .Pp
 .Sh EXAMPLES
 Play two ogg files in succession:
 .Pp
index 4073258..2d20b43 100644 (file)
@@ -13,10 +13,21 @@ class AudioPlayer {
                AudioPlayer();
                ~AudioPlayer();
                void play(char const* uri);
                AudioPlayer();
                ~AudioPlayer();
                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:
                SLObjectItf mSlEngineObject{NULL};
                SLEngineItf mSlEngineInterface{NULL};
                SLObjectItf mSlOutputMixObject{NULL};
        private:
                SLObjectItf mSlEngineObject{NULL};
                SLEngineItf mSlEngineInterface{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);
        assert(SL_RESULT_SUCCESS == result);
 
        result = (*mSlEngineObject)->GetInterface(mSlEngineObject, SL_IID_ENGINE, &mSlEngineInterface);
        assert(SL_RESULT_SUCCESS == result);
 
-       SLuint32 const numWantedInterfaces = 1;
-       SLInterfaceID wantedInterfaces[numWantedInterfaces]{ SL_IID_ENVIRONMENTALREVERB };
-       SLboolean wantedInterfacesRequired[numWantedInterfaces]{ SL_BOOLEAN_TRUE };
-       result = (*mSlEngineInterface)->CreateOutputMix(mSlEngineInterface, &mSlOutputMixObject, numWantedInterfaces, wantedInterfaces, wantedInterfacesRequired);
+       SLuint32 const numWantedInterfaces = 0;
+       result = (*mSlEngineInterface)->CreateOutputMix(mSlEngineInterface, &mSlOutputMixObject, numWantedInterfaces, NULL, NULL);
        assert(SL_RESULT_SUCCESS == result);
 
        result = (*mSlOutputMixObject)->Realize(mSlOutputMixObject, SL_BOOLEAN_FALSE);
        assert(SL_RESULT_SUCCESS == result);
 
        result = (*mSlOutputMixObject)->Realize(mSlOutputMixObject, SL_BOOLEAN_FALSE);
@@ -73,7 +82,7 @@ void opensl_prefetch_callback(SLPrefetchStatusItf caller, void* pContext, SLuint
                        (*caller)->GetPrefetchStatus(caller, &status);
                        if (status == SL_PREFETCHSTATUS_UNDERFLOW) {
                                // Level is 0 but we have SL_PREFETCHSTATUS_UNDERFLOW, implying an error.
                        (*caller)->GetPrefetchStatus(caller, &status);
                        if (status == SL_PREFETCHSTATUS_UNDERFLOW) {
                                // 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;
                                cond->lockAndSignal();
                        }
                                MutexWithCondition* cond = (MutexWithCondition*) pContext;
                                cond->lockAndSignal();
                        }
@@ -95,16 +104,10 @@ void AudioPlayer::play(char const* uri)
        SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, mSlOutputMixObject};
        SLDataSink audioSnk = {&loc_outmix, NULL};
 
        SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, mSlOutputMixObject};
        SLDataSink audioSnk = {&loc_outmix, NULL};
 
-       // SL_IID_ANDROIDCONFIGURATION is Android specific interface, SL_IID_VOLUME is general:
-       SLuint32 const numWantedInterfaces = 5;
-       SLInterfaceID wantedInterfaces[numWantedInterfaces]{
-               SL_IID_ANDROIDCONFIGURATION,
-               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 };
+       // SL_IID_ANDROIDCONFIGURATION is Android specific interface, SL_IID_PREFETCHSTATUS is general:
+       SLuint32 const numWantedInterfaces = 2;
+       SLInterfaceID wantedInterfaces[numWantedInterfaces]{ SL_IID_ANDROIDCONFIGURATION, SL_IID_PREFETCHSTATUS };
+       SLboolean wantedInterfacesRequired[numWantedInterfaces]{ SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE };
 
        SLObjectItf uriPlayerObject = NULL;
        SLresult result = (*mSlEngineInterface)->CreateAudioPlayer(mSlEngineInterface, &uriPlayerObject, &audioSrc, &audioSnk,
 
        SLObjectItf uriPlayerObject = NULL;
        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);
        assert(SL_RESULT_SUCCESS == result);
 
        result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_ANDROIDCONFIGURATION, &androidConfig);
        assert(SL_RESULT_SUCCESS == result);
 
-       // This allows setting the stream type (default:SL_ANDROID_STREAM_MEDIA):
-       /*      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));
+       result = (*androidConfig)->SetConfiguration(androidConfig, SL_ANDROID_KEY_STREAM_TYPE, &this->androidStreamType, sizeof(SLint32));
        assert(SL_RESULT_SUCCESS == result);
 
        // We now Realize(). Note that the android config needs to be done before, but getting the SLPrefetchStatusItf after.
        assert(SL_RESULT_SUCCESS == result);
 
        // 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);
        assert(SL_RESULT_SUCCESS == result);
 
        result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_PLAY, &uriPlayerPlay);
        assert(SL_RESULT_SUCCESS == result);
 
-       SLPlaybackRateItf playbackRateInterface;
-       result = (*uriPlayerObject)->GetInterface(uriPlayerObject, SL_IID_PLAYBACKRATE, &playbackRateInterface);
-       assert(SL_RESULT_SUCCESS == result);
-
        if (NULL == uriPlayerPlay) {
                fprintf(stderr, "Cannot play '%s'\n", uri);
        } else {
        if (NULL == uriPlayerPlay) {
                fprintf(stderr, "Cannot play '%s'\n", uri);
        } else {
@@ -194,19 +179,53 @@ int main(int argc, char** argv)
 {
        bool help = false;
        int c;
 {
        bool help = false;
        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]);
-               exit(0);
+               printf("usage: play-audio [-s streamtype] [files]\n");
+               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;
 }