13ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten/*
23ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten * Copyright (C) 2016 The Android Open Source Project
33ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten *
43ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License");
53ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten * you may not use this file except in compliance with the License.
63ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten * You may obtain a copy of the License at
73ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten *
83ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten *      http://www.apache.org/licenses/LICENSE-2.0
93ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten *
103ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten * Unless required by applicable law or agreed to in writing, software
113ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS,
123ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten * See the License for the specific language governing permissions and
143ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten * limitations under the License.
153ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten */
163ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten
17c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten#include <errno.h>
183ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten#include <pthread.h>
193ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten#include <stdio.h>
203ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten#include <unistd.h>
213ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten#include <audio_utils/fifo.h>
223ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kastenextern "C" {
233ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten#include "getch.h"
243ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten}
253ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten
263ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kastenstruct Context {
273ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    audio_utils_fifo_writer *mInputWriter;
283ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    audio_utils_fifo_reader *mInputReader;
293ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    audio_utils_fifo_writer *mTransferWriter;
303ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    audio_utils_fifo_reader *mTransferReader;
313ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    audio_utils_fifo_writer *mOutputWriter;
323ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    audio_utils_fifo_reader *mOutputReader;
333ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten};
343ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten
353ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kastenvoid *input_routine(void *arg)
363ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten{
373ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    Context *context = (Context *) arg;
383ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    for (;;) {
393ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten        struct timespec timeout;
40c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten        timeout.tv_sec = 30;
413ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten        timeout.tv_nsec = 0;
423ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten        char buffer[4];
433ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten        ssize_t actual = context->mInputReader->read(buffer, sizeof(buffer), &timeout);
44c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten        // TODO this test is unreadable
45c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten        if (actual > 0) {
46c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten            if ((size_t) actual > sizeof(buffer)) {
47c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten                printf("input.read actual = %d\n", (int) actual);
48c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten                abort();
49c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten            }
50c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten            ssize_t actual2 = context->mTransferWriter->write(buffer, actual, &timeout);
51c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten            if (actual2 != actual) {
52c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten                printf("transfer.write(%d) = %d\n", (int) actual, (int) actual2);
53c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten            }
54c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten            //sleep(10);
55c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten        } else if (actual == -ETIMEDOUT) {
563ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten            (void) write(1, "t", 1);
573ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten        } else {
583ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten            printf("input.read actual = %d\n", (int) actual);
593ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten        }
603ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    }
613ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    return NULL;
623ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten}
633ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten
64c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kastenvolatile bool outputPaused = false;
65c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten
663ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kastenvoid *output_routine(void *arg)
673ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten{
683ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    Context *context = (Context *) arg;
693ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    for (;;) {
70c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten        if (outputPaused) {
71c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten            sleep(1);
72c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten            continue;
73c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten        }
743ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten        struct timespec timeout;
75c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten        timeout.tv_sec = 60;
763ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten        timeout.tv_nsec = 0;
773ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten        char buffer[4];
783ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten        ssize_t actual = context->mTransferReader->read(buffer, sizeof(buffer), &timeout);
79c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten        if (actual > 0) {
80c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten            if ((size_t) actual > sizeof(buffer)) {
81c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten                printf("transfer.read actual = %d\n", (int) actual);
82c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten                abort();
83c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten            }
84c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten            ssize_t actual2 = context->mOutputWriter->write(buffer, actual, NULL /*timeout*/);
85c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten            if (actual2 != actual) {
86c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten                printf("output.write(%d) = %d\n", (int) actual, (int) actual2);
87c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten            }
88c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten        } else if (actual == -ETIMEDOUT) {
893ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten            (void) write(1, "T", 1);
903ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten        } else {
913ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten            printf("transfer.read actual = %d\n", (int) actual);
923ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten        }
933ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    }
943ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    return NULL;
953ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten}
963ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten
973ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kastenint main(int argc, char **argv)
983ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten{
993ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    set_conio_terminal_mode();
1003ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    argc = argc + 0;
1013ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    argv = &argv[0];
1023ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten
103c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten    char inputBuffer[16];
104c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten    audio_utils_fifo inputFifo(sizeof(inputBuffer) /*frameCount*/, 1 /*frameSize*/, inputBuffer,
105c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten            true /*throttlesWriter*/);
1063ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    audio_utils_fifo_writer inputWriter(inputFifo);
107c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten    audio_utils_fifo_reader inputReader(inputFifo, true /*throttlesWriter*/);
108c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten    //inputWriter.setHysteresis(sizeof(inputBuffer) * 1/4, sizeof(inputBuffer) * 3/4);
1093ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten
1103ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    char transferBuffer[64];
1113ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    audio_utils_fifo transferFifo(sizeof(transferBuffer) /*frameCount*/, 1 /*frameSize*/,
112c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten            transferBuffer, true /*throttlesWriter*/);
1133ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    audio_utils_fifo_writer transferWriter(transferFifo);
114c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten    audio_utils_fifo_reader transferReader(transferFifo, true /*throttlesWriter*/);
115c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten    transferReader.setHysteresis(sizeof(transferBuffer) * 3/4, sizeof(transferBuffer) * 1/4);
116c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten    //transferWriter.setEffective(8);
1173ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten
1183ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    char outputBuffer[64];
119c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten    audio_utils_fifo outputFifo(sizeof(outputBuffer) /*frameCount*/, 1 /*frameSize*/, outputBuffer,
120c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten            true /*throttlesWriter*/);
1213ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    audio_utils_fifo_writer outputWriter(outputFifo);
1223ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    audio_utils_fifo_reader outputReader(outputFifo, true /*readerThrottlesWriter*/);
1233ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten
1243ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    Context context;
1253ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    context.mInputWriter = &inputWriter;
1263ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    context.mInputReader = &inputReader;
1273ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    context.mTransferWriter = &transferWriter;
1283ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    context.mTransferReader = &transferReader;
1293ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    context.mOutputWriter = &outputWriter;
1303ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    context.mOutputReader = &outputReader;
1313ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten
1323ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    pthread_t input_thread;
1333ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    int ok = pthread_create(&input_thread, (const pthread_attr_t *) NULL, input_routine,
1343ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten            (void *) &context);
1353ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    pthread_t output_thread;
1363ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    ok = pthread_create(&output_thread, (const pthread_attr_t *) NULL, output_routine,
1373ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten            (void *) &context);
1383ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    ok = ok + 0;
1393ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten
1403ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    for (;;) {
141c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten        char buffer[4];
142c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten        ssize_t actual = outputReader.read(buffer, sizeof(buffer), NULL /*timeout*/);
143c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten        if (actual > 0) {
144c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten            printf("%.*s", (int) actual, buffer);
1453ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten            fflush(stdout);
1463ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten        } else if (actual != 0) {
1473ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten            printf("outputReader.read actual = %d\n", (int) actual);
1483ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten        }
1493ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten        if (kbhit()) {
1503ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten            int ch = getch();
151c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten            if (ch <= 0 || ch == '\003' /*control-C*/) {
1523ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten                break;
1533ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten            }
154c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten            if (ch == 'p')
155c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten                outputPaused = true;
156c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten            else if (ch == 'p')
157c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten                outputPaused = false;
1583ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten            buffer[0] = ch;
159c0924bc38334c7adbf8cbc9cfa9d00559c002652Glenn Kasten            actual = inputWriter.write(buffer, 1, NULL /*timeout*/);
1603ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten            if (actual != 1) {
1613ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten                printf("inputWriter.write actual = %d\n", (int) actual);
1623ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten            }
1633ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten        }
1643ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    }
1653ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten    reset_terminal_mode();
1663ddacbbcd6c119d3c47a50a9291fdff91fb98386Glenn Kasten}
167