feat(microphone): apply selected capture device
This commit is contained in:
parent
e0da0f1f80
commit
05ab64cf76
@ -34,7 +34,11 @@ namespace cmvr::device{
|
|||||||
}
|
}
|
||||||
return health;
|
return health;
|
||||||
}
|
}
|
||||||
virtual void startRecording(const std::string& outputFilePath) {}
|
virtual bool selectInputDevice(const std::string& input_device) {
|
||||||
|
(void)input_device;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
virtual bool startRecording(const std::string& outputFilePath) { return false; }
|
||||||
virtual void stopRecording() {}
|
virtual void stopRecording() {}
|
||||||
virtual void pause() {}
|
virtual void pause() {}
|
||||||
virtual void resume() {}
|
virtual void resume() {}
|
||||||
|
|||||||
@ -33,7 +33,8 @@ namespace cmvr::device {
|
|||||||
bool start() override;
|
bool start() override;
|
||||||
bool stop() override;
|
bool stop() override;
|
||||||
void getState(MicrophoneState &state) override;
|
void getState(MicrophoneState &state) override;
|
||||||
void startRecording(const std::string& outputFilePath) override;
|
bool selectInputDevice(const std::string& input_device) override;
|
||||||
|
bool startRecording(const std::string& outputFilePath) override;
|
||||||
void stopRecording() override;
|
void stopRecording() override;
|
||||||
void pause() override;
|
void pause() override;
|
||||||
void resume() override;
|
void resume() override;
|
||||||
|
|||||||
@ -149,20 +149,46 @@ void ffmpegMicroPhone::getState(MicrophoneState& state)
|
|||||||
state = state_;
|
state = state_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ffmpegMicroPhone::startRecording(const std::string& outputFilePath)
|
bool ffmpegMicroPhone::selectInputDevice(const std::string& input_device)
|
||||||
|
{
|
||||||
|
if (input_device.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard capture_lock(capture_mutex_);
|
||||||
|
lock_guard lock(mtx_);
|
||||||
|
if (input_device == input_device_) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (is_capturing_.load(std::memory_order_acquire) ||
|
||||||
|
state_.is_recording || stream_count_ > 0) {
|
||||||
|
state_.is_error = true;
|
||||||
|
state_.error_message = "cannot switch microphone input while capture is active";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
input_device_ = input_device;
|
||||||
|
config_.set_input_device(input_device);
|
||||||
|
state_.is_error = false;
|
||||||
|
state_.error_message.clear();
|
||||||
|
CMVR_LOG(INFO) << "[ffmpegMicroPhone] Selected input device: " << input_device_;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ffmpegMicroPhone::startRecording(const std::string& outputFilePath)
|
||||||
{
|
{
|
||||||
std::lock_guard capture_lock(capture_mutex_);
|
std::lock_guard capture_lock(capture_mutex_);
|
||||||
{
|
{
|
||||||
lock_guard lock(mtx_);
|
lock_guard lock(mtx_);
|
||||||
if (state_.is_recording) {
|
if (state_.is_recording) {
|
||||||
CMVR_LOG(ERROR) << "[ffmpegMicroPhone] (startRecording): microphone is already recording";
|
CMVR_LOG(ERROR) << "[ffmpegMicroPhone] (startRecording): microphone is already recording";
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
if (stream_count_ > 0 || is_capturing_) {
|
if (stream_count_ > 0 || is_capturing_) {
|
||||||
state_.is_error = true;
|
state_.is_error = true;
|
||||||
state_.error_message = "cannot start recording while microphone streaming is active";
|
state_.error_message = "cannot start recording while microphone streaming is active";
|
||||||
CMVR_LOG(ERROR) << "[ffmpegMicroPhone] " << state_.error_message;
|
CMVR_LOG(ERROR) << "[ffmpegMicroPhone] " << state_.error_message;
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t dot_pos = outputFilePath.find_last_of('.');
|
size_t dot_pos = outputFilePath.find_last_of('.');
|
||||||
@ -174,7 +200,7 @@ void ffmpegMicroPhone::startRecording(const std::string& outputFilePath)
|
|||||||
lock_guard lock(mtx_);
|
lock_guard lock(mtx_);
|
||||||
state_.is_error = true;
|
state_.is_error = true;
|
||||||
state_.error_message = "FFmpeg init error";
|
state_.error_message = "FFmpeg init error";
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -183,6 +209,7 @@ void ffmpegMicroPhone::startRecording(const std::string& outputFilePath)
|
|||||||
state_.is_error = false;
|
state_.is_error = false;
|
||||||
state_.error_message.clear();
|
state_.error_message.clear();
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ffmpegMicroPhone::stopRecording()
|
void ffmpegMicroPhone::stopRecording()
|
||||||
|
|||||||
@ -25,6 +25,29 @@ grpc::Status failResponse(ResponseT* response, const std::string& message) {
|
|||||||
return grpc::Status::OK;
|
return grpc::Status::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string selectInputDevice(
|
||||||
|
const std::shared_ptr<AbstractMicrophone>& microphone,
|
||||||
|
const std::string& input_device) {
|
||||||
|
if (input_device.empty()) {
|
||||||
|
return "Microphone input_device is required";
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto available_devices = listAvailableMicrophoneInputDevices();
|
||||||
|
const auto selected = std::find_if(
|
||||||
|
available_devices.begin(),
|
||||||
|
available_devices.end(),
|
||||||
|
[&input_device](const MicrophoneInputDeviceInfo& device) {
|
||||||
|
return device.input_device == input_device;
|
||||||
|
});
|
||||||
|
if (selected == available_devices.end()) {
|
||||||
|
return "Microphone input device is unavailable: " + input_device;
|
||||||
|
}
|
||||||
|
if (!microphone->selectInputDevice(input_device)) {
|
||||||
|
return "Cannot select microphone input device while capture is active: " + input_device;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gRPCMicroPhoneServiceImpl::gRPCMicroPhoneServiceImpl(): dmgr_(DeviceManager::getInstance()) {}
|
gRPCMicroPhoneServiceImpl::gRPCMicroPhoneServiceImpl(): dmgr_(DeviceManager::getInstance()) {}
|
||||||
@ -96,10 +119,22 @@ grpc::Status gRPCMicroPhoneServiceImpl::StartRecord(grpc::ServerContext* context
|
|||||||
if (!dev) {
|
if (!dev) {
|
||||||
return failResponse(response, "Microphone device not found: " + dev_id);
|
return failResponse(response, "Microphone device not found: " + dev_id);
|
||||||
}
|
}
|
||||||
|
const std::string selection_error = selectInputDevice(dev, request->input_device());
|
||||||
|
if (!selection_error.empty()) {
|
||||||
|
return failResponse(response, selection_error);
|
||||||
|
}
|
||||||
if (!dev->start()) {
|
if (!dev->start()) {
|
||||||
return failResponse(response, "Failed to start microphone: " + dev_id);
|
return failResponse(response, "Failed to start microphone: " + dev_id);
|
||||||
}
|
}
|
||||||
dev->startRecording(request->file_path());
|
if (!dev->startRecording(request->file_path())) {
|
||||||
|
MicrophoneState state;
|
||||||
|
dev->getState(state);
|
||||||
|
return failResponse(
|
||||||
|
response,
|
||||||
|
state.error_message.empty()
|
||||||
|
? "Failed to start microphone recording: " + dev_id
|
||||||
|
: state.error_message);
|
||||||
|
}
|
||||||
response->mutable_header()->set_success(true);
|
response->mutable_header()->set_success(true);
|
||||||
setCurrentTimestamp(response->mutable_header()->mutable_timestamp());
|
setCurrentTimestamp(response->mutable_header()->mutable_timestamp());
|
||||||
CMVR_LOG(DEBUG) << "[gRPCMicroPhoneServiceImpl] (StartRecord): success, id=" << dev_id
|
CMVR_LOG(DEBUG) << "[gRPCMicroPhoneServiceImpl] (StartRecord): success, id=" << dev_id
|
||||||
@ -199,6 +234,16 @@ grpc::Status gRPCMicroPhoneServiceImpl::StreamAudio(grpc::ServerContext* context
|
|||||||
return grpc::Status::OK;
|
return grpc::Status::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string selection_error = selectInputDevice(dev, request->input_device());
|
||||||
|
if (!selection_error.empty()) {
|
||||||
|
api::StreamMicAudioCommand_Feedback feedback;
|
||||||
|
feedback.mutable_header()->set_success(false);
|
||||||
|
feedback.mutable_header()->set_error_message(selection_error);
|
||||||
|
setCurrentTimestamp(feedback.mutable_header()->mutable_timestamp());
|
||||||
|
writer->Write(feedback);
|
||||||
|
return grpc::Status::OK;
|
||||||
|
}
|
||||||
|
|
||||||
auto& media_hub = cmvr::media::globalMediaSourceHub();
|
auto& media_hub = cmvr::media::globalMediaSourceHub();
|
||||||
const std::string track_id = cmvr::media::microphoneTrackId(dev_id);
|
const std::string track_id = cmvr::media::microphoneTrackId(dev_id);
|
||||||
if (!cmvr::media::ensureMicrophoneMediaSource(media_hub, dev)) {
|
if (!cmvr::media::ensureMicrophoneMediaSource(media_hub, dev)) {
|
||||||
|
|||||||
@ -43,6 +43,7 @@ message StartMicRecordingCommand {
|
|||||||
message Request {
|
message Request {
|
||||||
CommandHeader.Request header = 1;
|
CommandHeader.Request header = 1;
|
||||||
string file_path = 2;
|
string file_path = 2;
|
||||||
|
string input_device = 3;
|
||||||
}
|
}
|
||||||
message Feedback {
|
message Feedback {
|
||||||
CommandHeader.Feedback header = 1;
|
CommandHeader.Feedback header = 1;
|
||||||
@ -80,6 +81,7 @@ message ResumeMicRecordingCommand {
|
|||||||
message StreamMicAudioCommand {
|
message StreamMicAudioCommand {
|
||||||
message Request {
|
message Request {
|
||||||
CommandHeader.Request header = 1;
|
CommandHeader.Request header = 1;
|
||||||
|
string input_device = 2;
|
||||||
}
|
}
|
||||||
message Feedback {
|
message Feedback {
|
||||||
CommandHeader.Feedback header = 1;
|
CommandHeader.Feedback header = 1;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user