You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
156 lines
4.7 KiB
156 lines
4.7 KiB
/*
|
|
* Copyright (C) 2012 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
* use this file except in compliance with the License. You may obtain a copy of
|
|
* the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations under
|
|
* the License.
|
|
*/
|
|
|
|
|
|
#ifndef CTSAUDIO_REMOTEAUDIO_H
|
|
#define CTSAUDIO_REMOTEAUDIO_H
|
|
|
|
#include <map>
|
|
|
|
#include <utils/Looper.h>
|
|
#include <utils/String8.h>
|
|
#include <utils/StrongPointer.h>
|
|
#include <utils/threads.h>
|
|
|
|
#include "audio/Buffer.h"
|
|
#include "AudioProtocol.h"
|
|
#include "ClientSocket.h"
|
|
#include "Semaphore.h"
|
|
|
|
class CommandHandler;
|
|
/**
|
|
* Tcp communication runs in a separate thread,
|
|
* and client can communicate using public APIs
|
|
* Assumption: only one command at a time. No other command can come
|
|
* while a command is pending.
|
|
*/
|
|
class RemoteAudio: public android::Thread {
|
|
public:
|
|
|
|
explicit RemoteAudio(ClientSocket& socket);
|
|
virtual ~RemoteAudio();
|
|
|
|
/** launch a thread, and connect to host */
|
|
bool init(int port);
|
|
bool downloadData(const android::String8& name, android::sp<Buffer>& buffer, int& id);
|
|
// <0 : not found
|
|
int getDataId(const android::String8& name);
|
|
bool startPlayback(bool stereo, int samplingF, int mode, int volume,
|
|
int id, int numberRepetition);
|
|
void stopPlayback();
|
|
bool waitForPlaybackCompletion();
|
|
// buffer.getSize() determines number of samples
|
|
bool startRecording(bool stereo, int samplingF, int mode, int volume,
|
|
android::sp<Buffer>& buffer);
|
|
bool waitForRecordingCompletion();
|
|
void stopRecording();
|
|
|
|
bool getDeviceInfo(android::String8& data);
|
|
/** should be called before RemoteAudio is destroyed */
|
|
void release();
|
|
|
|
private:
|
|
RemoteAudio(const RemoteAudio&);
|
|
|
|
bool threadLoop();
|
|
void wakeClient(bool result);
|
|
void cleanup(bool notifyClient);
|
|
|
|
bool handlePacket();
|
|
static int socketRxCallback(int fd, int events, void* data);
|
|
|
|
class CommandHandler;
|
|
void sendCommand(android::sp<android::MessageHandler>& command);
|
|
|
|
// this is just semaphore wait without any addition
|
|
bool waitForCompletion(android::sp<android::MessageHandler>& command, int timeInMSec);
|
|
// common code for waitForXXXCompletion
|
|
bool waitForPlaybackOrRecordingCompletion(
|
|
android::sp<android::MessageHandler>& commandHandler);
|
|
// common code for stopXXX
|
|
void doStop(android::sp<android::MessageHandler>& commandHandler, AudioProtocol::CommandId id);
|
|
|
|
CommandHandler* toCommandHandler(android::sp<android::MessageHandler>& command) {
|
|
return reinterpret_cast<CommandHandler*>(command.get());
|
|
};
|
|
|
|
private:
|
|
bool mExitRequested;
|
|
bool mInitResult;
|
|
// used only for notifying successful init
|
|
Semaphore mInitWait;
|
|
|
|
|
|
enum EventId {
|
|
EIdSocket = 1,
|
|
};
|
|
static const int CLIENT_WAIT_TIMEOUT_MSEC = 2000;
|
|
int mPort;
|
|
ClientSocket& mSocket;
|
|
|
|
|
|
android::sp<android::Looper> mLooper;
|
|
|
|
friend class CommandHandler;
|
|
|
|
class CommandHandler: public android::MessageHandler {
|
|
public:
|
|
enum ClientCommands {
|
|
EExit = 1,
|
|
};
|
|
CommandHandler(RemoteAudio& thread, int command)
|
|
: mThread(thread),
|
|
mMessage(command),
|
|
mNotifyOnReply(false),
|
|
mActive(false) {};
|
|
virtual ~CommandHandler() {};
|
|
void handleMessage(const android::Message& message);
|
|
bool timedWait(int timeInMSec) {
|
|
return mClientWait.timedWait(timeInMSec);
|
|
};
|
|
AudioParam& getParam() {
|
|
return mParam;
|
|
};
|
|
android::Message& getMessage() {
|
|
return mMessage;
|
|
};
|
|
|
|
private:
|
|
RemoteAudio& mThread;
|
|
AudioParam mParam;
|
|
Semaphore mClientWait;
|
|
android::Mutex mStateLock;
|
|
android::Message mMessage;
|
|
bool mResult;
|
|
bool mNotifyOnReply;
|
|
bool mActive;
|
|
friend class RemoteAudio;
|
|
};
|
|
android::sp<android::MessageHandler> mDownloadHandler;
|
|
android::sp<android::MessageHandler> mPlaybackHandler;
|
|
android::sp<android::MessageHandler> mRecordingHandler;
|
|
android::sp<android::MessageHandler> mDeviceInfoHandler;
|
|
|
|
AudioProtocol* mCmds[AudioProtocol::ECmdLast - AudioProtocol::ECmdStart];
|
|
int mDownloadId;
|
|
std::map<int, android::sp<Buffer> > mBufferList;
|
|
std::map<android::String8, int> mIdMap;
|
|
};
|
|
|
|
|
|
|
|
#endif // CTSAUDIO_REMOTEAUDIO_H
|