diff --git a/effects/volumeeffect.cpp b/effects/volumeeffect.cpp index 546e3c99a..b79043dd6 100644 --- a/effects/volumeeffect.cpp +++ b/effects/volumeeffect.cpp @@ -4,8 +4,8 @@ #include #include #include +#include -#include "playback/audio.h" #include "ui/labelslider.h" #include "ui/collapsiblewidget.h" diff --git a/io/media.cpp b/io/media.cpp index 3ca621a85..9d50afe97 100644 --- a/io/media.cpp +++ b/io/media.cpp @@ -6,9 +6,7 @@ extern "C" { #include } -Media::Media() { - -} +Media::Media() {} Media::~Media() { for (int i=0;i #include -#define MEDIA_TYPE_FOOTAGE 0 -#define MEDIA_TYPE_SEQUENCE 1 -#define MEDIA_TYPE_FOLDER 2 -#define MEDIA_TYPE_SOLID 3 - struct Sequence; struct MediaStream { @@ -34,12 +29,10 @@ struct Media ~Media(); QString url; - QString name; - char type; + QString name; int64_t length; QVector video_tracks; QVector audio_tracks; - Sequence* sequence; int save_id; long get_length_in_frames(float frame_rate); MediaStream* get_stream_from_file_index(int index); diff --git a/io/previewgenerator.cpp b/io/previewgenerator.cpp index e69d9daf4..a2a6824d4 100644 --- a/io/previewgenerator.cpp +++ b/io/previewgenerator.cpp @@ -26,170 +26,162 @@ PreviewGenerator::PreviewGenerator(QObject* parent) : QThread(parent) { #define WAVEFORM_RESOLUTION 64 void PreviewGenerator::run() { - if (media == NULL) { - qDebug() << "[ERROR] No media was set for preview generation"; - } else { - if (media->type == MEDIA_TYPE_SEQUENCE) { - qDebug() << "[ERROR] Cannot run preview generation on a sequence"; - } else { - SwsContext* sws_ctx; - SwrContext* swr_ctx; - AVFrame* temp_frame = av_frame_alloc(); - AVCodecContext** codec_ctx = new AVCodecContext* [fmt_ctx->nb_streams]; - for (unsigned int i=0;inb_streams;i++) { - codec_ctx[i] = NULL; - if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { - AVCodec* codec = avcodec_find_decoder(fmt_ctx->streams[i]->codecpar->codec_id); - codec_ctx[i] = avcodec_alloc_context3(codec); - avcodec_parameters_to_context(codec_ctx[i], fmt_ctx->streams[i]->codecpar); - avcodec_open2(codec_ctx[i], codec, NULL); + Q_ASSERT(media != NULL); - if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && codec_ctx[i]->channel_layout == 0) { - codec_ctx[i]->channel_layout = guess_layout_from_channels(fmt_ctx->streams[i]->codecpar->channels); - } + SwsContext* sws_ctx; + SwrContext* swr_ctx; + AVFrame* temp_frame = av_frame_alloc(); + AVCodecContext** codec_ctx = new AVCodecContext* [fmt_ctx->nb_streams]; + for (unsigned int i=0;inb_streams;i++) { + codec_ctx[i] = NULL; + if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO || fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + AVCodec* codec = avcodec_find_decoder(fmt_ctx->streams[i]->codecpar->codec_id); + codec_ctx[i] = avcodec_alloc_context3(codec); + avcodec_parameters_to_context(codec_ctx[i], fmt_ctx->streams[i]->codecpar); + avcodec_open2(codec_ctx[i], codec, NULL); + + if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && codec_ctx[i]->channel_layout == 0) { + codec_ctx[i]->channel_layout = guess_layout_from_channels(fmt_ctx->streams[i]->codecpar->channels); + } + } + } + AVPacket packet; + bool done = true; + + bool end_of_file = false; + + // get the ball rolling + av_read_frame(fmt_ctx, &packet); + avcodec_send_packet(codec_ctx[packet.stream_index], &packet); + + while (!end_of_file) { + while (codec_ctx[packet.stream_index] == NULL || avcodec_receive_frame(codec_ctx[packet.stream_index], temp_frame) == AVERROR(EAGAIN)) { + av_packet_unref(&packet); + int read_ret = av_read_frame(fmt_ctx, &packet); + if (read_ret < 0) { + end_of_file = true; + if (read_ret != AVERROR_EOF) qDebug() << "[ERROR] Failed to read packet for preview generation"; + break; + } else if (codec_ctx[packet.stream_index] != NULL) { + int send_ret = avcodec_send_packet(codec_ctx[packet.stream_index], &packet); + if (send_ret < 0) { + qDebug() << "[ERROR] Failed to send packet for preview generation - aborting"; + end_of_file = true; + break; } } - AVPacket packet; - bool done = true; + } + if (!end_of_file) { + MediaStream* s = media->get_stream_from_file_index(packet.stream_index); + if (s != NULL && !s->preview_done) { + if (fmt_ctx->streams[packet.stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { + int dstH = 120; + int dstW = dstH * ((float)temp_frame->width/(float)temp_frame->height); + uint8_t* data = new uint8_t[dstW*dstH*3]; - bool end_of_file = false; + sws_ctx = sws_getContext( + temp_frame->width, + temp_frame->height, + static_cast(temp_frame->format), + dstW, + dstH, + static_cast(AV_PIX_FMT_RGB24), + SWS_FAST_BILINEAR, + NULL, + NULL, + NULL + ); - // get the ball rolling - av_read_frame(fmt_ctx, &packet); - avcodec_send_packet(codec_ctx[packet.stream_index], &packet); + int linesize[AV_NUM_DATA_POINTERS]; + linesize[0] = dstW*3; + sws_scale(sws_ctx, temp_frame->data, temp_frame->linesize, 0, temp_frame->height, &data, linesize); - while (!end_of_file) { - while (codec_ctx[packet.stream_index] == NULL || avcodec_receive_frame(codec_ctx[packet.stream_index], temp_frame) == AVERROR(EAGAIN)) { - av_packet_unref(&packet); - int read_ret = av_read_frame(fmt_ctx, &packet); - if (read_ret < 0) { - end_of_file = true; - if (read_ret != AVERROR_EOF) qDebug() << "[ERROR] Failed to read packet for preview generation"; - break; - } else if (codec_ctx[packet.stream_index] != NULL) { - int send_ret = avcodec_send_packet(codec_ctx[packet.stream_index], &packet); - if (send_ret < 0) { - qDebug() << "[ERROR] Failed to send packet for preview generation - aborting"; - end_of_file = true; + s->video_preview = QImage(data, dstW, dstH, linesize[0], QImage::Format_RGB888); + + // delete [] data; + + s->preview_done = true; + + sws_freeContext(sws_ctx); + + avcodec_close(codec_ctx[packet.stream_index]); + codec_ctx[packet.stream_index] = NULL; + } else if (fmt_ctx->streams[packet.stream_index]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { + int interval = qFloor((temp_frame->sample_rate/WAVEFORM_RESOLUTION)/4)*4; + + AVFrame* swr_frame = av_frame_alloc(); + swr_frame->channel_layout = temp_frame->channel_layout; + swr_frame->sample_rate = temp_frame->sample_rate; + swr_frame->format = AV_SAMPLE_FMT_S16; + + swr_ctx = swr_alloc_set_opts( + NULL, + temp_frame->channel_layout, + static_cast(swr_frame->format), + temp_frame->sample_rate, + temp_frame->channel_layout, + static_cast(temp_frame->format), + temp_frame->sample_rate, + 0, + NULL + ); + + swr_init(swr_ctx); + + swr_convert_frame(swr_ctx, swr_frame, temp_frame); + + int channel_skip = swr_frame->channels * 2; + for (int i=0;inb_samples;i+=interval) { + for (int j=0;jchannels;j++) { + qint16 min = 0; + qint16 max = 0; + for (int k=j*2;kdata[0][i+k+1] << 8) | swr_frame->data[0][i+k]); + if (sample > max) { + max = sample; + } else if (sample < min) { + min = sample; + } + } + min /= 256; + max /= 256; + s->audio_preview.append(min); + s->audio_preview.append(max); + } + } + + swr_free(&swr_ctx); + av_frame_free(&swr_frame); + } + + // check if we've got all our previews + if (media->audio_tracks.size() == 0) { + done = true; + for (int i=0;ivideo_tracks.size();i++) { + if (!media->video_tracks.at(i)->preview_done) { + done = false; break; } } - } - if (!end_of_file) { - MediaStream* s = media->get_stream_from_file_index(packet.stream_index); - if (s != NULL && !s->preview_done) { - if (fmt_ctx->streams[packet.stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { - int dstH = 120; - int dstW = dstH * ((float)temp_frame->width/(float)temp_frame->height); - uint8_t* data = new uint8_t[dstW*dstH*3]; - - sws_ctx = sws_getContext( - temp_frame->width, - temp_frame->height, - static_cast(temp_frame->format), - dstW, - dstH, - static_cast(AV_PIX_FMT_RGB24), - SWS_FAST_BILINEAR, - NULL, - NULL, - NULL - ); - - int linesize[AV_NUM_DATA_POINTERS]; - linesize[0] = dstW*3; - sws_scale(sws_ctx, temp_frame->data, temp_frame->linesize, 0, temp_frame->height, &data, linesize); - - s->video_preview = QImage(data, dstW, dstH, linesize[0], QImage::Format_RGB888); - -// delete [] data; - - s->preview_done = true; - - sws_freeContext(sws_ctx); - - avcodec_close(codec_ctx[packet.stream_index]); - codec_ctx[packet.stream_index] = NULL; - } else if (fmt_ctx->streams[packet.stream_index]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { - int interval = qFloor((temp_frame->sample_rate/WAVEFORM_RESOLUTION)/4)*4; - - AVFrame* swr_frame = av_frame_alloc(); - swr_frame->channel_layout = temp_frame->channel_layout; - swr_frame->sample_rate = temp_frame->sample_rate; - swr_frame->format = AV_SAMPLE_FMT_S16; - - swr_ctx = swr_alloc_set_opts( - NULL, - temp_frame->channel_layout, - static_cast(swr_frame->format), - temp_frame->sample_rate, - temp_frame->channel_layout, - static_cast(temp_frame->format), - temp_frame->sample_rate, - 0, - NULL - ); - - swr_init(swr_ctx); - - swr_convert_frame(swr_ctx, swr_frame, temp_frame); - - int channel_skip = swr_frame->channels * 2; - for (int i=0;inb_samples;i+=interval) { - for (int j=0;jchannels;j++) { - qint16 min = 0; - qint16 max = 0; - for (int k=j*2;kdata[0][i+k+1] << 8) | swr_frame->data[0][i+k]); - if (sample > max) { - max = sample; - } else if (sample < min) { - min = sample; - } - } - min /= 256; - max /= 256; - s->audio_preview.append(min); - s->audio_preview.append(max); - } - } - - swr_free(&swr_ctx); - av_frame_free(&swr_frame); - } - - // check if we've got all our previews - if (media->audio_tracks.size() == 0) { - done = true; - for (int i=0;ivideo_tracks.size();i++) { - if (!media->video_tracks.at(i)->preview_done) { - done = false; - break; - } - } - if (done) { - end_of_file = true; - break; - } - } + if (done) { + end_of_file = true; + break; } - av_packet_unref(&packet); } } - for (int i=0;iaudio_tracks.size();i++) { - media->audio_tracks.at(i)->preview_done = true; - } - av_frame_free(&temp_frame); - for (unsigned int i=0;inb_streams;i++) { - if (codec_ctx[i] != NULL) { - avcodec_close(codec_ctx[i]); - } - } - delete [] codec_ctx; + av_packet_unref(&packet); } } - - if (fmt_ctx != NULL) { - avformat_close_input(&fmt_ctx); + for (int i=0;iaudio_tracks.size();i++) { + media->audio_tracks.at(i)->preview_done = true; } + av_frame_free(&temp_frame); + for (unsigned int i=0;inb_streams;i++) { + if (codec_ctx[i] != NULL) { + avcodec_close(codec_ctx[i]); + } + } + delete [] codec_ctx; + + avformat_close_input(&fmt_ctx); } diff --git a/mainwindow.cpp b/mainwindow.cpp index 32ae0a584..5ccf27529 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #define OLIVE_FILE_FILTER "Olive Project (*.ove)" @@ -304,6 +305,14 @@ bool MainWindow::can_close_project() { return true; } +void MainWindow::closeEvent(QCloseEvent *e) { + if (can_close_project()) { + e->accept(); + } else { + e->ignore(); + } +} + void MainWindow::on_action_Save_Project_triggered() { save_project(); @@ -531,3 +540,8 @@ void MainWindow::on_actionSlide_Tool_triggered() { if (panel_timeline->focused()) panel_timeline->ui->toolSlideButton->click(); } + +void MainWindow::on_actionFolder_triggered() +{ + panel_project->new_folder(); +} diff --git a/mainwindow.h b/mainwindow.h index 3adbca085..6fd473777 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -20,6 +20,9 @@ public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); +protected: + void closeEvent(QCloseEvent *); + private slots: void on_action_Import_triggered(); @@ -139,6 +142,8 @@ private slots: void on_actionSlide_Tool_triggered(); + void on_actionFolder_triggered(); + private: Ui::MainWindow *ui; void setup_layout(); diff --git a/mainwindow.ui b/mainwindow.ui index ca99fd4a9..04f5837e3 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -38,6 +38,7 @@ + @@ -583,6 +584,11 @@ U + + + Folder + + diff --git a/olive.pro.user b/olive.pro.user index b7f9ea052..93707150a 100644 --- a/olive.pro.user +++ b/olive.pro.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/panels/project.cpp b/panels/project.cpp index 0e465b92a..b2f251ec7 100644 --- a/panels/project.cpp +++ b/panels/project.cpp @@ -38,7 +38,7 @@ Project::Project(QWidget *parent) : ui(new Ui::Project) { ui->setupUi(this); - + source_table = ui->treeWidget; connect(ui->treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, SLOT(rename_media(QTreeWidgetItem*,int))); } @@ -70,35 +70,30 @@ QString Project::get_next_sequence_name() { } void Project::rename_media(QTreeWidgetItem* item, int column) { - Media* m = get_media_from_tree(item); - m->name = item->text(column); - if (m->type == MEDIA_TYPE_SEQUENCE) { - m->sequence->name = m->name; + int type = get_type_from_tree(item); + QString n = item->text(column); + switch (type) { + case MEDIA_TYPE_FOOTAGE: get_media_from_tree(item)->name = n; break; + case MEDIA_TYPE_SEQUENCE: get_sequence_from_tree(item)->name = n; break; } } void Project::duplicate_selected() { QList items = ui->treeWidget->selectedItems(); for (int i=0;itype == MEDIA_TYPE_SEQUENCE) { - new_sequence(m->sequence->copy(), false); + int type = get_type_from_tree(items.at(i)); + if (type == MEDIA_TYPE_SEQUENCE) { + new_sequence(get_sequence_from_tree(items.at(i))->copy(), false); } } } void Project::new_sequence(Sequence *s, bool open) { - Media* m = new Media(); - m->type = MEDIA_TYPE_SEQUENCE; - m->sequence = s; - - QTreeWidgetItem* item = new QTreeWidgetItem(); - item->setFlags(item->flags() | Qt::ItemIsEditable); + QTreeWidgetItem* item = new_item(); item->setText(0, s->name); - set_media_of_tree(item, m); + set_sequence_of_tree(item, s); ui->treeWidget->addTopLevelItem(item); - source_table = ui->treeWidget; project_changed = true; @@ -128,7 +123,6 @@ Media* Project::import_file(QString file) { av_dump_format(pFormatCtx, 0, filename, 0); m = new Media(); - m->type = MEDIA_TYPE_FOOTAGE; m->url = file; m->name = file.mid(file.lastIndexOf('/')+1); @@ -155,8 +149,7 @@ Media* Project::import_file(QString file) { } m->length = pFormatCtx->duration; - QTreeWidgetItem* item = new QTreeWidgetItem(); - item->setFlags(item->flags() | Qt::ItemIsEditable); + QTreeWidgetItem* item = new_item(); if (m->video_tracks.size() == 0) { item->setIcon(0, QIcon(":/icons/audiosource.png")); } else { @@ -169,23 +162,39 @@ Media* Project::import_file(QString file) { ui->treeWidget->addTopLevelItem(item); project_changed = true; + + // generate waveform/thumbnail in another thread + PreviewGenerator* pg = new PreviewGenerator(); + pg->fmt_ctx = pFormatCtx; // cleaned up in PG + pg->media = m; + connect(pg, SIGNAL(finished()), pg, SLOT(deleteLater())); + pg->start(QThread::LowPriority); } } - PreviewGenerator* pg = new PreviewGenerator(); - pg->fmt_ctx = pFormatCtx; // cleaned up in PG - pg->media = m; - connect(pg, SIGNAL(finished()), pg, SLOT(deleteLater())); - pg->start(QThread::LowPriority); - delete [] filename; return m; } +QTreeWidgetItem* Project::new_item() { + QTreeWidgetItem* item = new QTreeWidgetItem(); + item->setFlags(item->flags() | Qt::ItemIsEditable); + return item; +} + bool Project::is_focused() { return ui->treeWidget->hasFocus(); } +void Project::new_folder() { + QTreeWidgetItem* item = new_item(); + item->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator); + item->setText(0, "New Folder"); + set_item_to_folder(item); + ui->treeWidget->addTopLevelItem(item); + project_changed = true; +} + void Project::delete_selected_media() { QList items = ui->treeWidget->selectedItems(); bool remove = true; @@ -193,8 +202,9 @@ void Project::delete_selected_media() { // check if media is in use for (int i=0;itype == MEDIA_TYPE_FOOTAGE && sequence != NULL) { + QTreeWidgetItem* item = items.at(i); + Media* m = get_media_from_tree(item); + if (get_type_from_tree(item) == MEDIA_TYPE_FOOTAGE && sequence != NULL) { for (int j=0;jclip_count();j++) { Clip* c = sequence->get_clip(j); if (c != NULL && c->media == m) { @@ -292,23 +302,47 @@ void Project::import_dialog() { process_file_list(files); } +void Project::set_item_to_folder(QTreeWidgetItem* item) { + item->setData(0, Qt::UserRole + 1, MEDIA_TYPE_FOLDER); +} + Media* Project::get_media_from_tree(QTreeWidgetItem* item) { - return reinterpret_cast(item->data(0, Qt::UserRole + 1).value()); + return reinterpret_cast(item->data(0, Qt::UserRole + 2).value()); } void Project::set_media_of_tree(QTreeWidgetItem* item, Media* media) { - item->setData(0, Qt::UserRole + 1, QVariant::fromValue(reinterpret_cast(media))); + item->setData(0, Qt::UserRole + 1, MEDIA_TYPE_FOOTAGE); + item->setData(0, Qt::UserRole + 2, QVariant::fromValue(reinterpret_cast(media))); +} + +Sequence* Project::get_sequence_from_tree(QTreeWidgetItem* item) { + return reinterpret_cast(item->data(0, Qt::UserRole + 2).value()); +} + +void Project::set_sequence_of_tree(QTreeWidgetItem* item, Sequence* sequence) { + item->setData(0, Qt::UserRole + 1, MEDIA_TYPE_SEQUENCE); + item->setData(0, Qt::UserRole + 2, QVariant::fromValue(reinterpret_cast(sequence))); +} + +int Project::get_type_from_tree(QTreeWidgetItem* item) { + return item->data(0, Qt::UserRole + 1).toInt(); } void Project::delete_media(QTreeWidgetItem* item) { - Media* m = get_media_from_tree(item); - if (m->type == MEDIA_TYPE_SEQUENCE) { - if (sequence == m->sequence) { + int type = get_type_from_tree(item); + switch (type) { + case MEDIA_TYPE_FOOTAGE: + delete get_media_from_tree(item); + break; + case MEDIA_TYPE_SEQUENCE: + Sequence* s = get_sequence_from_tree(item); + if (sequence == s) { set_sequence(NULL); } - delete m->sequence; + delete s; + break; } - delete m; + project_changed = true; } @@ -573,8 +607,9 @@ void Project::save_project() { int len = ui->treeWidget->topLevelItemCount(); stream.writeStartElement("media"); for (int i=0;itreeWidget->topLevelItem(i)); - if (m->type == MEDIA_TYPE_FOOTAGE) { + QTreeWidgetItem* item = ui->treeWidget->topLevelItem(i); + if (get_type_from_tree(item) == MEDIA_TYPE_FOOTAGE) { + Media* m = get_media_from_tree(item); m->save_id = i; stream.writeStartElement("footage"); stream.writeAttribute("id", QString::number(i)); @@ -587,9 +622,9 @@ void Project::save_project() { stream.writeStartElement("timeline"); for (int i=0;itreeWidget->topLevelItem(i)); - if (m->type == MEDIA_TYPE_SEQUENCE) { - Sequence* s = m->sequence; + QTreeWidgetItem* item = ui->treeWidget->topLevelItem(i); + if (get_type_from_tree(item) == MEDIA_TYPE_SEQUENCE) { + Sequence* s = get_sequence_from_tree(item); stream.writeStartElement("sequence"); stream.writeTextElement("name", s->name); stream.writeTextElement("width", QString::number(s->width)); diff --git a/panels/project.h b/panels/project.h index 7f89e7c8b..53417db2d 100644 --- a/panels/project.h +++ b/panels/project.h @@ -11,6 +11,11 @@ class Viewer; class SourceTable; class QTreeWidgetItem; +#define MEDIA_TYPE_FOOTAGE 0 +#define MEDIA_TYPE_SEQUENCE 1 +#define MEDIA_TYPE_FOLDER 2 +#define MEDIA_TYPE_SOLID 3 + namespace Ui { class Project; } @@ -40,12 +45,19 @@ public: void load_project(); void save_project(); + void new_folder(); + + int get_type_from_tree(QTreeWidgetItem* item); Media* get_media_from_tree(QTreeWidgetItem* item); void set_media_of_tree(QTreeWidgetItem* item, Media* media); + Sequence* get_sequence_from_tree(QTreeWidgetItem* item); + void set_sequence_of_tree(QTreeWidgetItem* item, Sequence* sequence); + void set_item_to_folder(QTreeWidgetItem* item); SourceTable* source_table; private: Ui::Project *ui; + QTreeWidgetItem* new_item(); private slots: void rename_media(QTreeWidgetItem* item, int column); }; diff --git a/panels/project.ui b/panels/project.ui index 5ab0c04f5..386fbb1ef 100644 --- a/panels/project.ui +++ b/panels/project.ui @@ -35,6 +35,9 @@ + + true + QAbstractItemView::NoEditTriggers @@ -51,7 +54,10 @@ QAbstractItemView::SelectRows - false + true + + + true true diff --git a/ui/audiomonitor.cpp b/ui/audiomonitor.cpp index 5bdc88a81..ed4e52c49 100644 --- a/ui/audiomonitor.cpp +++ b/ui/audiomonitor.cpp @@ -10,6 +10,7 @@ #include #include +#define AUDIO_MONITOR_PEAK_HEIGHT 15 #define AUDIO_MONITOR_GAP 3 extern "C" { @@ -39,24 +40,39 @@ void AudioMonitor::paintEvent(QPaintEvent *) { QPainter p(this); int channel_x = AUDIO_MONITOR_GAP; int channel_count = av_get_channel_layout_nb_channels(sequence->audio_layout); + if (peaks.size() != channel_count) { + peaks.resize(channel_count); + peaks.fill(false); + } int channel_width = (width()/channel_count) - AUDIO_MONITOR_GAP; long playhead_offset = -1; int i; for (i=0;iplayhead - sample_cache_offset) * channel_count; if (playhead_offset >= 0 && playhead_offset < sample_cache.size()) { double multiplier = 1 - qAbs((double) sample_cache.at(playhead_offset+i) / 32768.0); // 16-bit int divided to float + if (multiplier == (double) 0) { + peaks[i] = true; + } r.setHeight(r.height()*multiplier); } else { reset(); } } + QRect peak_rect(channel_x, 0, channel_width, AUDIO_MONITOR_PEAK_HEIGHT); + if (peaks.at(i)) { + p.fillRect(peak_rect, QColor(255, 0, 0)); + } else { + p.fillRect(peak_rect, QColor(64, 0, 0)); + } + p.fillRect(r, QColor(0, 0, 0, 160)); + channel_x += channel_width + AUDIO_MONITOR_GAP; } if (playhead_offset > -1) { diff --git a/ui/audiomonitor.h b/ui/audiomonitor.h index c22212412..4e8f374ff 100644 --- a/ui/audiomonitor.h +++ b/ui/audiomonitor.h @@ -22,6 +22,7 @@ public slots: private: QLinearGradient gradient; + QVector peaks; }; #endif // AUDIOMONITOR_H diff --git a/ui/sourcetable.cpp b/ui/sourcetable.cpp index dd4766ba6..6c125173a 100644 --- a/ui/sourcetable.cpp +++ b/ui/sourcetable.cpp @@ -13,14 +13,9 @@ SourceTable::SourceTable(QWidget* parent) : QTreeWidget(parent) { sortByColumn(0, Qt::AscendingOrder); - setAcceptDrops(true); - editing_item = NULL; rename_timer.setInterval(500); connect(&rename_timer, SIGNAL(timeout()), this, SLOT(rename_interval())); connect(this, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(item_click(QTreeWidgetItem*,int))); -// connect(this, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(stop_rename_timer())); - -// connect(this, SIGNAL(itemChanged(QTreeWidgetItem*,int)), this, ) } void SourceTable::stop_rename_timer() { @@ -50,9 +45,8 @@ void SourceTable::mouseDoubleClickEvent(QMouseEvent* ) { panel_project->import_dialog(); } else if (selectedItems().count() == 1) { QTreeWidgetItem* item = selectedItems().at(0); - Media* m = reinterpret_cast(item->data(0, Qt::UserRole + 1).value()); - if (m->type == MEDIA_TYPE_SEQUENCE) { - set_sequence(m->sequence); + if (panel_project->get_type_from_tree(item) == MEDIA_TYPE_SEQUENCE) { + set_sequence(panel_project->get_sequence_from_tree(item)); } } } @@ -75,7 +69,6 @@ void SourceTable::dragMoveEvent(QDragMoveEvent *event) { void SourceTable::dropEvent(QDropEvent* event) { const QMimeData* mimeData = event->mimeData(); - if (mimeData->hasUrls()) { QList urls = mimeData->urls(); if (!urls.isEmpty()) { @@ -87,5 +80,34 @@ void SourceTable::dropEvent(QDropEvent* event) { panel_project->process_file_list(paths); } event->acceptProposedAction(); + } else { + QTreeWidgetItem* item = itemAt(event->pos()); + if (item == NULL || (item != NULL && panel_project->get_type_from_tree(item) == MEDIA_TYPE_FOLDER)) { + QList items = selectedItems(); + for (int i=0;iparent() == NULL) { + takeTopLevelItem(indexOfTopLevelItem(s)); + } else { + // if child belongs to a selected parent, assume the user is just moving the parent and ignore the child + for (int j=0;jparent() == items.at(j)) { + ignore = true; + break; + } + } + if (!ignore) s->parent()->takeChild(s->parent()->indexOfChild(s)); + } + if (!ignore) { + if (item == NULL) { + addTopLevelItem(s); + } else { + item->addChild(s); + } + } + } + project_changed = true; + } } } diff --git a/ui/timelinewidget.cpp b/ui/timelinewidget.cpp index 6e5c159c9..a6328792e 100644 --- a/ui/timelinewidget.cpp +++ b/ui/timelinewidget.cpp @@ -59,27 +59,29 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) { panel_timeline->drag_frame_start = entry_point + panel_timeline->getFrameFromScreenPoint(50); panel_timeline->drag_track_start = (bottom_align) ? -1 : 0; for (int i=0;iget_media_from_tree(items.at(i)); - Ghost g; - g.clip = -1; - g.media = m; - g.old_clip_in = g.clip_in = 0; - g.in = entry_point; - entry_point += m->get_length_in_frames(sequence->frame_rate); - g.out = entry_point; - g.trimming = false; - for (int j=0;jaudio_tracks.size();j++) { - g.track = j; - g.media_stream = m->audio_tracks.at(j); - ignore_infinite_length = true; - panel_timeline->ghosts.append(g); - } - for (int j=0;jvideo_tracks.size();j++) { - g.track = -1-j; - g.media_stream = m->video_tracks.at(j); - if (m->video_tracks[j]->infinite_length && !ignore_infinite_length) g.out = g.in + 100; - panel_timeline->ghosts.append(g); + QTreeWidgetItem* item = items.at(i); + if (panel_project->get_type_from_tree(item) == MEDIA_TYPE_FOOTAGE) { + Media* m = panel_project->get_media_from_tree(item); + bool ignore_infinite_length = (m->audio_tracks.size() > 0); + Ghost g; + g.clip = -1; + g.media = m; + g.old_clip_in = g.clip_in = 0; + g.in = entry_point; + entry_point += m->get_length_in_frames(sequence->frame_rate); + g.out = entry_point; + g.trimming = false; + for (int j=0;jaudio_tracks.size();j++) { + g.track = j; + g.media_stream = m->audio_tracks.at(j); + panel_timeline->ghosts.append(g); + } + for (int j=0;jvideo_tracks.size();j++) { + g.track = -1-j; + g.media_stream = m->video_tracks.at(j); + if (m->video_tracks[j]->infinite_length && !ignore_infinite_length) g.out = g.in + 100; + panel_timeline->ghosts.append(g); + } } } for (int i=0;ighosts.size();i++) {