From 4d4386716f258413132b8696315cb4efbf2c8b45 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Mon, 23 Apr 2018 20:09:04 +0200 Subject: [PATCH] Allow changing FFmpeg URL from the context menu. --- ffmpeg_capture.cpp | 12 +++++++++--- ffmpeg_capture.h | 14 ++++++++++++++ glwidget.cpp | 22 +++++++++++++++++++++- mixer.cpp | 11 +++++++++++ mixer.h | 4 ++++ 5 files changed, 59 insertions(+), 4 deletions(-) diff --git a/ffmpeg_capture.cpp b/ffmpeg_capture.cpp index a0904dc..b7db50c 100644 --- a/ffmpeg_capture.cpp +++ b/ffmpeg_capture.cpp @@ -282,9 +282,15 @@ void FFmpegCapture::producer_thread_func() pthread_setname_np(pthread_self(), thread_name); while (!producer_thread_should_quit.should_quit()) { - string pathname = search_for_file(filename); - if (filename.empty()) { - fprintf(stderr, "%s not found, sleeping one second and trying again...\n", filename.c_str()); + string filename_copy; + { + lock_guard lock(filename_mu); + filename_copy = filename; + } + + string pathname = search_for_file(filename_copy); + if (pathname.empty()) { + fprintf(stderr, "%s not found, sleeping one second and trying again...\n", filename_copy.c_str()); send_disconnected_frame(); producer_thread_should_quit.sleep_for(seconds(1)); continue; diff --git a/ffmpeg_capture.h b/ffmpeg_capture.h index 336f6bd..8a513df 100644 --- a/ffmpeg_capture.h +++ b/ffmpeg_capture.h @@ -77,6 +77,19 @@ public: producer_thread_should_quit.wakeup(); } + std::string get_filename() const + { + std::lock_guard lock(filename_mu); + return filename; + } + + void change_filename(const std::string &new_filename) + { + std::lock_guard lock(filename_mu); + filename = new_filename; + should_interrupt = true; + } + // Will stop the stream even if it's hung on blocking I/O. void disconnect() { @@ -215,6 +228,7 @@ private: static int interrupt_cb_thunk(void *unique); int interrupt_cb(); + mutable std::mutex filename_mu; std::string description, filename; uint16_t timecode = 0; unsigned width, height; diff --git a/glwidget.cpp b/glwidget.cpp index 7caee37..c3e82da 100644 --- a/glwidget.cpp +++ b/glwidget.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -239,7 +240,15 @@ void GLWidget::show_preview_context_menu(unsigned signal_num, const QPoint &pos) // --- The choices in the next few options depend a lot on which card is active --- bool has_auto_mode = false; - if (!is_ffmpeg) { + QAction *change_url_action = nullptr; + if (is_ffmpeg) { + // Add a menu to change the source URL if we're an FFmpeg card. + // (The theme can still override.) + if (global_mixer->card_is_ffmpeg(current_card)) { + change_url_action = new QAction("Change source filename/URL…", &menu); + menu.addAction(change_url_action); + } + } else { // Add a submenu for selecting video input, with an action for each input. QMenu video_input_submenu; QActionGroup video_input_group(&video_input_submenu); @@ -341,6 +350,17 @@ void GLWidget::show_preview_context_menu(unsigned signal_num, const QPoint &pos) QAction *selected_item = menu.exec(global_pos); if (audio_source_action != nullptr && selected_item == audio_source_action) { global_audio_mixer->set_simple_input(current_card); + } else if (change_url_action != nullptr && selected_item == change_url_action) { + // NOTE: We can't use “this” as parent, since the dialog would inherit our style sheet. + bool ok; + const string url = global_mixer->get_ffmpeg_filename(current_card); + QString new_url = QInputDialog::getText(window(), tr("Change URL"), + tr("Enter new filename/URL for the given video input:"), QLineEdit::Normal, + QString::fromStdString(url), &ok); + // FIXME prefill the input + if (ok) { + global_mixer->set_ffmpeg_filename(current_card, new_url.toStdString()); + } } else if (selected_item == master_clock_action) { global_mixer->set_master_clock(signal_num); } else if (selected_item != nullptr) { diff --git a/mixer.cpp b/mixer.cpp index 73a59d5..5cee300 100644 --- a/mixer.cpp +++ b/mixer.cpp @@ -1587,6 +1587,17 @@ map Mixer::get_available_output_video_modes() const return cards[desired_output_card_index].output->get_available_video_modes(); } +string Mixer::get_ffmpeg_filename(unsigned card_index) const +{ + assert(card_index >= num_cards && card_index < num_cards + num_video_inputs); + return ((FFmpegCapture *)(cards[card_index].capture.get()))->get_filename(); +} + +void Mixer::set_ffmpeg_filename(unsigned card_index, const string &filename) { + assert(card_index >= num_cards && card_index < num_cards + num_video_inputs); + ((FFmpegCapture *)(cards[card_index].capture.get()))->change_filename(filename); +} + Mixer::OutputChannel::~OutputChannel() { if (has_current_frame) { diff --git a/mixer.h b/mixer.h index 03a5163..5a3e203 100644 --- a/mixer.h +++ b/mixer.h @@ -374,6 +374,10 @@ public: cards[card_index].capture->set_audio_input(input); } + std::string get_ffmpeg_filename(unsigned card_index) const; + + void set_ffmpeg_filename(unsigned card_index, const std::string &filename); + void change_x264_bitrate(unsigned rate_kbit) { video_encoder->change_x264_bitrate(rate_kbit); } -- 2.39.2