pulse segfault fixed and changed default config (#2044)
[termux-packages] / packages / libpulseaudio / module-sles-sink.c
index 313a1c4..7f10ae9 100644 (file)
 
 #include "module-sles-sink-symdef.h"
 
+//Only certain interfaces are supported by the fast mixer. These are:
+//SL_IID_ANDROIDSIMPLEBUFFERQUEUE
+//SL_IID_VOLUME
+//SL_IID_MUTESOLO
+#define USE_ANDROID_SIMPLE_BUFFER_QUEUE
+
 #ifdef USE_ANDROID_SIMPLE_BUFFER_QUEUE
        #include <SLES/OpenSLES_Android.h>
        #define DATALOCATOR_BUFFERQUEUE SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE
                else fprintf(stderr, "error %d at %s:%d\n", (int) r, __FILE__, __LINE__); \
                } \
        } while (0)
-typedef struct {
-       short left;
-       short right;
-} frame_t;
 
 PA_MODULE_AUTHOR("Lennart Poettering, Nathan Martynov");
 PA_MODULE_DESCRIPTION("Android OpenSL ES sink");
@@ -86,6 +88,11 @@ PA_MODULE_USAGE(
 #define DEFAULT_SINK_NAME "OpenSL ES sink"
 #define BLOCK_USEC (PA_USEC_PER_SEC * 2)
 
+typedef struct pa_memblock_queue_t {
+       pa_memblock *memblock;
+       struct pa_memblock_queue_t* next;
+} pa_memblock_queue;
+
 struct userdata {
     pa_core *core;
     pa_module *module;
@@ -110,6 +117,9 @@ struct userdata {
        SLObjectItf bqPlayerObject;
        SLPlayItf bqPlayerPlay;
        BufferQueueItf bqPlayerBufferQueue;
+       
+       pa_memblock_queue* current;
+       pa_memblock_queue* last;
 };
 
 static const char* const valid_modargs[] = {
@@ -168,6 +178,17 @@ static void sink_update_requested_latency_cb(pa_sink *s) {
     pa_sink_set_max_request_within_thread(s, nbytes);
 }
 
+static void pa_sles_callback(BufferQueueItf bq, void *context){
+       struct userdata* s = (struct userdata*) context;
+       pa_memblock_queue* next;
+       if (s->current != NULL){
+               if (s->current->memblock != NULL) pa_memblock_unref(s->current->memblock);
+               next = s->current->next;
+               free(s->current);
+               s->current = next;
+       }
+}
+
 static int pa_init_sles_player(struct userdata *s, SLint32 sl_rate)
 {
        if (s == NULL) return -1;
@@ -193,7 +214,7 @@ static int pa_init_sles_player(struct userdata *s, SLint32 sl_rate)
        locator_bufferqueue.locatorType = DATALOCATOR_BUFFERQUEUE;
        locator_bufferqueue.numBuffers = 50;
        
-       if (sl_rate < 0) {
+       if (sl_rate < SL_SAMPLINGRATE_8 || sl_rate > SL_SAMPLINGRATE_192) {
                pa_log("Incompatible sample rate");
                return -1;
        }
@@ -223,7 +244,10 @@ static int pa_init_sles_player(struct userdata *s, SLint32 sl_rate)
        result = (*s->bqPlayerObject)->GetInterface(s->bqPlayerObject, SL_IID_PLAY, &s->bqPlayerPlay); checkResult(result);
        result = (*s->bqPlayerObject)->GetInterface(s->bqPlayerObject, IID_BUFFERQUEUE_USED, &s->bqPlayerBufferQueue); checkResult(result);
        
+    result = (*s->bqPlayerBufferQueue)->RegisterCallback(s->bqPlayerBufferQueue, pa_sles_callback, s); checkResult(result);
+       
        result = (*s->bqPlayerPlay)->SetPlayState(s->bqPlayerPlay, SL_PLAYSTATE_PLAYING); checkResult(result);
+       
        return 0;
 }
 
@@ -236,6 +260,7 @@ static void pa_destroy_sles_player(struct userdata *s){
 }
 
 static void process_render(struct userdata *u, pa_usec_t now) {
+       pa_memblock_queue* current_block;
     size_t ate = 0;
 
     pa_assert(u);
@@ -256,6 +281,20 @@ static void process_render(struct userdata *u, pa_usec_t now) {
 
         u->timestamp += pa_bytes_to_usec(u->memchunk.length, &u->sink->sample_spec);
         ate += u->memchunk.length;
+        
+        current_block = malloc(sizeof(pa_memblock_queue));
+        memset(current_block, 0, sizeof(pa_memblock_queue));
+        
+        current_block->memblock = u->memchunk.memblock;
+        if (u->current == NULL) { u->current = current_block; }
+        if (u->last == NULL) { u->last = current_block; }
+        else {
+                       u->last->next = current_block;
+                       u->last = current_block;
+               }
+        
+        //pa_memblock_unref(u->memchunk.memblock);
+        pa_memchunk_reset(&u->memchunk);
         if (ate >= u->sink->thread_info.max_request) break;
     }
 }
@@ -307,39 +346,12 @@ fail:
 finish:
     pa_log_debug("Thread shutting down");
 }
-       
-static SLint32 PA2SLrate(int32_t rate){
-       if (!(rate >= 8000 && rate <= 192000)) return -1;
-       switch(rate){
-               case 8000:
-                       return SL_SAMPLINGRATE_8;
-               case 11025:
-                       return SL_SAMPLINGRATE_11_025;
-               case 12000:
-                       return SL_SAMPLINGRATE_12;
-               case 16000:
-                       return SL_SAMPLINGRATE_16;
-               case 22050:
-                       return SL_SAMPLINGRATE_22_05;
-               case 24000:
-                       return SL_SAMPLINGRATE_24;
-               case 32000:
-                       return SL_SAMPLINGRATE_32;
-               case 44100:
-                       return SL_SAMPLINGRATE_44_1;
-               case 48000:
-                       return SL_SAMPLINGRATE_48;
-               case 64000:
-                       return SL_SAMPLINGRATE_64;
-               case 88200:
-                       return SL_SAMPLINGRATE_88_2;
-               case 96000:
-                       return SL_SAMPLINGRATE_96;
-               case 192000:
-                       return SL_SAMPLINGRATE_192;
-               default:
-                       return -1;
-        }
+
+static int getenv_int(const char * env, size_t min_len){
+    char * got_env = getenv(env);
+    int ret = 0;
+    if (got_env != NULL && strlen(got_env) >= min_len) ret = atoi(got_env); //"8000" is 4 symbols
+    return ret;
 }
 
 int pa__init(pa_module*m) {
@@ -373,20 +385,25 @@ int pa__init(pa_module*m) {
        //Needed. Don't touch
     ss.channels = 2; 
     ss.format = PA_SAMPLE_S16LE;
-    int forceFormat = atoi(getenv("PROPERTY_OUTPUT_SAMPLE_RATE"));
-    if (forceFormat >= 8000 && forceFormat <= 192000) 
-       ss.rate = forceFormat;
     
     m->userdata = u = pa_xnew0(struct userdata, 1);
+    
+    int forceFormat = getenv_int("PROPERTY_OUTPUT_SAMPLE_RATE", 4); //"8000" is 4 symbols
+    if (forceFormat >= 8000 && forceFormat <= 192000)  {
+               ss.rate = forceFormat;
+               pa_log_info("Sample rate was forced to be %u\n", ss.rate);
+       }
+       
     u->core = m->core;
     u->module = m;
     u->rtpoll = pa_rtpoll_new();
     pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll);
        
-       if (pa_init_sles_player(u, PA2SLrate(ss.rate)) < 0)
+       //Pulseaudio uses samples per sec but OpenSL ES uses samples per ms
+       if (pa_init_sles_player(u, ss.rate * 1000) < 0)
                goto fail;
-       int buff[2] = {0, 0};
-       (*u->bqPlayerBufferQueue)->Enqueue(u->bqPlayerBufferQueue, buff, 1);
+       //int buff[2] = {0, 0};
+       //(*u->bqPlayerBufferQueue)->Enqueue(u->bqPlayerBufferQueue, buff, 1);
 
     pa_sink_new_data_init(&data);
     data.driver = __FILE__;
@@ -469,6 +486,10 @@ void pa__done(pa_module*m) {
         pa_asyncmsgq_send(u->thread_mq.inq, NULL, PA_MESSAGE_SHUTDOWN, NULL, 0, NULL);
         pa_thread_free(u->thread);
     }
+    
+    if (u->engineObject){
+               pa_destroy_sles_player(u);
+       }
 
     pa_thread_mq_done(&u->thread_mq);