X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=mainwindow.cpp;h=dd3c82764537bc23cb588a1dc9978e54db21b667;hb=3795723be95f2fe82f3c8b8b45b1a905b2c811fd;hp=6e999bad4ba653253c81b54073879d7fc87e06c0;hpb=020a2721a6537ffecc82a26c097da64551571617;p=nageru diff --git a/mainwindow.cpp b/mainwindow.cpp index 6e999ba..dd3c827 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -3,6 +3,7 @@ #include "clip_list.h" #include "disk_space_estimator.h" #include "flags.h" +#include "frame_on_disk.h" #include "player.h" #include "post_to_main_thread.h" #include "timebase.h" @@ -25,8 +26,6 @@ static ClipList *cliplist_clips; static PlayList *playlist_clips; extern int64_t current_pts; -extern mutex frame_mu; -extern vector frames[MAX_STREAMS]; MainWindow::MainWindow() : ui(new Ui::MainWindow), @@ -130,9 +129,9 @@ MainWindow::MainWindow() }); }); live_player->set_next_clip_callback(bind(&MainWindow::live_player_get_next_clip, this)); - live_player->set_progress_callback([this](double played_this_clip, double total_length) { - post_to_main_thread([this, played_this_clip, total_length] { - live_player_clip_progress(played_this_clip, total_length); + live_player->set_progress_callback([this](const map &progress) { + post_to_main_thread([this, progress] { + live_player_clip_progress(progress); }); }); set_output_status("paused"); @@ -199,12 +198,23 @@ void MainWindow::queue_clicked() void MainWindow::preview_clicked() { + if (ui->playlist->hasFocus()) { + // Allow the playlist as preview iff it has focus and something is selected. + QItemSelectionModel *selected = ui->playlist->selectionModel(); + if (selected->hasSelection()) { + QModelIndex index = selected->currentIndex(); + const Clip &clip = *playlist_clips->clip(index.row()); + preview_player->play_clip(clip, index.row(), clip.stream_idx); + return; + } + } + if (cliplist_clips->empty()) return; QItemSelectionModel *selected = ui->clip_list->selectionModel(); if (!selected->hasSelection()) { - preview_player->play_clip(*cliplist_clips->back(), 0); + preview_player->play_clip(*cliplist_clips->back(), cliplist_clips->size() - 1, 0); return; } @@ -216,7 +226,7 @@ void MainWindow::preview_clicked() } else { stream_idx = ui->preview_display->get_stream_idx(); } - preview_player->play_clip(*cliplist_clips->clip(index.row()), stream_idx); + preview_player->play_clip(*cliplist_clips->clip(index.row()), index.row(), stream_idx); } void MainWindow::preview_angle_clicked(unsigned stream_idx) @@ -328,7 +338,8 @@ void MainWindow::play_clicked() } const Clip &clip = *playlist_clips->clip(row); - live_player->play_clip(clip, clip.stream_idx); + live_player->play_clip(clip, row, clip.stream_idx); + playlist_clips->set_progress({{ row, 0.0f }}); playlist_clips->set_currently_playing(row, 0.0f); playlist_selection_changed(); } @@ -338,24 +349,26 @@ void MainWindow::live_player_clip_done() int row = playlist_clips->get_currently_playing(); if (row == -1 || row == int(playlist_clips->size()) - 1) { set_output_status("paused"); + playlist_clips->set_progress({}); playlist_clips->set_currently_playing(-1, 0.0f); } else { + playlist_clips->set_progress({{ row + 1, 0.0f }}); playlist_clips->set_currently_playing(row + 1, 0.0f); } } -Clip MainWindow::live_player_get_next_clip() +pair MainWindow::live_player_get_next_clip() { // playlist_clips can only be accessed on the main thread. // Hopefully, we won't have to wait too long for this to come back. - promise clip_promise; - future clip = clip_promise.get_future(); + promise> clip_promise; + future> clip = clip_promise.get_future(); post_to_main_thread([this, &clip_promise] { int row = playlist_clips->get_currently_playing(); if (row != -1 && row < int(playlist_clips->size()) - 1) { - clip_promise.set_value(*playlist_clips->clip(row + 1)); + clip_promise.set_value(make_pair(*playlist_clips->clip(row + 1), row + 1)); } else { - clip_promise.set_value(Clip()); + clip_promise.set_value(make_pair(Clip(), 0)); } }); return clip.get(); @@ -376,14 +389,28 @@ static string format_duration(double t) return buf; } -void MainWindow::live_player_clip_progress(double played_this_clip, double total_length) +void MainWindow::live_player_clip_progress(const map &progress) { - playlist_clips->set_currently_playing(playlist_clips->get_currently_playing(), played_this_clip / total_length); - - double remaining = total_length - played_this_clip; - for (int row = playlist_clips->get_currently_playing() + 1; row < int(playlist_clips->size()); ++row) { + playlist_clips->set_progress(progress); + + // Look at the last clip and then start counting from there. + assert(!progress.empty()); + auto last_it = progress.end(); + --last_it; + double remaining = 0.0; + double last_fade_time_seconds = 0.0; + for (size_t row = last_it->first; row < playlist_clips->size(); ++row) { const Clip clip = *playlist_clips->clip(row); - remaining += double(clip.pts_out - clip.pts_in) / TIMEBASE / 0.5; // FIXME: stop hardcoding speed. + double clip_length = double(clip.pts_out - clip.pts_in) / TIMEBASE / 0.5; // FIXME: stop hardcoding speed. + if (row == last_it->first) { + // A clip we're playing: Subtract the part we've already played. + remaining = clip_length * (1.0 - last_it->second); + } else { + // A clip we haven't played yet: Subtract the part that's overlapping + // with a previous clip (due to fade). + remaining += max(clip_length - last_fade_time_seconds, 0.0); + } + last_fade_time_seconds = min(clip_length, clip.fade_time_seconds); } set_output_status(format_duration(remaining) + " left"); } @@ -613,25 +640,27 @@ void MainWindow::preview_single_frame(int64_t pts, unsigned stream_idx, MainWind lock_guard lock(frame_mu); if (frames[stream_idx].empty()) return; - auto it = lower_bound(frames[stream_idx].begin(), frames[stream_idx].end(), pts); + auto it = lower_bound(frames[stream_idx].begin(), frames[stream_idx].end(), pts, + [](const FrameOnDisk &frame, int64_t pts) { return frame.pts < pts; }); if (it != frames[stream_idx].end()) { - pts = *it; + pts = it->pts; } } else { assert(rounding == FIRST_AT_OR_AFTER); lock_guard lock(frame_mu); if (frames[stream_idx].empty()) return; - auto it = upper_bound(frames[stream_idx].begin(), frames[stream_idx].end(), pts - 1); + auto it = upper_bound(frames[stream_idx].begin(), frames[stream_idx].end(), pts - 1, + [](int64_t pts, const FrameOnDisk &frame) { return pts < frame.pts; }); if (it != frames[stream_idx].end()) { - pts = *it; + pts = it->pts; } } Clip fake_clip; fake_clip.pts_in = pts; fake_clip.pts_out = pts + 1; - preview_player->play_clip(fake_clip, stream_idx); + preview_player->play_clip(fake_clip, 0, stream_idx); } void MainWindow::playlist_selection_changed()