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<mutex> 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;
producer_thread_should_quit.wakeup();
}
+ std::string get_filename() const
+ {
+ std::lock_guard<std::mutex> lock(filename_mu);
+ return filename;
+ }
+
+ void change_filename(const std::string &new_filename)
+ {
+ std::lock_guard<std::mutex> lock(filename_mu);
+ filename = new_filename;
+ should_interrupt = true;
+ }
+
// Will stop the stream even if it's hung on blocking I/O.
void disconnect()
{
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;
#include <stdint.h>
#include <QAction>
#include <QActionGroup>
+#include <QInputDialog>
#include <QList>
#include <QMenu>
#include <QPoint>
// --- 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);
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) {
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) {
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);
}