merged with master

This commit is contained in:
itsmattkc
2019-03-25 12:43:23 +11:00
83 changed files with 7823 additions and 1469 deletions
+1
View File
@@ -86,6 +86,7 @@ void alloc_panels(QWidget* parent) {
panel_sequence_viewer->setObjectName("seq_viewer");
panel_footage_viewer = new Viewer(parent);
panel_footage_viewer->setObjectName("footage_viewer");
panel_footage_viewer->show_videoaudio_buttons(true);
panel_project = new Project(parent);
panel_project->setObjectName("proj_root");
panel_effect_controls = new EffectControls(parent);
+87 -48
View File
@@ -65,20 +65,15 @@ extern "C" {
#include "global/debug.h"
#include "ui/menu.h"
// TODO make these configurable
const int kDefaultSequenceWidth = 1920;
const int kDefaultSequenceHeight = 1080;
const double kDefaultSequenceFrameRate = 29.97;
const int kDefaultSequenceFrequency = 48000;
const int kDefaultSequenceChannelLayout = 3;
#define MAXIMUM_RECENT_PROJECTS 10 // FIXME: should be configurable
QString autorecovery_filename;
QStringList recent_projects;
Project::Project(QWidget *parent) :
Panel(parent)
Panel(parent),
sorter(this),
sources_common(this, sorter)
{
QWidget* dockWidgetContents = new QWidget(this);
@@ -88,10 +83,7 @@ Project::Project(QWidget *parent) :
setWidget(dockWidgetContents);
sources_common = new SourcesCommon(this);
sorter = new ProjectFilter(this);
sorter->setSourceModel(&olive::project_model);
ConnectFilterToModel();
// optional toolbar
toolbar_widget = new QWidget();
@@ -104,57 +96,63 @@ Project::Project(QWidget *parent) :
QPushButton* toolbar_new = new QPushButton();
toolbar_new->setIcon(olive::icon::CreateIconFromSVG(QStringLiteral(":/icons/add-button.svg")));
toolbar_new->setToolTip("New");
toolbar_new->setToolTip(tr("New"));
connect(toolbar_new, SIGNAL(clicked(bool)), this, SLOT(make_new_menu()));
toolbar->addWidget(toolbar_new);
QPushButton* toolbar_open = new QPushButton();
toolbar_open->setIcon(olive::icon::CreateIconFromSVG(QStringLiteral(":/icons/open.svg")));
toolbar_open->setToolTip("Open Project");
toolbar_open->setToolTip(tr("Open Project"));
connect(toolbar_open, SIGNAL(clicked(bool)), olive::Global.get(), SLOT(OpenProject()));
toolbar->addWidget(toolbar_open);
QPushButton* toolbar_save = new QPushButton();
toolbar_save->setIcon(olive::icon::CreateIconFromSVG(QStringLiteral(":/icons/save.svg")));
toolbar_save->setToolTip("Save Project");
toolbar_save->setToolTip(tr("Save Project"));
connect(toolbar_save, SIGNAL(clicked(bool)), olive::Global.get(), SLOT(save_project()));
toolbar->addWidget(toolbar_save);
QPushButton* toolbar_undo = new QPushButton();
toolbar_undo->setIcon(olive::icon::CreateIconFromSVG(QStringLiteral(":/icons/undo.svg")));
toolbar_undo->setToolTip("Undo");
toolbar_undo->setToolTip(tr("Undo"));
connect(toolbar_undo, SIGNAL(clicked(bool)), olive::Global.get(), SLOT(undo()));
toolbar->addWidget(toolbar_undo);
QPushButton* toolbar_redo = new QPushButton();
toolbar_redo->setIcon(olive::icon::CreateIconFromSVG(QStringLiteral(":/icons/redo.svg")));
toolbar_redo->setToolTip("Redo");
toolbar_redo->setToolTip(tr("Redo"));
connect(toolbar_redo, SIGNAL(clicked(bool)), olive::Global.get(), SLOT(redo()));
toolbar->addWidget(toolbar_redo);
toolbar_search = new QLineEdit();
toolbar_search->setClearButtonEnabled(true);
connect(toolbar_search, SIGNAL(textChanged(QString)), sorter, SLOT(update_search_filter(const QString&)));
connect(toolbar_search, SIGNAL(textChanged(QString)), &sorter, SLOT(update_search_filter(const QString&)));
toolbar->addWidget(toolbar_search);
QPushButton* toolbar_tree_view = new QPushButton();
toolbar_tree_view->setIcon(olive::icon::CreateIconFromSVG(QStringLiteral(":/icons/treeview.svg")));
toolbar_tree_view->setToolTip("Tree View");
toolbar_tree_view->setToolTip(tr("Tree View"));
connect(toolbar_tree_view, SIGNAL(clicked(bool)), this, SLOT(set_tree_view()));
toolbar->addWidget(toolbar_tree_view);
QPushButton* toolbar_icon_view = new QPushButton();
toolbar_icon_view->setIcon(olive::icon::CreateIconFromSVG(QStringLiteral(":/icons/iconview.svg")));
toolbar_icon_view->setToolTip("Icon View");
toolbar_icon_view->setToolTip(tr("Icon View"));
connect(toolbar_icon_view, SIGNAL(clicked(bool)), this, SLOT(set_icon_view()));
toolbar->addWidget(toolbar_icon_view);
QPushButton* toolbar_list_view = new QPushButton();
toolbar_list_view->setIcon(olive::icon::CreateIconFromSVG(QStringLiteral(":/icons/listview.svg")));
toolbar_list_view->setToolTip(tr("List View"));
connect(toolbar_list_view, SIGNAL(clicked(bool)), this, SLOT(set_list_view()));
toolbar->addWidget(toolbar_list_view);
verticalLayout->addWidget(toolbar_widget);
// tree view
tree_view = new SourceTable();
tree_view = new SourceTable(sources_common);
tree_view->project_parent = this;
tree_view->setModel(sorter);
tree_view->setModel(&sorter);
verticalLayout->addWidget(tree_view);
// Set the first column width
@@ -181,23 +179,23 @@ Project::Project(QWidget *parent) :
icon_view_controls->addStretch();
QSlider* icon_size_slider = new QSlider(Qt::Horizontal);
icon_size_slider = new QSlider(Qt::Horizontal);
icon_size_slider->setMinimum(16);
icon_size_slider->setMaximum(120);
icon_size_slider->setMaximum(256);
icon_view_controls->addWidget(icon_size_slider);
connect(icon_size_slider, SIGNAL(valueChanged(int)), this, SLOT(set_icon_view_size(int)));
icon_view_container_layout->addLayout(icon_view_controls);
icon_view = new SourceIconView();
icon_view = new SourceIconView(sources_common);
icon_view->project_parent = this;
icon_view->setModel(sorter);
icon_view->setIconSize(QSize(100, 100));
icon_view->setModel(&sorter);
icon_view->setGridSize(QSize(100, 100));
icon_view->setViewMode(QListView::IconMode);
icon_view->setUniformItemSizes(true);
icon_view_container_layout->addWidget(icon_view);
icon_size_slider->setValue(icon_view->iconSize().height());
icon_size_slider->setValue(icon_view->gridSize().height());
verticalLayout->addWidget(icon_view_container);
@@ -212,8 +210,14 @@ Project::Project(QWidget *parent) :
Retranslate();
}
Project::~Project() {
delete sorter;
void Project::ConnectFilterToModel()
{
sorter.setSourceModel(&olive::project_model);
}
void Project::DisconnectFilterToModel()
{
sorter.setSourceModel(nullptr);
}
void Project::Retranslate() {
@@ -245,22 +249,22 @@ QString Project::get_next_sequence_name(QString start) {
return name;
}
SequencePtr create_sequence_from_media(QVector<Media*>& media_list) {
SequencePtr create_sequence_from_media(QVector<olive::timeline::MediaImportData>& media_list) {
SequencePtr s(new Sequence());
s->name = panel_project->get_next_sequence_name();
// shitty hardcoded default values
s->width = kDefaultSequenceWidth;
s->height = kDefaultSequenceHeight;
s->frame_rate = kDefaultSequenceFrameRate;
s->audio_frequency = kDefaultSequenceFrequency;
s->audio_layout = kDefaultSequenceChannelLayout;
// Retrieve default Sequence settings from Config
s->width = olive::CurrentConfig.default_sequence_width;
s->height = olive::CurrentConfig.default_sequence_height;
s->frame_rate = olive::CurrentConfig.default_sequence_framerate;
s->audio_frequency = olive::CurrentConfig.default_sequence_audio_frequency;
s->audio_layout = olive::CurrentConfig.default_sequence_audio_channel_layout;
bool got_video_values = false;
bool got_audio_values = false;
for (int i=0;i<media_list.size();i++) {
Media* media = media_list.at(i);
Media* media = media_list.at(i).media();
switch (media->get_type()) {
case MEDIA_TYPE_FOOTAGE:
{
@@ -418,10 +422,10 @@ void Project::new_folder() {
QModelIndex index = olive::project_model.create_index(m->row(), 0, m.get());
switch (olive::CurrentConfig.project_view_type) {
case olive::PROJECT_VIEW_TREE:
tree_view->edit(sorter->mapFromSource(index));
tree_view->edit(sorter.mapFromSource(index));
break;
case olive::PROJECT_VIEW_ICON:
icon_view->edit(sorter->mapFromSource(index));
icon_view->edit(sorter.mapFromSource(index));
break;
}
}
@@ -475,7 +479,7 @@ MediaPtr Project::create_folder_internal(QString name) {
}
Media* Project::item_to_media(const QModelIndex &index) {
return static_cast<Media*>(sorter->mapToSource(index).internalPointer());
return static_cast<Media*>(sorter.mapToSource(index).internalPointer());
}
MediaPtr Project::item_to_media_ptr(const QModelIndex &index) {
@@ -503,6 +507,21 @@ void Project::get_all_media_from_table(QList<Media*>& items, QList<Media*>& list
}
}
bool Project::IsToolbarVisible()
{
return toolbar_widget->isVisible();
}
void Project::SetToolbarVisible(bool visible)
{
toolbar_widget->setVisible(visible);
}
bool Project::IsProjectWidget(QObject *child)
{
return (child == tree_view || child == icon_view);
}
bool delete_clips_in_clipboard_with_media(ComboAction* ca, Media* m) {
int delete_count = 0;
if (clipboard_type == CLIPBOARD_TYPE_CLIP) {
@@ -944,7 +963,7 @@ bool Project::reveal_media(Media *media, QModelIndex parent) {
// if m == media, then we found the media object we were looking for
// get sorter proxy item (the item that's "visible")
QModelIndex sorted_index = sorter->mapFromSource(item);
QModelIndex sorted_index = sorter.mapFromSource(item);
// retrieve its parent item
QModelIndex hierarchy = sorted_index.parent();
@@ -959,8 +978,8 @@ bool Project::reveal_media(Media *media, QModelIndex parent) {
// select item (requires a QItemSelection object to select the whole row)
QItemSelection row_select(
sorter->index(sorted_index.row(), 0, sorted_index.parent()),
sorter->index(sorted_index.row(), sorter->columnCount()-1, sorted_index.parent())
sorter.index(sorted_index.row(), 0, sorted_index.parent()),
sorter.index(sorted_index.row(), sorter.columnCount()-1, sorted_index.parent())
);
tree_view->selectionModel()->select(row_select, QItemSelectionModel::Select);
@@ -1307,14 +1326,23 @@ void Project::save_project(bool autorecovery) {
void Project::update_view_type() {
tree_view->setVisible(olive::CurrentConfig.project_view_type == olive::PROJECT_VIEW_TREE);
icon_view_container->setVisible(olive::CurrentConfig.project_view_type == olive::PROJECT_VIEW_ICON);
icon_view_container->setVisible(olive::CurrentConfig.project_view_type == olive::PROJECT_VIEW_ICON
|| olive::CurrentConfig.project_view_type == olive::PROJECT_VIEW_LIST);
switch (olive::CurrentConfig.project_view_type) {
case olive::PROJECT_VIEW_TREE:
sources_common->view = tree_view;
sources_common.view = tree_view;
break;
case olive::PROJECT_VIEW_ICON:
sources_common->view = icon_view;
case olive::PROJECT_VIEW_LIST:
icon_view->setViewMode(olive::CurrentConfig.project_view_type == olive::PROJECT_VIEW_ICON ?
QListView::IconMode : QListView::ListMode);
// update list/grid size since they use this value slightly differently
set_icon_view_size(icon_size_slider->value());
sources_common.view = icon_view;
break;
}
}
@@ -1324,6 +1352,12 @@ void Project::set_icon_view() {
update_view_type();
}
void Project::set_list_view()
{
olive::CurrentConfig.project_view_type = olive::PROJECT_VIEW_LIST;
update_view_type();
}
void Project::set_tree_view() {
olive::CurrentConfig.project_view_type = olive::PROJECT_VIEW_TREE;
update_view_type();
@@ -1352,7 +1386,12 @@ void Project::clear_recent_projects() {
}
void Project::set_icon_view_size(int s) {
icon_view->setIconSize(QSize(s, s));
if (icon_view->viewMode() == QListView::IconMode) {
icon_view->setGridSize(QSize(s, s));
} else {
icon_view->setGridSize(QSize());
icon_view->setIconSize(QSize(s, s));
}
}
void Project::set_up_dir_enabled() {
+18 -9
View File
@@ -35,6 +35,7 @@
#include "project/sourcescommon.h"
#include "ui/panel.h"
#include "ui/sourceiconview.h"
#include "timeline/mediaimportdata.h"
#include "undo/undo.h"
#include "ui/sourcetable.h"
@@ -45,7 +46,7 @@
extern QString autorecovery_filename;
extern QStringList recent_projects;
SequencePtr create_sequence_from_media(QVector<Media *> &media_list);
SequencePtr create_sequence_from_media(QVector<olive::timeline::MediaImportData> &media_list);
QString get_channel_layout_name(int channels, uint64_t layout);
QString get_interlacing_name(int interlacing);
@@ -54,7 +55,9 @@ class Project : public Panel {
Q_OBJECT
public:
explicit Project(QWidget *parent = nullptr);
~Project();
void ConnectFilterToModel();
void DisconnectFilterToModel();
bool is_focused();
void clear();
@@ -77,19 +80,14 @@ public:
QVector<Media*> list_all_project_sequences();
SourceTable* tree_view;
SourceIconView* icon_view;
SourcesCommon* sources_common;
ProjectFilter* sorter;
QVector<Media*> last_imported_media;
QModelIndexList get_current_selected();
void get_all_media_from_table(QList<Media *> &items, QList<Media *> &list, int type = -1);
QWidget* toolbar_widget;
bool IsToolbarVisible();
bool IsProjectWidget(QObject *child);
virtual void Retranslate() override;
protected:
@@ -103,6 +101,8 @@ public slots:
void open_properties();
void new_folder();
void new_sequence();
void SetToolbarVisible(bool visible);
private:
void save_folder(QXmlStreamWriter& stream, int type, bool set_ids_only, const QModelIndex &parent = QModelIndex());
int folder_id;
@@ -112,11 +112,20 @@ private:
QString get_file_name_from_path(const QString &path);
QDir proj_dir;
QWidget* icon_view_container;
QSlider* icon_size_slider;
QPushButton* directory_up;
QLineEdit* toolbar_search;
QWidget* toolbar_widget;
SourceTable* tree_view;
SourceIconView* icon_view;
ProjectFilter sorter;
SourcesCommon sources_common;
private slots:
void update_view_type();
void set_icon_view();
void set_list_view();
void set_tree_view();
void clear_recent_projects();
void set_icon_view_size(int);
+110 -20
View File
@@ -138,6 +138,53 @@ void Timeline::Retranslate() {
UpdateTitle();
}
void Timeline::split_clip_at_positions(ComboAction* ca, int clip_index, QVector<long> positions) {
QVector<int> pre_splits;
// Add the clip and each of its links to the pre_splits array
Clip* clip = olive::ActiveSequence->clips.at(clip_index).get();
pre_splits.append(clip_index);
for (int i=0;i<clip->linked.size();i++) {
pre_splits.append(clip->linked.at(i));
}
std::sort(positions.begin(), positions.end());
// Remove any duplicate positions
for (int i=1;i<positions.size();i++) {
if (positions.at(i-1) == positions.at(i)) {
positions.removeAt(i);
i--;
}
}
for (int i=1;i<positions.size();i++) {
Q_ASSERT(positions.at(i-1) < positions.at(i));
}
QVector< QVector<ClipPtr> > post_splits(positions.size());
for (int i=positions.size()-1;i>=0;i--) {
post_splits[i].resize(pre_splits.size());
for (int j=0;j<pre_splits.size();j++) {
post_splits[i][j] = split_clip(ca, true, pre_splits.at(j), positions.at(i));
if (post_splits[i][j] != nullptr && i + 1 < positions.size()) {
post_splits[i][j]->set_timeline_out(positions.at(i+1));
}
}
}
for (int i=0;i<post_splits.size();i++) {
relink_clips_using_ids(pre_splits, post_splits[i]);
ca->append(new AddClipCommand(olive::ActiveSequence.get(), post_splits[i]));
}
}
void Timeline::previous_cut() {
if (olive::ActiveSequence != nullptr
&& olive::ActiveSequence->playhead > 0) {
@@ -192,14 +239,15 @@ void Timeline::toggle_show_all() {
}
}
void Timeline::create_ghosts_from_media(Sequence* seq, long entry_point, QVector<Media*>& media_list) {
void Timeline::create_ghosts_from_media(Sequence* seq, long entry_point, QVector<olive::timeline::MediaImportData>& media_list) {
video_ghosts = false;
audio_ghosts = false;
for (int i=0;i<media_list.size();i++) {
bool can_import = true;
Media* medium = media_list.at(i);
const olive::timeline::MediaImportData import_data = media_list.at(i);
Media* medium = import_data.media();
Footage* m = nullptr;
Sequence* s = nullptr;
long sequence_length = 0;
@@ -212,7 +260,9 @@ void Timeline::create_ghosts_from_media(Sequence* seq, long entry_point, QVector
can_import = m->ready;
if (m->using_inout) {
double source_fr = 30;
if (m->video_tracks.size() > 0 && !qIsNull(m->video_tracks.at(0).video_frame_rate)) source_fr = m->video_tracks.at(0).video_frame_rate * m->speed;
if (m->video_tracks.size() > 0 && !qIsNull(m->video_tracks.at(0).video_frame_rate)) {
source_fr = m->video_tracks.at(0).video_frame_rate * m->speed;
}
default_clip_in = rescale_frame_number(m->in, source_fr, seq->frame_rate);
default_clip_out = rescale_frame_number(m->out, source_fr, seq->frame_rate);
}
@@ -253,20 +303,27 @@ void Timeline::create_ghosts_from_media(Sequence* seq, long entry_point, QVector
}
}
for (int j=0;j<m->audio_tracks.size();j++) {
if (m->audio_tracks.at(j).enabled) {
g.track = j;
g.media_stream = m->audio_tracks.at(j).file_index;
ghosts.append(g);
audio_ghosts = true;
if (import_data.type() == olive::timeline::kImportAudioOnly
|| import_data.type() == olive::timeline::kImportBoth) {
for (int j=0;j<m->audio_tracks.size();j++) {
if (m->audio_tracks.at(j).enabled) {
g.track = j;
g.media_stream = m->audio_tracks.at(j).file_index;
ghosts.append(g);
audio_ghosts = true;
}
}
}
for (int j=0;j<m->video_tracks.size();j++) {
if (m->video_tracks.at(j).enabled) {
g.track = -1-j;
g.media_stream = m->video_tracks.at(j).file_index;
ghosts.append(g);
video_ghosts = true;
if (import_data.type() == olive::timeline::kImportVideoOnly
|| import_data.type() == olive::timeline::kImportBoth) {
for (int j=0;j<m->video_tracks.size();j++) {
if (m->video_tracks.at(j).enabled) {
g.track = -1-j;
g.media_stream = m->video_tracks.at(j).file_index;
ghosts.append(g);
video_ghosts = true;
}
}
}
break;
@@ -277,10 +334,17 @@ void Timeline::create_ghosts_from_media(Sequence* seq, long entry_point, QVector
g.out -= (sequence_length - default_clip_out);
}
g.track = -1;
ghosts.append(g);
g.track = 0;
ghosts.append(g);
if (import_data.type() == olive::timeline::kImportVideoOnly
|| import_data.type() == olive::timeline::kImportBoth) {
g.track = -1;
ghosts.append(g);
}
if (import_data.type() == olive::timeline::kImportAudioOnly
|| import_data.type() == olive::timeline::kImportBoth) {
g.track = 0;
ghosts.append(g);
}
video_ghosts = true;
audio_ghosts = true;
@@ -446,9 +510,35 @@ void Timeline::nest() {
MediaPtr m = panel_project->create_sequence_internal(ca, s, false, nullptr);
// add nested sequence to active sequence
QVector<Media*> media_list;
QVector<olive::timeline::MediaImportData> media_list;
media_list.append(m.get());
create_ghosts_from_media(olive::ActiveSequence.get(), earliest_point, media_list);
// ensure ghosts won't overlap anything
for (int j=0;j<olive::ActiveSequence->clips.size();j++) {
Clip* c = olive::ActiveSequence->clips.at(j).get();
if (c != nullptr && !selected_clips.contains(j)) {
for (int i=0;i<ghosts.size();i++) {
Ghost& g = ghosts[i];
if (c->track() == g.track
&& !((c->timeline_in() < g.in
&& c->timeline_out() < g.in)
|| (c->timeline_in() > g.out
&& c->timeline_out() > g.out))) {
// There's a clip occupied by the space taken up by this ghost. Move up/down a track, and seek again
if (g.track < 0) {
g.track--;
} else {
g.track++;
}
j = -1;
break;
}
}
}
}
add_clips_from_ghosts(ca, olive::ActiveSequence.get());
panel_graph_editor->set_row(nullptr);
+3 -1
View File
@@ -29,6 +29,7 @@
#include "ui/timelinetools.h"
#include "timeline/selection.h"
#include "timeline/clip.h"
#include "timeline/mediaimportdata.h"
#include "undo/undo.h"
#include "ui/timelineheader.h"
#include "ui/resizablescrollbar.h"
@@ -116,6 +117,7 @@ public:
bool split_selection(ComboAction* ca);
bool split_all_clips_at_point(ComboAction *ca, long point);
bool split_clip_and_relink(ComboAction* ca, int clip, long frame, bool relink);
void split_clip_at_positions(ComboAction* ca, int clip_index, QVector<long> positions);
void clean_up_selections(QVector<Selection>& areas);
void deselect_area(long in, long out, int track);
void delete_areas_and_relink(ComboAction *ca, QVector<Selection>& areas, bool deselect_areas);
@@ -125,7 +127,7 @@ public:
void edit_to_point_internal(bool in, bool ripple);
void delete_in_out_internal(bool ripple);
void create_ghosts_from_media(Sequence *seq, long entry_point, QVector<Media *> &media_list);
void create_ghosts_from_media(Sequence *seq, long entry_point, QVector<olive::timeline::MediaImportData> &media_list);
void add_clips_from_ghosts(ComboAction *ca, Sequence *s);
int getTimelineScreenPointFromFrame(long frame);
+133 -46
View File
@@ -20,6 +20,21 @@
#include "viewer.h"
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
}
#include <QtMath>
#include <QAudioOutput>
#include <QPainter>
#include <QStringList>
#include <QTimer>
#include <QHBoxLayout>
#include <QPushButton>
#include <QDrag>
#include <QMimeData>
#include "rendering/audio.h"
#include "timeline.h"
#include "panels/project.h"
@@ -45,19 +60,6 @@
#define FRAMES_IN_ONE_MINUTE 1798 // 1800 - 2
#define FRAMES_IN_TEN_MINUTES 17978 // (FRAMES_IN_ONE_MINUTE * 10) - 2
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
}
#include <QtMath>
#include <QAudioOutput>
#include <QPainter>
#include <QStringList>
#include <QTimer>
#include <QHBoxLayout>
#include <QPushButton>
Viewer::Viewer(QWidget *parent) :
Panel(parent),
playing(false),
@@ -120,7 +122,6 @@ bool Viewer::is_main_sequence() {
}
void Viewer::set_main_sequence() {
clean_created_seq();
set_sequence(true, olive::ActiveSequence);
}
@@ -401,7 +402,7 @@ void Viewer::play(bool in_to_out) {
if (!is_recording_cued()
&& playback_speed >= 0
&& (playing_in_to_out
|| seq->playhead >= sequence_end_frame
|| (olive::CurrentConfig.auto_seek_to_beginning && seq->playhead >= sequence_end_frame)
|| (seek_to_in && seq->playhead >= seq->workarea_out))) {
seek(seek_to_in ? seq->workarea_in : 0);
}
@@ -539,6 +540,17 @@ void Viewer::update_viewer() {
update_end_timecode();
}
void Viewer::initiate_drag(olive::timeline::MediaImportType drag_type)
{
// FIXME: This should contain actual metadata rather than fake metadata
QDrag* drag = new QDrag(this);
QMimeData* mimeData = new QMimeData;
mimeData->setText(QString::number(drag_type));
drag->setMimeData(mimeData);
drag->exec();
}
void Viewer::clear_in() {
if (seq != nullptr
&& seq->using_workarea) {
@@ -586,6 +598,12 @@ void Viewer::set_panel_name(const QString &n) {
update_window_title();
}
void Viewer::show_videoaudio_buttons(bool s)
{
video_only_button->setVisible(s);
audio_only_button->setVisible(s);
}
void Viewer::update_window_title() {
QString name;
if (seq == nullptr) {
@@ -659,8 +677,12 @@ void Viewer::setup_ui() {
QHBoxLayout* lower_control_layout = new QHBoxLayout(lower_controls);
lower_control_layout->setMargin(0);
// current time code
QSizePolicy timecode_container_policy(QSizePolicy::Minimum, QSizePolicy::Maximum);
QSizePolicy lower_control_policy(QSizePolicy::Expanding, QSizePolicy::Maximum);
// Current time code container
QWidget* current_timecode_container = new QWidget();
current_timecode_container->setSizePolicy(timecode_container_policy);
QHBoxLayout* current_timecode_container_layout = new QHBoxLayout(current_timecode_container);
current_timecode_container_layout->setSpacing(0);
current_timecode_container_layout->setMargin(0);
@@ -668,11 +690,19 @@ void Viewer::setup_ui() {
current_timecode_container_layout->addWidget(current_timecode_slider);
lower_control_layout->addWidget(current_timecode_container);
// Left controls container
QWidget* left_controls = new QWidget();
left_controls->setSizePolicy(lower_control_policy);
lower_control_layout->addWidget(left_controls);
// Playback controls container
QWidget* playback_controls = new QWidget();
playback_controls->setSizePolicy(lower_control_policy);
QHBoxLayout* playback_control_layout = new QHBoxLayout(playback_controls);
playback_control_layout->setSpacing(0);
playback_control_layout->setMargin(0);
playback_control_layout->addStretch();
go_to_start_button = new QPushButton();
go_to_start_button->setIcon(olive::icon::ViewerGoToStart);
@@ -699,9 +729,40 @@ void Viewer::setup_ui() {
connect(go_to_end_frame, SIGNAL(clicked(bool)), this, SLOT(go_to_out()));
playback_control_layout->addWidget(go_to_end_frame);
playback_control_layout->addStretch();
lower_control_layout->addWidget(playback_controls);
// Right controls container
QWidget* right_controls = new QWidget();
right_controls->setSizePolicy(lower_control_policy);
QHBoxLayout* right_control_layout = new QHBoxLayout(right_controls);
right_control_layout->setSpacing(0);
right_control_layout->setMargin(0);
right_control_layout->addStretch();
video_only_button = new QPushButton();
video_only_button->setToolTip(tr("Drag video only"));
video_only_button->setIcon(olive::icon::MediaVideo);
video_only_button->setVisible(false);
right_control_layout->addWidget(video_only_button);
connect(video_only_button, SIGNAL(pressed()), this, SLOT(drag_video_only()));
audio_only_button = new QPushButton();
audio_only_button->setToolTip(tr("Drag audio only"));
audio_only_button->setIcon(olive::icon::MediaAudio);
audio_only_button->setVisible(false);
right_control_layout->addWidget(audio_only_button);
connect(audio_only_button, SIGNAL(pressed()), this, SLOT(drag_audio_only()));
right_control_layout->addStretch();
lower_control_layout->addWidget(right_controls);
// End time code container
QWidget* end_timecode_container = new QWidget();
end_timecode_container->setSizePolicy(timecode_container_policy);
QHBoxLayout* end_timecode_layout = new QHBoxLayout(end_timecode_container);
end_timecode_layout->setSpacing(0);
@@ -720,7 +781,8 @@ void Viewer::set_media(Media* m) {
main_sequence = false;
media = m;
clean_created_seq();
SequencePtr new_sequence = nullptr;
if (media != nullptr) {
switch (media->get_type()) {
case MEDIA_TYPE_FOOTAGE:
@@ -729,30 +791,31 @@ void Viewer::set_media(Media* m) {
marker_ref = &footage->markers;
seq = std::make_shared<Sequence>();
new_sequence = std::make_shared<Sequence>();
created_sequence = true;
seq->wrapper_sequence = true;
seq->name = footage->name;
new_sequence->wrapper_sequence = true;
new_sequence->name = footage->name;
seq->using_workarea = footage->using_inout;
new_sequence->using_workarea = footage->using_inout;
if (footage->using_inout) {
seq->workarea_in = footage->in;
seq->workarea_out = footage->out;
new_sequence->workarea_in = footage->in;
new_sequence->workarea_out = footage->out;
}
// FIXME: Move this magic number to Config
seq->frame_rate = 30;
new_sequence->frame_rate = olive::CurrentConfig.default_sequence_framerate;
if (footage->video_tracks.size() > 0) {
const FootageStream& video_stream = footage->video_tracks.at(0);
seq->width = video_stream.video_width;
seq->height = video_stream.video_height;
if (video_stream.video_frame_rate > 0 && !video_stream.infinite_length) seq->frame_rate = video_stream.video_frame_rate * footage->speed;
new_sequence->width = video_stream.video_width;
new_sequence->height = video_stream.video_height;
if (video_stream.video_frame_rate > 0 && !video_stream.infinite_length) {
new_sequence->frame_rate = video_stream.video_frame_rate * footage->speed;
}
ClipPtr c = std::make_shared<Clip>(seq.get());
ClipPtr c = std::make_shared<Clip>(new_sequence.get());
c->set_media(media, video_stream.file_index);
c->set_timeline_in(0);
c->set_timeline_out(footage->get_length_in_frames(seq->frame_rate));
c->set_timeline_out(footage->get_length_in_frames(new_sequence->frame_rate));
if (c->timeline_out() <= 0) {
// FIXME: Move this magic number to Config
c->set_timeline_out(150);
@@ -760,25 +823,24 @@ void Viewer::set_media(Media* m) {
c->set_track(-1);
c->set_clip_in(0);
c->refresh();
seq->clips.append(c);
new_sequence->clips.append(c);
} else {
// FIXME: Move this magic number to Config
seq->width = 1920;
seq->height = 1080;
new_sequence->width = olive::CurrentConfig.default_sequence_width;
new_sequence->height = olive::CurrentConfig.default_sequence_height;
}
if (footage->audio_tracks.size() > 0) {
const FootageStream& audio_stream = footage->audio_tracks.at(0);
seq->audio_frequency = audio_stream.audio_frequency;
new_sequence->audio_frequency = audio_stream.audio_frequency;
ClipPtr c = std::make_shared<Clip>(seq.get());
ClipPtr c = std::make_shared<Clip>(new_sequence.get());
c->set_media(media, audio_stream.file_index);
c->set_timeline_in(0);
c->set_timeline_out(footage->get_length_in_frames(seq->frame_rate));
c->set_timeline_out(footage->get_length_in_frames(new_sequence->frame_rate));
c->set_track(0);
c->set_clip_in(0);
c->refresh();
seq->clips.append(c);
new_sequence->clips.append(c);
if (footage->video_tracks.size() == 0) {
viewer_widget->waveform = true;
@@ -787,19 +849,19 @@ void Viewer::set_media(Media* m) {
viewer_widget->frame_update();
}
} else {
// FIXME: Move this magic number to Config
seq->audio_frequency = 48000;
new_sequence->audio_frequency = olive::CurrentConfig.default_sequence_audio_frequency;
}
seq->audio_layout = AV_CH_LAYOUT_STEREO;
new_sequence->audio_layout = AV_CH_LAYOUT_STEREO;
}
break;
case MEDIA_TYPE_SEQUENCE:
seq = media->to_sequence();
new_sequence = media->to_sequence();
break;
}
}
set_sequence(false, seq);
set_sequence(false, new_sequence);
}
void Viewer::update_playhead() {
@@ -810,7 +872,11 @@ void Viewer::timer_update() {
previous_playhead = seq->playhead;
seq->playhead = qMax(0, qRound(playhead_start + ((QDateTime::currentMSecsSinceEpoch()-start_msecs) * 0.001 * seq->frame_rate * playback_speed)));
if (olive::CurrentConfig.seek_also_selects) panel_timeline->select_from_playhead();
if (olive::CurrentConfig.seek_also_selects) {
panel_timeline->select_from_playhead();
}
update_parents(olive::CurrentConfig.seek_also_selects);
if (playing) {
@@ -821,7 +887,8 @@ void Viewer::timer_update() {
pause();
}
} else if (playback_speed > 0) {
if (seq->playhead >= seq->getEndFrame()) {
long end_frame = seq->getEndFrame();
if ((olive::CurrentConfig.auto_seek_to_beginning || previous_playhead < end_frame) && seq->playhead >= end_frame) {
pause();
}
if (seq->using_workarea && seq->playhead >= seq->workarea_out) {
@@ -848,6 +915,16 @@ void Viewer::resize_move(double d) {
set_zoom_value(headers->get_zoom()*d);
}
void Viewer::drag_video_only()
{
initiate_drag(olive::timeline::kImportVideoOnly);
}
void Viewer::drag_audio_only()
{
initiate_drag(olive::timeline::kImportAudioOnly);
}
void Viewer::clean_created_seq() {
viewer_widget->waveform = false;
@@ -861,7 +938,9 @@ void Viewer::clean_created_seq() {
}
*/
// Delete the current sequence
seq.reset();
created_sequence = false;
}
}
@@ -871,13 +950,19 @@ void Viewer::set_sequence(bool main, SequencePtr s) {
reset_all_audio();
main_sequence = main;
viewer_widget->wait_until_render_is_paused();
// If we had a current sequence open, close it
if (seq != nullptr) {
close_active_clips(seq.get());
}
clean_created_seq();
main_sequence = main;
seq = (main) ? olive::ActiveSequence : s;
bool null_sequence = (seq == nullptr);
@@ -891,6 +976,8 @@ void Viewer::set_sequence(bool main, SequencePtr s) {
play_button->setEnabled(!null_sequence);
next_frame_button->setEnabled(!null_sequence);
go_to_end_frame->setEnabled(!null_sequence);
video_only_button->setEnabled(!null_sequence);
audio_only_button->setEnabled(!null_sequence);
if (!null_sequence) {
current_timecode_slider->SetFrameRate(seq->frame_rate);
+14
View File
@@ -27,6 +27,7 @@
#include <QPushButton>
#include "timeline/marker.h"
#include "timeline/mediaimportdata.h"
#include "project/media.h"
#include "ui/panel.h"
@@ -64,6 +65,7 @@ public:
void set_out_point();
void set_zoom(bool in);
void set_panel_name(const QString& n);
void show_videoaudio_buttons(bool s);
// playback functions
void seek(long p);
@@ -98,6 +100,10 @@ public:
TimelineHeader* headers;
void initiate_drag(olive::timeline::MediaImportType drag_type);
virtual void Retranslate() override;
protected:
virtual void resizeEvent(QResizeEvent *event) override;
@@ -116,12 +122,17 @@ public slots:
void close_media();
void update_viewer();
private slots:
void update_playhead();
void timer_update();
void recording_flasher_update();
void resize_move(double d);
void drag_video_only();
void drag_audio_only();
private:
void update_window_title();
@@ -155,6 +166,9 @@ private:
QPushButton* next_frame_button;
QPushButton* go_to_end_frame;
QPushButton* video_only_button;
QPushButton* audio_only_button;
bool cue_recording_internal;
QTimer recording_flasher;