Home | History | Annotate | Download | only in audio
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
      5  * use this file except in compliance with the License. You may obtain a copy of
      6  * the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
     12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
     13  * License for the specific language governing permissions and limitations under
     14  * the License.
     15  */
     16 
     17 
     18 #ifndef CTSAUDIO_REMOTEAUDIO_H
     19 #define CTSAUDIO_REMOTEAUDIO_H
     20 
     21 #include <map>
     22 
     23 #include <utils/Looper.h>
     24 #include <utils/StrongPointer.h>
     25 #include <utils/threads.h>
     26 
     27 #include "audio/Buffer.h"
     28 #include "AudioProtocol.h"
     29 #include "ClientSocket.h"
     30 #include "Semaphore.h"
     31 
     32 class CommandHandler;
     33 /**
     34  * Tcp communication runs in a separate thread,
     35  * and client can communicate using public APIs
     36  * Assumption: only one command at a time. No other command can come
     37  * while a command is pending.
     38  */
     39 class RemoteAudio: public android::Thread {
     40 public:
     41 
     42     RemoteAudio(ClientSocket& socket);
     43     virtual ~RemoteAudio();
     44 
     45     /** launch a thread, and connect to host */
     46     bool init(int port);
     47     bool downloadData(const android::String8 name, android::sp<Buffer>& buffer, int& id);
     48     // <0 : not found
     49     int getDataId(const android::String8& name);
     50     bool startPlayback(bool stereo, int samplingF, int mode, int volume,
     51             int id, int numberRepetition);
     52     void stopPlayback();
     53     bool waitForPlaybackCompletion();
     54     // buffer.getSize() determines number of samples
     55     bool startRecording(bool stereo, int samplingF, int mode, int volume,
     56             android::sp<Buffer>& buffer);
     57     bool waitForRecordingCompletion();
     58     void stopRecording();
     59     /** should be called before RemoteAudio is destroyed */
     60     void release();
     61 
     62 private:
     63     RemoteAudio(const RemoteAudio&);
     64 
     65     bool threadLoop();
     66     void wakeClient(bool result);
     67     void cleanup(bool notifyClient);
     68 
     69     bool handlePacket();
     70     static int socketRxCallback(int fd, int events, void* data);
     71 
     72     class CommandHandler;
     73     void sendCommand(android::sp<android::MessageHandler>& command);
     74 
     75     // this is just semaphore wait without any addition
     76     bool waitForCompletion(android::sp<android::MessageHandler>& command, int timeInMSec);
     77     // common code for waitForXXXCompletion
     78     bool waitForPlaybackOrRecordingCompletion(
     79             android::sp<android::MessageHandler>& commandHandler);
     80     // common code for stopXXX
     81     void doStop(android::sp<android::MessageHandler>& commandHandler, AudioProtocol::CommandId id);
     82 
     83     CommandHandler* toCommandHandler(android::sp<android::MessageHandler>& command) {
     84         return reinterpret_cast<CommandHandler*>(command.get());
     85     };
     86 
     87 private:
     88     bool mExitRequested;
     89     bool mInitResult;
     90     // used only for notifying successful init
     91     Semaphore mInitWait;
     92 
     93 
     94     enum EventId {
     95         EIdSocket = 1,
     96     };
     97     static const int CLIENT_WAIT_TIMEOUT_MSEC = 2000;
     98     int mPort;
     99     ClientSocket& mSocket;
    100 
    101 
    102     android::sp<android::Looper> mLooper;
    103 
    104     friend class CommandHandler;
    105 
    106     class CommandHandler: public android::MessageHandler {
    107     public:
    108         enum ClientCommands {
    109             EExit = 1,
    110         };
    111         CommandHandler(RemoteAudio& thread, int command)
    112             : mThread(thread),
    113               mMessage(command),
    114               mNotifyOnReply(false),
    115               mActive(false) {};
    116         virtual ~CommandHandler() {};
    117         void handleMessage(const android::Message& message);
    118         bool timedWait(int timeInMSec) {
    119             return mClientWait.timedWait(timeInMSec);
    120         };
    121         AudioParam& getParam() {
    122             return mParam;
    123         };
    124         android::Message& getMessage() {
    125             return mMessage;
    126         };
    127 
    128     private:
    129         RemoteAudio& mThread;
    130         AudioParam mParam;
    131         Semaphore mClientWait;
    132         android::Mutex mStateLock;
    133         android::Message mMessage;
    134         bool mResult;
    135         bool mNotifyOnReply;
    136         bool mActive;
    137         friend class RemoteAudio;
    138     };
    139     android::sp<android::MessageHandler> mDownloadHandler;
    140     android::sp<android::MessageHandler> mPlaybackHandler;
    141     android::sp<android::MessageHandler> mRecordingHandler;
    142 
    143     AudioProtocol* mCmds[AudioProtocol::ECmdLast - AudioProtocol::ECmdStart];
    144     int mDownloadId;
    145     std::map<int, android::sp<Buffer> > mBufferList;
    146     std::map<android::String8, int> mIdMap;
    147 };
    148 
    149 
    150 
    151 #endif // CTSAUDIO_REMOTEAUDIO_H
    152