progress.setMaximum(100000);
progress.setValue(0);
- double total_length = compute_time_left(clips, { { 0, 0.0 } });
vector<Player::ClipWithRow> clips_with_row;
for (const Clip &clip : clips) {
clips_with_row.emplace_back(Player::ClipWithRow{ clip, 0 });
}
+ double total_length = compute_total_time(clips_with_row);
promise<void> done_promise;
future<void> done = done_promise.get_future();
done_promise.set_value();
}
});
- player.set_progress_callback([¤t_value, &clips, total_length](const std::map<size_t, double> &player_progress) {
- current_value = 1.0 - compute_time_left(clips, player_progress) / total_length;
+ player.set_progress_callback([¤t_value, &clips, total_length](const std::map<size_t, double> &player_progress, double time_remaining) {
+ current_value = 1.0 - time_remaining / total_length;
});
player.play(clips_with_row);
while (done.wait_for(std::chrono::milliseconds(100)) != future_status::ready && !progress.wasCanceled()) {
live_player_clip_done();
});
});
- live_player->set_progress_callback([this](const map<size_t, double> &progress) {
- post_to_main_thread([this, progress] {
- live_player_clip_progress(progress);
+ live_player->set_progress_callback([this](const map<size_t, double> &progress, double time_remaining) {
+ post_to_main_thread([this, progress, time_remaining] {
+ live_player_clip_progress(progress, time_remaining);
});
});
set_output_status("paused");
return buf;
}
-void MainWindow::live_player_clip_progress(const map<size_t, double> &progress)
+void MainWindow::live_player_clip_progress(const map<size_t, double> &progress, double time_remaining)
{
playlist_clips->set_progress(progress);
-
- vector<Clip> clips;
- for (size_t row = 0; row < playlist_clips->size(); ++row) {
- clips.push_back(*playlist_clips->clip(row));
- }
- double remaining = compute_time_left(clips, progress);
- set_output_status(format_duration(remaining) + " left");
+ set_output_status(format_duration(time_remaining) + " left");
}
void MainWindow::resizeEvent(QResizeEvent *event)
if (!any_selected) {
set_output_status("paused");
} else {
- vector<Clip> clips;
- for (size_t row = 0; row < playlist_clips->size(); ++row) {
- clips.push_back(*playlist_clips->clip(row));
+ vector<Player::ClipWithRow> clips;
+ for (size_t row = selected->selectedRows().front().row(); row < playlist_clips->size(); ++row) {
+ clips.emplace_back(Player::ClipWithRow{ *playlist_clips->clip(row), row });
}
- double remaining = compute_time_left(clips, { { selected->selectedRows().front().row(), 0.0 } });
+ double remaining = compute_total_time(clips);
set_output_status(format_duration(remaining) + " ready");
}
}
void stop_clicked();
void live_player_clip_done();
std::pair<Clip, size_t> live_player_get_next_clip();
- void live_player_clip_progress(const std::map<size_t, double> &progress);
+ void live_player_clip_progress(const std::map<size_t, double> &progress, double time_remaining);
void set_output_status(const std::string &status);
void playlist_duplicate();
void playlist_remove();
if (progress_callback != nullptr) {
// NOTE: None of this will take into account any snapping done below.
- map<size_t, double> progress{ { clip_list[clip_idx].row, calc_progress(clip, in_pts_for_progress) } };
+ double clip_progress = calc_progress(clip, in_pts_for_progress);
+ map<size_t, double> progress{ { clip_list[clip_idx].row, clip_progress } };
+ double time_remaining;
if (next_clip != nullptr && time_left_this_clip <= next_clip_fade_time) {
- progress[clip_list[clip_idx + 1].row] = calc_progress(*next_clip, in_pts_secondary_for_progress);
+ double next_clip_progress = calc_progress(*next_clip, in_pts_secondary_for_progress);
+ progress[clip_list[clip_idx + 1].row] = next_clip_progress;
+ time_remaining = compute_time_left(clip_list, clip_idx + 1, next_clip_progress);
+ } else {
+ time_remaining = compute_time_left(clip_list, clip_idx, clip_progress);
}
- progress_callback(progress);
+ progress_callback(progress, time_remaining);
}
FrameOnDisk frame_lower, frame_upper;
new_clip_changed.notify_all();
}
-double compute_time_left(const vector<Clip> &clips, const map<size_t, double> &progress)
+double compute_time_left(const vector<Player::ClipWithRow> &clips, size_t currently_playing_idx, double progress_currently_playing)
{
// 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 < clips.size(); ++row) {
- const Clip &clip = clips[row];
+ for (size_t row = currently_playing_idx; row < clips.size(); ++row) {
+ const Clip &clip = clips[row].clip;
double clip_length = double(clip.pts_out - clip.pts_in) / TIMEBASE / clip.speed;
- if (row == last_it->first) {
+ if (row == currently_playing_idx) {
// A clip we're playing: Subtract the part we've already played.
- remaining = clip_length * (1.0 - last_it->second);
+ remaining = clip_length * (1.0 - progress_currently_playing);
} else {
// A clip we haven't played yet: Subtract the part that's overlapping
// with a previous clip (due to fade).
class QSurface;
class QSurfaceFormat;
-double compute_time_left(const std::vector<Clip> &clips, const std::map<size_t, double> &progress);
-
class Player : public QueueInterface {
public:
enum StreamOutput {
struct ClipWithRow {
Clip clip;
- unsigned row; // Used for progress callback only.
+ size_t row; // Used for progress callback only.
};
void play(const Clip &clip)
{
// Not thread-safe to set concurrently with playing.
// Will be called back from the player thread.
// The keys in the given map are row members in the vector given to play().
- using progress_callback_func = std::function<void(const std::map<size_t, double> &progress)>;
+ using progress_callback_func = std::function<void(const std::map<size_t, double> &progress, double time_remaining)>;
void set_progress_callback(progress_callback_func cb) { progress_callback = cb; }
// QueueInterface.
const StreamOutput stream_output;
};
+double compute_time_left(const std::vector<Player::ClipWithRow> &clips, size_t currently_playing_idx, double progress_currently_playing);
+
+static inline double compute_total_time(const std::vector<Player::ClipWithRow> &clips)
+{
+ return compute_time_left(clips, 0, 0.0);
+}
+
#endif // !defined(_PLAYER_H)