feat(microphone): apply selected capture device
This commit is contained in:
parent
e0da0f1f80
commit
05ab64cf76
@ -34,7 +34,11 @@ namespace cmvr::device{
|
||||
}
|
||||
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 pause() {}
|
||||
virtual void resume() {}
|
||||
|
||||
@ -33,7 +33,8 @@ namespace cmvr::device {
|
||||
bool start() override;
|
||||
bool stop() 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 pause() override;
|
||||
void resume() override;
|
||||
|
||||
@ -149,20 +149,46 @@ void ffmpegMicroPhone::getState(MicrophoneState& 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_);
|
||||
{
|
||||
lock_guard lock(mtx_);
|
||||
if (state_.is_recording) {
|
||||
CMVR_LOG(ERROR) << "[ffmpegMicroPhone] (startRecording): microphone is already recording";
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
if (stream_count_ > 0 || is_capturing_) {
|
||||
state_.is_error = true;
|
||||
state_.error_message = "cannot start recording while microphone streaming is active";
|
||||
CMVR_LOG(ERROR) << "[ffmpegMicroPhone] " << state_.error_message;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t dot_pos = outputFilePath.find_last_of('.');
|
||||
@ -174,7 +200,7 @@ void ffmpegMicroPhone::startRecording(const std::string& outputFilePath)
|
||||
lock_guard lock(mtx_);
|
||||
state_.is_error = true;
|
||||
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_.error_message.clear();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ffmpegMicroPhone::stopRecording()
|
||||
|
||||
@ -25,6 +25,29 @@ grpc::Status failResponse(ResponseT* response, const std::string& message) {
|
||||
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()) {}
|
||||
@ -96,10 +119,22 @@ grpc::Status gRPCMicroPhoneServiceImpl::StartRecord(grpc::ServerContext* context
|
||||
if (!dev) {
|
||||
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()) {
|
||||
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);
|
||||
setCurrentTimestamp(response->mutable_header()->mutable_timestamp());
|
||||
CMVR_LOG(DEBUG) << "[gRPCMicroPhoneServiceImpl] (StartRecord): success, id=" << dev_id
|
||||
@ -199,6 +234,16 @@ grpc::Status gRPCMicroPhoneServiceImpl::StreamAudio(grpc::ServerContext* context
|
||||
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();
|
||||
const std::string track_id = cmvr::media::microphoneTrackId(dev_id);
|
||||
if (!cmvr::media::ensureMicrophoneMediaSource(media_hub, dev)) {
|
||||
|
||||
@ -43,6 +43,7 @@ message StartMicRecordingCommand {
|
||||
message Request {
|
||||
CommandHeader.Request header = 1;
|
||||
string file_path = 2;
|
||||
string input_device = 3;
|
||||
}
|
||||
message Feedback {
|
||||
CommandHeader.Feedback header = 1;
|
||||
@ -80,6 +81,7 @@ message ResumeMicRecordingCommand {
|
||||
message StreamMicAudioCommand {
|
||||
message Request {
|
||||
CommandHeader.Request header = 1;
|
||||
string input_device = 2;
|
||||
}
|
||||
message Feedback {
|
||||
CommandHeader.Feedback header = 1;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user