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