X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=futatabi%2Fclip_list.cpp;h=f76906f2a2b4f539a02506f2a01324e6c17b8836;hb=refs%2Fheads%2Fmaster;hp=0321727cef00888b4ce96bc719b5ed016d6da897;hpb=85e1c098fb61869cba7edf20a6281b2f87a7b9ed;p=nageru diff --git a/futatabi/clip_list.cpp b/futatabi/clip_list.cpp index 0321727..f76906f 100644 --- a/futatabi/clip_list.cpp +++ b/futatabi/clip_list.cpp @@ -58,7 +58,7 @@ int ClipList::columnCount(const QModelIndex &parent) const { if (parent.isValid()) return 0; - return int(Column::NUM_NON_CAMERA_COLUMNS) + NUM_CAMERAS; + return int(Column::NUM_NON_CAMERA_COLUMNS) + num_cameras; } int PlayList::columnCount(const QModelIndex &parent) const @@ -131,6 +131,7 @@ QVariant PlayList::data(const QModelIndex &parent, int role) const case Column::OUT: case Column::DURATION: case Column::FADE_TIME: + case Column::SPEED: return Qt::AlignRight + Qt::AlignVCenter; case Column::CAMERA: return Qt::AlignCenter; @@ -140,7 +141,7 @@ QVariant PlayList::data(const QModelIndex &parent, int role) const } if (role == Qt::BackgroundRole) { if (Column(column) == Column::PLAYING) { - auto it = current_progress.find(row); + auto it = current_progress.find(clips[row].id); if (it != current_progress.end()) { double play_progress = it->second; @@ -166,30 +167,37 @@ QVariant PlayList::data(const QModelIndex &parent, int role) const switch (Column(column)) { case Column::PLAYING: - return current_progress.count(row) ? "→" : ""; + return current_progress.count(clips[row].id) ? "→" : ""; case Column::IN: - return QString::fromStdString(pts_to_string(clips[row].pts_in)); + return QString::fromStdString(pts_to_string(clips[row].clip.pts_in)); case Column::OUT: - if (clips[row].pts_out >= 0) { - return QString::fromStdString(pts_to_string(clips[row].pts_out)); + if (clips[row].clip.pts_out >= 0) { + return QString::fromStdString(pts_to_string(clips[row].clip.pts_out)); } else { return QVariant(); } case Column::DURATION: - if (clips[row].pts_out >= 0) { - return QString::fromStdString(duration_to_string(clips[row].pts_out - clips[row].pts_in)); + if (clips[row].clip.pts_out >= 0) { + return QString::fromStdString(duration_to_string(clips[row].clip.pts_out - clips[row].clip.pts_in)); } else { return QVariant(); } case Column::CAMERA: - return qlonglong(clips[row].stream_idx + 1); + return qlonglong(clips[row].clip.stream_idx + 1); case Column::DESCRIPTION: - return QString::fromStdString(clips[row].descriptions[clips[row].stream_idx]); + return QString::fromStdString(clips[row].clip.descriptions[clips[row].clip.stream_idx]); case Column::FADE_TIME: { stringstream ss; ss.imbue(locale("C")); ss.precision(3); - ss << fixed << clips[row].fade_time_seconds; + ss << fixed << clips[row].clip.fade_time_seconds; + return QString::fromStdString(ss.str()); + } + case Column::SPEED: { + stringstream ss; + ss.imbue(locale("C")); + ss.precision(3); + ss << fixed << clips[row].clip.speed; return QString::fromStdString(ss.str()); } default: @@ -212,7 +220,7 @@ QVariant ClipList::headerData(int section, Qt::Orientation orientation, int role case Column::DURATION: return "Duration"; default: - if (section >= int(Column::CAMERA_1) && section < int(Column::CAMERA_1) + NUM_CAMERAS) { + if (is_camera_column(section)) { return QString::fromStdString("Camera " + to_string(section - int(Column::CAMERA_1) + 1)); } else { return ""; @@ -242,6 +250,8 @@ QVariant PlayList::headerData(int section, Qt::Orientation orientation, int role return "Description"; case Column::FADE_TIME: return "Fade time"; + case Column::SPEED: + return "Speed"; default: return ""; } @@ -274,7 +284,7 @@ Qt::ItemFlags PlayList::flags(const QModelIndex &index) const case Column::DESCRIPTION: case Column::CAMERA: case Column::FADE_TIME: - return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable; + case Column::SPEED: return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable; default: return Qt::ItemIsEnabled | Qt::ItemIsSelectable; @@ -313,16 +323,16 @@ bool PlayList::setData(const QModelIndex &index, const QVariant &value, int role switch (Column(column)) { case Column::DESCRIPTION: - clips[row].descriptions[clips[row].stream_idx] = value.toString().toStdString(); + clips[row].clip.descriptions[clips[row].clip.stream_idx] = value.toString().toStdString(); emit_data_changed(row); return true; case Column::CAMERA: { bool ok; int camera_idx = value.toInt(&ok); - if (!ok || camera_idx < 1 || camera_idx > NUM_CAMERAS) { + if (!ok || camera_idx < 1 || camera_idx > int(num_cameras)) { return false; } - clips[row].stream_idx = camera_idx - 1; + clips[row].clip.stream_idx = camera_idx - 1; emit_data_changed(row); return true; } @@ -332,7 +342,17 @@ bool PlayList::setData(const QModelIndex &index, const QVariant &value, int role if (!ok || !(val >= 0.0)) { return false; } - clips[row].fade_time_seconds = val; + clips[row].clip.fade_time_seconds = val; + emit_data_changed(row); + return true; + } + case Column::SPEED: { + bool ok; + double val = value.toDouble(&ok); + if (!ok || !(val >= 0.001)) { + return false; + } + clips[row].clip.speed = val; emit_data_changed(row); return true; } @@ -352,15 +372,20 @@ void ClipList::add_clip(const Clip &clip) void PlayList::add_clip(const Clip &clip) { beginInsertRows(QModelIndex(), clips.size(), clips.size()); - clips.push_back(clip); + clips.emplace_back(ClipWithID{ clip, clip_counter++ }); endInsertRows(); emit any_content_changed(); } void PlayList::duplicate_clips(size_t first, size_t last) { - beginInsertRows(QModelIndex(), first, last); - clips.insert(clips.begin() + first, clips.begin() + first, clips.begin() + last + 1); + beginInsertRows(QModelIndex(), last + 1, last + 1 + (last - first)); + + vector new_clips; + for (auto it = clips.begin() + first; it <= clips.begin() + last; ++it) { + new_clips.emplace_back(ClipWithID{ it->clip, clip_counter++ }); // Give them new IDs. + } + clips.insert(clips.begin() + last + 1, new_clips.begin(), new_clips.end()); // Note: The new elements are inserted after the old ones. endInsertRows(); emit any_content_changed(); } @@ -390,7 +415,7 @@ void PlayList::move_clips(size_t first, size_t last, int delta) void ClipList::emit_data_changed(size_t row) { - emit dataChanged(index(row, 0), index(row, int(Column::NUM_NON_CAMERA_COLUMNS) + NUM_CAMERAS)); + emit dataChanged(index(row, 0), index(row, int(Column::NUM_NON_CAMERA_COLUMNS) + num_cameras)); emit any_content_changed(); } @@ -400,41 +425,31 @@ void PlayList::emit_data_changed(size_t row) emit any_content_changed(); } -void PlayList::set_currently_playing(int index, double progress) +void ClipList::change_num_cameras(size_t num_cameras) { - int old_index = currently_playing_index; - int column = int(Column::PLAYING); - if (index != old_index) { - currently_playing_index = index; - play_progress = progress; - if (old_index != -1) { - emit dataChanged(this->index(old_index, column), this->index(old_index, column)); - } - if (index != -1) { - emit dataChanged(this->index(index, column), this->index(index, column)); - } - } else if (index != -1 && fabs(progress - play_progress) > 1e-3) { - play_progress = progress; - emit dataChanged(this->index(index, column), this->index(index, column)); + assert(num_cameras >= this->num_cameras); + if (num_cameras == this->num_cameras) { + return; } + + beginInsertColumns(QModelIndex(), int(Column::NUM_NON_CAMERA_COLUMNS) + this->num_cameras, int(Column::NUM_NON_CAMERA_COLUMNS) + num_cameras - 1); + this->num_cameras = num_cameras; + endInsertColumns(); + emit any_content_changed(); } -void PlayList::set_progress(const map &progress) +void PlayList::set_progress(const map &progress) { const int column = int(Column::PLAYING); - map old_progress = move(this->current_progress); + map old_progress = move(this->current_progress); this->current_progress = progress; - for (auto it : old_progress) { - size_t index = it.first; - if (current_progress.count(index) == 0) { - emit dataChanged(this->index(index, column), this->index(index, column)); + for (size_t row = 0; row < clips.size(); ++row) { + uint64_t id = clips[row].id; + if (current_progress.count(id) || old_progress.count(id)) { + emit dataChanged(this->index(row, column), this->index(row, column)); } } - for (auto it : current_progress) { - size_t index = it.first; - emit dataChanged(this->index(index, column), this->index(index, column)); - } } namespace { @@ -444,11 +459,16 @@ Clip deserialize_clip(const ClipProto &clip_proto) Clip clip; clip.pts_in = clip_proto.pts_in(); clip.pts_out = clip_proto.pts_out(); - for (int camera_idx = 0; camera_idx < min(clip_proto.description_size(), NUM_CAMERAS); ++camera_idx) { + for (int camera_idx = 0; camera_idx < min(clip_proto.description_size(), MAX_STREAMS); ++camera_idx) { clip.descriptions[camera_idx] = clip_proto.description(camera_idx); } clip.stream_idx = clip_proto.stream_idx(); clip.fade_time_seconds = clip_proto.fade_time_seconds(); + if (clip_proto.speed() < 0.001) { + clip.speed = 0.5; // Default. + } else { + clip.speed = clip_proto.speed(); + } return clip; } @@ -456,11 +476,12 @@ void serialize_clip(const Clip &clip, ClipProto *clip_proto) { clip_proto->set_pts_in(clip.pts_in); clip_proto->set_pts_out(clip.pts_out); - for (int camera_idx = 0; camera_idx < NUM_CAMERAS; ++camera_idx) { + for (int camera_idx = 0; camera_idx < MAX_STREAMS; ++camera_idx) { *clip_proto->add_description() = clip.descriptions[camera_idx]; } clip_proto->set_stream_idx(clip.stream_idx); clip_proto->set_fade_time_seconds(clip.fade_time_seconds); + clip_proto->set_speed(clip.speed); } } // namespace @@ -484,15 +505,15 @@ ClipListProto ClipList::serialize() const PlayList::PlayList(const ClipListProto &serialized) { for (const ClipProto &clip_proto : serialized.clip()) { - clips.push_back(deserialize_clip(clip_proto)); + clips.emplace_back(ClipWithID{ deserialize_clip(clip_proto), clip_counter++ }); } } ClipListProto PlayList::serialize() const { ClipListProto ret; - for (const Clip &clip : clips) { - serialize_clip(clip, ret.add_clip()); + for (const ClipWithID &clip : clips) { + serialize_clip(clip.clip, ret.add_clip()); } return ret; }