]> git.sesse.net Git - nageru/commitdiff
Make it possible to switch camera angles for previews with the 1–4 keys.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Sun, 17 Jun 2018 22:41:06 +0000 (00:41 +0200)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Sun, 17 Jun 2018 22:41:06 +0000 (00:41 +0200)
mainwindow.cpp
mainwindow.h
player.cpp
player.h
ui_mainwindow.ui

index 579dbb116cf150cc20fab3ee3c426862785033f0..67f58624d648fb7feff540daa8458fe074333f46 100644 (file)
@@ -58,6 +58,22 @@ MainWindow::MainWindow()
        connect(play, &QShortcut::activated, ui->play_btn, &QPushButton::click);
        connect(ui->play_btn, &QPushButton::clicked, this, &MainWindow::play_clicked);
 
+       QShortcut *preview_1 = new QShortcut(QKeySequence(Qt::Key_1), this);
+       connect(preview_1, &QShortcut::activated, ui->preview_1_btn, &QPushButton::click);
+       connect(ui->preview_1_btn, &QPushButton::clicked, [this]{ preview_angle_clicked(0); });
+
+       QShortcut *preview_2 = new QShortcut(QKeySequence(Qt::Key_2), this);
+       connect(preview_2, &QShortcut::activated, ui->preview_2_btn, &QPushButton::click);
+       connect(ui->preview_2_btn, &QPushButton::clicked, [this]{ preview_angle_clicked(1); });
+
+       QShortcut *preview_3 = new QShortcut(QKeySequence(Qt::Key_3), this);
+       connect(preview_3, &QShortcut::activated, ui->preview_3_btn, &QPushButton::click);
+       connect(ui->preview_3_btn, &QPushButton::clicked, [this]{ preview_angle_clicked(2); });
+
+       QShortcut *preview_4 = new QShortcut(QKeySequence(Qt::Key_4), this);
+       connect(preview_4, &QShortcut::activated, ui->preview_4_btn, &QPushButton::click);
+       connect(ui->preview_4_btn, &QPushButton::clicked, [this]{ preview_angle_clicked(3); });
+
        preview_player = new Player(ui->preview_display);
        live_player = new Player(ui->live_display);
        live_player->set_done_callback([this]{
@@ -123,6 +139,21 @@ void MainWindow::preview_clicked()
        }
 }
 
+void MainWindow::preview_angle_clicked(unsigned stream_idx)
+{
+       preview_player->override_angle(stream_idx);
+
+       // Change the selection if we were previewing a clip from the clip list.
+       // (The only other thing we could be showing is a pts scrub, and if so,
+       // that would be selected.)
+       QItemSelectionModel *selected = ui->clip_list->selectionModel();
+       if (selected->hasSelection()) {
+               QModelIndex cell = selected->selectedIndexes()[0];
+               int column = int(ClipList::Column::CAMERA_1) + stream_idx;
+               selected->setCurrentIndex(cell.sibling(cell.row(), column), QItemSelectionModel::ClearAndSelect);
+       }
+}
+
 void MainWindow::play_clicked()
 {
        if (playlist_clips->empty()) return;
index 6d214ff696b5ddd73e4e576f8f029e94c524fb21..76124ae63fbb1e6518986dd1e7bc54fff00b3c30 100644 (file)
@@ -40,6 +40,7 @@ private:
        void cue_out_clicked();
        void queue_clicked();
        void preview_clicked();
+       void preview_angle_clicked(unsigned stream_idx);
        void play_clicked();
        void live_player_clip_done();
 
index 1f2d9e50cadbaa2d7938d4dc5ea0cb26c953d133..9f524bb884cdc0b36a46bb3069f7092224a4e6be 100644 (file)
@@ -26,6 +26,7 @@ void Player::thread_func()
                                return new_clip_ready && current_clip.pts_in != -1;
                        });
                        new_clip_ready = false;
+                       playing = true;
                }
 
                Clip clip;
@@ -62,16 +63,25 @@ void Player::thread_func()
                        // Sleep until the next frame start, or until there's a new clip we're supposed to play.
                        {
                                unique_lock<mutex> lock(queue_state_mu);
-                               aborted = new_clip_changed.wait_until(lock, next_frame_start, [this]{
-                                       return new_clip_ready;
+                               new_clip_changed.wait_until(lock, next_frame_start, [this]{
+                                       return new_clip_ready || override_stream_idx != -1;
                                });
-                               if (aborted) break;
+                               if (new_clip_ready) break;
+                               if (override_stream_idx != -1) {
+                                       stream_idx = override_stream_idx;
+                                       override_stream_idx = -1;
+                                       continue;
+                               }
                        }
 
                        destination->setFrame(stream_idx, next_pts);
 
                }
 
+               {
+                       unique_lock<mutex> lock(queue_state_mu);
+                       playing = false;
+               }
                if (done_callback != nullptr && !aborted) {
                        done_callback();
                }
@@ -95,6 +105,49 @@ void Player::play_clip(const Clip &clip, unsigned stream_idx)
        {
                lock_guard<mutex> lock(queue_state_mu);
                new_clip_ready = true;
+               override_stream_idx = -1;
                new_clip_changed.notify_all();
        }
 }
+
+void Player::override_angle(unsigned stream_idx)
+{
+       // Corner case: If a new clip is waiting to be played, change its stream and then we're done. 
+       {
+               unique_lock<mutex> lock(queue_state_mu);
+               if (new_clip_ready) {
+                       lock_guard<mutex> lock2(mu);
+                       current_stream_idx = stream_idx;
+                       return;
+               }
+       }
+
+       // If we are playing a clip, set override_stream_idx, and the player thread will
+       // pick it up and change its internal index.
+       {
+               unique_lock<mutex> lock(queue_state_mu);
+               if (playing) {
+                       override_stream_idx = stream_idx;
+                       new_clip_changed.notify_all();
+               }
+       }
+
+       // OK, so we're standing still, presumably at the end of a clip.
+       // Look at the current pts_out (if it exists), and show the closest
+       // thing we've got.
+       int64_t pts_out;
+       {
+               lock_guard<mutex> lock(mu);
+               if (current_clip.pts_out < 0) {
+                       return;
+               }
+               pts_out = current_clip.pts_out;
+       }
+                       
+       lock_guard<mutex> lock(frame_mu);
+       auto it = upper_bound(frames[stream_idx].begin(), frames[stream_idx].end(), pts_out);
+       if (it == frames[stream_idx].end()) {
+               return;
+       }
+       destination->setFrame(stream_idx, *it);
+}
index bcc81acb1edb52e316f5994542b8193f226d37d2..e251c6e86d8f20446e8692361bad34c2123d15bd 100644 (file)
--- a/player.h
+++ b/player.h
@@ -14,6 +14,7 @@ public:
        Player(JPEGFrameView *destination);
 
        void play_clip(const Clip &clip, unsigned stream_idx);
+       void override_angle(unsigned stream_idx);  // For the current clip only.
 
        // Not thread-safe to set concurrently with playing.
        // Will be called back from the player thread.
@@ -30,9 +31,11 @@ private:
        Clip current_clip;  // Under mu. Can have pts_in = -1 for no clip.
        unsigned current_stream_idx;  // Under mu.
 
-       bool new_clip_ready = false;  // Under queue_state_mu.
        std::mutex queue_state_mu;
        std::condition_variable new_clip_changed;
+       bool new_clip_ready = false;  // Under queue_state_mu.
+       bool playing = false;  // Under queue_state_mu.
+       int override_stream_idx = -1;  // Under queue_state_mu.
 };
 
 #endif  // !defined(_PLAYER_H)
index c3597d982071f97563da6ecc7cb72bef47e2b9db..2dd07d7ff306b11411f9363bbbb3a4f6837d7929 100644 (file)
          </layout>
         </item>
         <item>
-         <layout class="QVBoxLayout" name="verticalLayout" stretch="1,0">
+         <layout class="QVBoxLayout" name="preview_pane" stretch="1,0">
           <item>
            <widget class="JPEGFrameView" name="preview_display" native="true"/>
           </item>
           <item>
-           <widget class="QLabel" name="label_2">
-            <property name="text">
-             <string>Preview output</string>
-            </property>
-            <property name="alignment">
-             <set>Qt::AlignCenter</set>
+           <layout class="QHBoxLayout" name="horizontalLayout_3">
+            <property name="spacing">
+             <number>0</number>
             </property>
-           </widget>
+            <item>
+             <widget class="QLabel" name="label_2">
+              <property name="text">
+               <string>Preview output</string>
+              </property>
+              <property name="alignment">
+               <set>Qt::AlignCenter</set>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="preview_1_btn">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="maximumSize">
+               <size>
+                <width>20</width>
+                <height>17</height>
+               </size>
+              </property>
+              <property name="text">
+               <string>1</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="preview_2_btn">
+              <property name="sizePolicy">
+               <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+                <horstretch>0</horstretch>
+                <verstretch>0</verstretch>
+               </sizepolicy>
+              </property>
+              <property name="maximumSize">
+               <size>
+                <width>20</width>
+                <height>17</height>
+               </size>
+              </property>
+              <property name="text">
+               <string>2</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="preview_3_btn">
+              <property name="maximumSize">
+               <size>
+                <width>20</width>
+                <height>17</height>
+               </size>
+              </property>
+              <property name="text">
+               <string>3</string>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="preview_4_btn">
+              <property name="maximumSize">
+               <size>
+                <width>20</width>
+                <height>17</height>
+               </size>
+              </property>
+              <property name="text">
+               <string>4</string>
+              </property>
+             </widget>
+            </item>
+           </layout>
           </item>
          </layout>
         </item>