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/String8.h>
     25 #include <utils/StrongPointer.h>
     26 #include <utils/threads.h>
     27 
     28 #include "audio/Buffer.h"
     29 #include "AudioProtocol.h"
     30 #include "ClientSocket.h"
     31 #include "Semaphore.h"
     32 
     33 class CommandHandler;
     34 /**
     35  * Tcp communication runs in a separate thread,
     36  * and client can communicate using public APIs
     37  * Assumption: only one command at a time. No other command can come
     38  * while a command is pending.
     39  */
     40 class RemoteAudio: public android::Thread {
     41 public:
     42 
     43     explicit RemoteAudio(ClientSocket& socket);
     44     virtual ~RemoteAudio();
     45 
     46     /** launch a thread, and connect to host */
     47     bool init(int port);
     48     bool downloadData(const android::String8& name, android::sp<Buffer>& buffer, int& id);
     49     // <0 : not found
     50     int getDataId(const android::String8& name);
     51     bool startPlayback(bool stereo, int samplingF, int mode, int volume,
     52             int id, int numberRepetition);
     53     void stopPlayback();
     54     bool waitForPlaybackCompletion();
     55     // buffer.getSize() determines number of samples
     56     bool startRecording(bool stereo, int samplingF, int mode, int volume,
     57             android::sp<Buffer>& buffer);
     58     bool waitForRecordingCompletion();
     59     void stopRecording();
     60 
     61     bool getDeviceInfo(android::String8& data);
     62     /** should be called before RemoteAudio is destroyed */
     63     void release();
     64 
     65 private:
     66     RemoteAudio(const RemoteAudio&);
     67 
     68     bool threadLoop();
     69     void wakeClient(bool result);
     70     void cleanup(bool notifyClient);
     71 
     72     bool handlePacket();
     73     static int socketRxCallback(int fd, int events, void* data);
     74 
     75     class CommandHandler;
     76     void sendCommand(android::sp<android::MessageHandler>& command);
     77 
     78     // this is just semaphore wait without any addition
     79     bool waitForCompletion(android::sp<android::MessageHandler>& command, int timeInMSec);
     80     // common code for waitForXXXCompletion
     81     bool waitForPlaybackOrRecordingCompletion(
     82             android::sp<android::MessageHandler>& commandHandler);
     83     // common code for stopXXX
     84     void doStop(android::sp<android::MessageHandler>& commandHandler, AudioProtocol::CommandId id);
     85 
     86     CommandHandler* toCommandHandler(android::sp<android::MessageHandler>& command) {
     87         return reinterpret_cast<CommandHandler*>(command.get());
     88     };
     89 
     90 private:
     91     bool mExitRequested;
     92     bool mInitResult;
     93     // used only for notifying successful init
     94     Semaphore mInitWait;
     95 
     96 
     97     enum EventId {
     98         EIdSocket = 1,
     99     };
    100     static const int CLIENT_WAIT_TIMEOUT_MSEC = 2000;
    101     int mPort;
    102     ClientSocket& mSocket;
    103 
    104 
    105     android::sp<android::Looper> mLooper;
    106 
    107     friend class CommandHandler;
    108 
    109     class CommandHandler: public android::MessageHandler {
    110     public:
    111         enum ClientCommands {
    112             EExit = 1,
    113         };
    114         CommandHandler(RemoteAudio& thread, int command)
    115             : mThread(thread),
    116               mMessage(command),
    117               mNotifyOnReply(false),
    118               mActive(false) {};
    119         virtual ~CommandHandler() {};
    120         void handleMessage(const android::Message& message);
    121         bool timedWait(int timeInMSec) {
    122             return mClientWait.timedWait(timeInMSec);
    123         };
    124         AudioParam& getParam() {
    125             return mParam;
    126         };
    127         android::Message& getMessage() {
    128             return mMessage;
    129         };
    130 
    131     private:
    132         RemoteAudio& mThread;
    133         AudioParam mParam;
    134         Semaphore mClientWait;
    135         android::Mutex mStateLock;
    136         android::Message mMessage;
    137         bool mResult;
    138         bool mNotifyOnReply;
    139         bool mActive;
    140         friend class RemoteAudio;
    141     };
    142     android::sp<android::MessageHandler> mDownloadHandler;
    143     android::sp<android::MessageHandler> mPlaybackHandler;
    144     android::sp<android::MessageHandler> mRecordingHandler;
    145     android::sp<android::MessageHandler> mDeviceInfoHandler;
    146 
    147     AudioProtocol* mCmds[AudioProtocol::ECmdLast - AudioProtocol::ECmdStart];
    148     int mDownloadId;
    149     std::map<int, android::sp<Buffer> > mBufferList;
    150     std::map<android::String8, int> mIdMap;
    151 };
    152 
    153 
    154 
    155 #endif // CTSAUDIO_REMOTEAUDIO_H
    156