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_VERSION=0.1
+TERMUX_PKG_VERSION=0.2
 
 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
+.Op Fl s Ar stream
 .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 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
index 4073258..2d20b43 100644 (file)
@@ -13,10 +13,21 @@ class AudioPlayer {
                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};
+               SLint32 androidStreamType{SL_ANDROID_STREAM_MEDIA};
 };
 
 class MutexWithCondition {
@@ -53,10 +64,8 @@ AudioPlayer::AudioPlayer() {
        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);
@@ -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.
-                               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();
                        }
@@ -95,16 +104,10 @@ void AudioPlayer::play(char const* uri)
        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,
@@ -119,21 +122,7 @@ void AudioPlayer::play(char const* uri)
        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.
@@ -148,10 +137,6 @@ void AudioPlayer::play(char const* uri)
        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 {
@@ -194,19 +179,53 @@ int main(int argc, char** argv)
 {
        bool help = false;
        int c;
-       while ((c = getopt(argc, argv, "h")) != -1) {
+       char* streamType = NULL;
+       while ((c = getopt(argc, argv, "hs:")) != -1) {
                switch (c) {
-                       case 'h': help = true; break;
+                       case 'h':
+                       case '?': help = true; break;
+                       case 's': streamType = optarg; break;
                }
        }
 
        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;
-       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;
 }