diff --git a/effects/volumeeffect.cpp b/effects/volumeeffect.cpp index 0c01b6a65..5c64ebd8b 100644 --- a/effects/volumeeffect.cpp +++ b/effects/volumeeffect.cpp @@ -48,7 +48,9 @@ void VolumeEffect::save(QXmlStreamWriter *stream) { void VolumeEffect::process_audio(quint8 *samples, int nb_bytes) { for (int i=0;ivalue()*0.01; + samples[i+1] = (quint8) (full_sample >> 8); samples[i] = (quint8) full_sample; } diff --git a/io/media.h b/io/media.h index bf7f179d6..b98ac9c23 100644 --- a/io/media.h +++ b/io/media.h @@ -18,7 +18,7 @@ struct MediaStream { // preview thumbnail/waveform bool preview_done; - QImage preview; + QImage preview; // TODO change to QPixmap QMutex preview_lock; int preview_audio_index; }; diff --git a/io/previewgenerator.cpp b/io/previewgenerator.cpp index 0c6f02c11..06ececab0 100644 --- a/io/previewgenerator.cpp +++ b/io/previewgenerator.cpp @@ -33,7 +33,7 @@ MediaStream* PreviewGenerator::get_stream_from_file_index(int index) { return NULL; } -#define WAVEFORM_RESOLUTION 256 +#define WAVEFORM_RESOLUTION 64 void PreviewGenerator::run() { if (media == NULL) { @@ -55,7 +55,9 @@ void PreviewGenerator::run() { if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { // initiate qimage MediaStream* ms = get_stream_from_file_index(i); - ms->preview = QImage(fmt_ctx->streams[i]->duration * av_q2d(fmt_ctx->streams[i]->time_base) * WAVEFORM_RESOLUTION, 255, QImage::Format_RGBA8888); + int width = fmt_ctx->streams[i]->duration * av_q2d(fmt_ctx->streams[i]->time_base) * WAVEFORM_RESOLUTION; + if (width > 32767) qDebug() << "[WARNING] Due to limitations in Qt's painter, this waveform may not appear correctly (see issue #76)"; + ms->preview = QImage(width, 80, QImage::Format_RGBA8888); ms->preview_audio_index = 0; ms->preview.fill(Qt::transparent); } @@ -125,13 +127,25 @@ void PreviewGenerator::run() { QPainter p; p.begin(&s->preview); p.setPen(QColor(80, 80, 80)); + int channel_jump = swr_frame->channels * 2; + int divider = (32768.0/(s->preview.height()/2))*swr_frame->channels; for (int i=0;inb_samples;i+=interval) { for (int j=0;jchannels;j++) { - qint16 sample = ((swr_frame->data[0][i+1] << 8) | swr_frame->data[0][i]); - sample /= 256; - sample /= swr_frame->channels; + 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 /= divider; + max /= divider; + int mid = channel_height*j+(channel_height/2); - p.drawLine(s->preview_audio_index, mid, s->preview_audio_index, mid+sample); + p.drawLine(s->preview_audio_index, mid+min, s->preview_audio_index, mid+max); i += 2; } s->preview_audio_index++; diff --git a/mainwindow.cpp b/mainwindow.cpp index 4832383bd..56eae5bea 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -23,12 +23,15 @@ #define OLIVE_FILE_FILTER "Olive Project (*.ove)" void MainWindow::setup_layout() { + panel_project->show(); + panel_effect_controls->show(); + panel_viewer->show(); + panel_timeline->show(); + addDockWidget(Qt::TopDockWidgetArea, panel_project); addDockWidget(Qt::TopDockWidgetArea, panel_effect_controls); addDockWidget(Qt::TopDockWidgetArea, panel_viewer); addDockWidget(Qt::BottomDockWidgetArea, panel_timeline); - - setCentralWidget(NULL); } MainWindow::MainWindow(QWidget *parent) : @@ -66,6 +69,8 @@ MainWindow::MainWindow(QWidget *parent) : setWindowTitle("Olive (May 2018 | Pre-Alpha)"); statusBar()->showMessage("Welcome to Olive::Qt"); + setCentralWidget(NULL); + // TODO maybe replace these with non-pointers later on? panel_project = new Project(this); panel_effect_controls = new EffectControls(this); diff --git a/mainwindow.ui b/mainwindow.ui index df5dd8dce..657e3d5e9 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -95,7 +95,7 @@ - Playback + &Playback diff --git a/olive.pro.user b/olive.pro.user index 5b75310a5..8a5123e55 100644 --- a/olive.pro.user +++ b/olive.pro.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/panels/timeline.cpp b/panels/timeline.cpp index ed6565099..a50aed645 100644 --- a/panels/timeline.cpp +++ b/panels/timeline.cpp @@ -80,13 +80,12 @@ void Timeline::seek(long p) { repaint_timeline(); } -bool Timeline::toggle_play() { +void Timeline::toggle_play() { if (playing) { pause(); } else { play(); - } - return playing; + } } void Timeline::play() { @@ -94,10 +93,12 @@ void Timeline::play() { start_msecs = QDateTime::currentMSecsSinceEpoch(); playback_updater.start(); playing = true; + panel_viewer->set_playpause_icon(false); } void Timeline::pause() { playing = false; + panel_viewer->set_playpause_icon(true); } void Timeline::go_to_end() { @@ -167,6 +168,7 @@ void Timeline::redraw_all_clips() { ui->video_area->redraw_clips(); ui->audio_area->redraw_clips(); + ui->headers->update(); } void Timeline::select_all() { diff --git a/panels/timeline.h b/panels/timeline.h index 8327158b6..9f5c3b82e 100644 --- a/panels/timeline.h +++ b/panels/timeline.h @@ -84,7 +84,7 @@ public: void previous_frame(); void next_frame(); void seek(long p); - bool toggle_play(); + void toggle_play(); void play(); void pause(); void go_to_end(); diff --git a/panels/viewer.cpp b/panels/viewer.cpp index 89800d9e3..9f3416c5c 100644 --- a/panels/viewer.cpp +++ b/panels/viewer.cpp @@ -71,10 +71,13 @@ void Viewer::on_pushButton_4_clicked() void Viewer::on_pushButton_3_clicked() { - if (panel_timeline->toggle_play()) { - // playing - ui->pushButton_3->setIcon(QIcon(":/icons/pause.png")); - } else { - ui->pushButton_3->setIcon(QIcon(":/icons/play.png")); - } + panel_timeline->toggle_play(); +} + +void Viewer::set_playpause_icon(bool play) { + if (play) { + ui->pushButton_3->setIcon(QIcon(":/icons/play.png")); + } else { + ui->pushButton_3->setIcon(QIcon(":/icons/pause.png")); + } } diff --git a/panels/viewer.h b/panels/viewer.h index 53d99f778..7aa0856dc 100644 --- a/panels/viewer.h +++ b/panels/viewer.h @@ -20,6 +20,7 @@ public: ~Viewer(); void update_sequence(); void compose(); + void set_playpause_icon(bool play); ViewerWidget* viewer_widget; diff --git a/playback/audio.cpp b/playback/audio.cpp index d7e0f37b3..6ad3ef384 100644 --- a/playback/audio.cpp +++ b/playback/audio.cpp @@ -37,7 +37,9 @@ void init_audio() { if (!info.isFormatSupported(audio_format)) { qWarning() << "[WARNING] Couldn't initialize audio. Audio format is not supported by backend"; } else { - audio_output = new QAudioOutput(audio_format); + audio_output = new QAudioOutput(audio_format); + audio_output->setBufferSize(20480); + // connect audio_io_device = audio_output->start(); audio_device_set = true; diff --git a/ui/timelineheader.cpp b/ui/timelineheader.cpp index 72367d820..fc5c7e5a0 100644 --- a/ui/timelineheader.cpp +++ b/ui/timelineheader.cpp @@ -40,7 +40,12 @@ void TimelineHeader::paintEvent(QPaintEvent*) { if (sequence != NULL) { QPainter p(this); p.setPen(Qt::gray); - int interval = panel_timeline->getScreenPointFromFrame(sequence->frame_rate); + int interval = 0; + int multiplier = 0; + do { + multiplier++; + interval = panel_timeline->getScreenPointFromFrame(sequence->frame_rate*multiplier); + } while (interval < 10); for (int i=0;igetScreenPointFromFrame(sequence->getEndFrame()) + 100; @@ -817,6 +815,11 @@ void TimelineWidget::redraw_clips() { } QRect text_rect(clip_rect.left() + CLIP_TEXT_PADDING, clip_rect.top() + CLIP_TEXT_PADDING, clip_rect.width() - CLIP_TEXT_PADDING - CLIP_TEXT_PADDING, clip_rect.height() - CLIP_TEXT_PADDING - CLIP_TEXT_PADDING); clip_painter.drawText(text_rect, 0, clip->name, &text_rect); + if (clip->linked.size() > 0) { + int underline_y = CLIP_TEXT_PADDING + clip_painter.fontMetrics().height() + clip_rect.top(); + int underline_width = qMin(clip_rect.width() - CLIP_TEXT_PADDING, clip_rect.left() + CLIP_TEXT_PADDING+clip_painter.fontMetrics().width(clip->name)); + clip_painter.drawLine(clip_rect.left() + CLIP_TEXT_PADDING, underline_y, underline_width, underline_y); + } // bottom right gray clip_painter.setPen(Qt::gray);