precision audio playback
This commit is contained in:
@@ -923,3 +923,7 @@ void MainWindow::on_actionNest_triggered() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionToggle_Show_All_triggered() {
|
||||
if (sequence != NULL) panel_timeline->toggle_show_all();
|
||||
}
|
||||
|
||||
@@ -199,6 +199,8 @@ private slots:
|
||||
|
||||
void on_actionNest_triggered();
|
||||
|
||||
void on_actionToggle_Show_All_triggered();
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
void setup_layout();
|
||||
|
||||
@@ -137,6 +137,7 @@
|
||||
<addaction name="actionZoom_out"/>
|
||||
<addaction name="actionIncrease_Track_Height"/>
|
||||
<addaction name="actionDecrease_Track_Height"/>
|
||||
<addaction name="actionToggle_Show_All"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionFrames"/>
|
||||
<addaction name="actionDrop_Frame"/>
|
||||
@@ -848,6 +849,14 @@
|
||||
<string>Nest</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionToggle_Show_All">
|
||||
<property name="text">
|
||||
<string>Toggle Show All</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>\</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources/>
|
||||
|
||||
+22
-6
@@ -64,7 +64,8 @@ Timeline::Timeline(QWidget *parent) :
|
||||
transition_tool_clip(-1),
|
||||
transition_tool_init(false),
|
||||
transition_tool_proc(false),
|
||||
move_insert(false)
|
||||
move_insert(false),
|
||||
showing_all(false)
|
||||
{
|
||||
default_track_height = (QGuiApplication::primaryScreen()->logicalDotsPerInch() / 96) * TRACK_DEFAULT_HEIGHT;
|
||||
|
||||
@@ -145,6 +146,16 @@ void Timeline::next_cut() {
|
||||
if (seek_enabled) panel_sequence_viewer->seek(n_cut);
|
||||
}
|
||||
|
||||
void Timeline::toggle_show_all() {
|
||||
showing_all = !showing_all;
|
||||
if (showing_all) {
|
||||
old_zoom = zoom;
|
||||
set_zoom_value((double) (ui->timeline_area->width() - 200) / (double) sequence->getEndFrame());
|
||||
} else {
|
||||
set_zoom_value(old_zoom);
|
||||
}
|
||||
}
|
||||
|
||||
int Timeline::get_track_height_size(bool video) {
|
||||
if (video) {
|
||||
return video_track_heights.size();
|
||||
@@ -345,14 +356,19 @@ int lerp(int a, int b, double t) {
|
||||
return ((1.0 - t) * a) + (t * b);
|
||||
}
|
||||
|
||||
void Timeline::set_zoom(bool in) {
|
||||
zoom *= (in) ? 2 : 0.5;
|
||||
void Timeline::set_zoom_value(double v) {
|
||||
zoom = v;
|
||||
ui->headers->update_zoom(zoom);
|
||||
repaint_timeline();
|
||||
|
||||
// TODO find a way to gradually move towards target_scroll instead of just setting it?
|
||||
int target_scroll = getScreenPointFromFrame(zoom, sequence->playhead)-(ui->editAreas->width()>>1);
|
||||
ui->horizontalScrollBar->setValue(target_scroll);
|
||||
// TODO find a way to gradually move towards target_scroll instead of just setting it?
|
||||
int target_scroll = getScreenPointFromFrame(zoom, sequence->playhead)-(ui->editAreas->width()>>1);
|
||||
ui->horizontalScrollBar->setValue(target_scroll);
|
||||
}
|
||||
|
||||
void Timeline::set_zoom(bool in) {
|
||||
showing_all = false;
|
||||
set_zoom_value(zoom * ((in) ? 2 : 0.5));
|
||||
}
|
||||
|
||||
void Timeline::decheck_tool_buttons(QObject* sender) {
|
||||
|
||||
@@ -97,6 +97,7 @@ public:
|
||||
void delete_in_out(bool ripple);
|
||||
void previous_cut();
|
||||
void next_cut();
|
||||
void toggle_show_all();
|
||||
|
||||
int getTimelineScreenPointFromFrame(long frame);
|
||||
long getTimelineFrameFromScreenPoint(int x);
|
||||
@@ -116,6 +117,8 @@ public:
|
||||
long drag_frame_start;
|
||||
int drag_track_start;
|
||||
void update_effect_controls();
|
||||
bool showing_all;
|
||||
double old_zoom;
|
||||
|
||||
QVector<int> video_track_heights;
|
||||
QVector<int> audio_track_heights;
|
||||
@@ -216,6 +219,7 @@ private slots:
|
||||
void transition_menu_select(QAction*);
|
||||
|
||||
private:
|
||||
void set_zoom_value(double v);
|
||||
QVector<QPushButton*> tool_buttons;
|
||||
void decheck_tool_buttons(QObject* sender);
|
||||
void set_tool(int tool);
|
||||
|
||||
+18
-6
@@ -35,7 +35,8 @@ Viewer::Viewer(QWidget *parent) :
|
||||
seq(NULL),
|
||||
playing(false),
|
||||
created_sequence(false),
|
||||
cue_recording_internal(false)
|
||||
cue_recording_internal(false),
|
||||
just_played(false)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->headers->viewer = this;
|
||||
@@ -283,17 +284,26 @@ void Viewer::play() {
|
||||
return;
|
||||
}
|
||||
playhead_start = seq->playhead;
|
||||
start_msecs = QDateTime::currentMSecsSinceEpoch();
|
||||
playing = true;
|
||||
just_played = true;
|
||||
set_playpause_icon(false);
|
||||
playback_updater.start();
|
||||
start_msecs = QDateTime::currentMSecsSinceEpoch();
|
||||
timer_update();
|
||||
audio_thread->notifyReceiver();
|
||||
}
|
||||
}
|
||||
|
||||
void Viewer::play_wake() {
|
||||
if (just_played) {
|
||||
start_msecs = QDateTime::currentMSecsSinceEpoch();
|
||||
playback_updater.start();
|
||||
audio_thread->notifyReceiver();
|
||||
just_played = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Viewer::pause() {
|
||||
playing = false;
|
||||
just_played = false;
|
||||
set_playpause_icon(true);
|
||||
playback_updater.stop();
|
||||
|
||||
@@ -394,8 +404,10 @@ void Viewer::set_media(int type, void* media) {
|
||||
seq->name = footage->name;
|
||||
|
||||
seq->using_workarea = footage->using_inout;
|
||||
seq->workarea_in = footage->in;
|
||||
seq->workarea_out = footage->out;
|
||||
if (footage->using_inout) {
|
||||
seq->workarea_in = footage->in;
|
||||
seq->workarea_out = footage->out;
|
||||
}
|
||||
|
||||
seq->frame_rate = 30;
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ public:
|
||||
long playhead_start;
|
||||
qint64 start_msecs;
|
||||
QTimer playback_updater;
|
||||
bool just_played;
|
||||
|
||||
void cue_recording(long start, long end, int track);
|
||||
void uncue_recording();
|
||||
@@ -69,6 +70,7 @@ public:
|
||||
Ui::Viewer *ui;
|
||||
|
||||
public slots:
|
||||
void play_wake();
|
||||
|
||||
private slots:
|
||||
void on_pushButton_clicked();
|
||||
|
||||
+14
-5
@@ -9,6 +9,8 @@
|
||||
#include "panels/timeline.h"
|
||||
#include "panels/project.h"
|
||||
#include "playback/audio.h"
|
||||
#include "panels/panels.h"
|
||||
#include "panels/viewer.h"
|
||||
#include "debug.h"
|
||||
|
||||
extern "C" {
|
||||
@@ -37,8 +39,6 @@ double bytes_to_seconds(int nb_bytes, int nb_channels, int sample_rate) {
|
||||
}
|
||||
|
||||
void apply_audio_effects(Clip* c, double timecode_start, AVFrame* frame, int nb_bytes, QVector<Clip*> nests) {
|
||||
dout << c->name << timecode_start;
|
||||
|
||||
// perform all aud io effects
|
||||
double timecode_end;
|
||||
timecode_end = timecode_start + bytes_to_seconds(nb_bytes, frame->channels, frame->sample_rate);
|
||||
@@ -306,8 +306,8 @@ void cache_audio_worker(Clip* c, bool scrubbing, QVector<Clip*>& nests) {
|
||||
}
|
||||
}
|
||||
|
||||
int offset = (audio_ibuffer_read + AUDIO_BUFFER_PADDING) - c->audio_buffer_write;
|
||||
if (offset > 0) {
|
||||
int offset = audio_ibuffer_read - c->audio_buffer_write;
|
||||
if (offset > 0) {
|
||||
c->audio_buffer_write += offset;
|
||||
c->frame_sample_index += offset;
|
||||
}
|
||||
@@ -341,7 +341,9 @@ void cache_audio_worker(Clip* c, bool scrubbing, QVector<Clip*>& nests) {
|
||||
apply_audio_effects(c, bytes_to_seconds(frame->pts, frame->channels, frame->sample_rate), frame, nb_bytes, nests);
|
||||
c->frame->pts += nb_bytes;
|
||||
c->frame_sample_index = 0;
|
||||
if (c->audio_buffer_write == 0) c->audio_buffer_write = get_buffer_offset_from_frame(sequence, qMax(timeline_in, c->audio_target_frame));
|
||||
if (c->audio_buffer_write == 0) {
|
||||
c->audio_buffer_write = get_buffer_offset_from_frame(sequence, qMax(timeline_in, c->audio_target_frame));
|
||||
}
|
||||
int offset = audio_ibuffer_read - c->audio_buffer_write;
|
||||
if (offset > 0) {
|
||||
c->audio_buffer_write += offset;
|
||||
@@ -361,6 +363,10 @@ void cache_audio_worker(Clip* c, bool scrubbing, QVector<Clip*>& nests) {
|
||||
long buffer_timeline_out = get_buffer_offset_from_frame(sequence, timeline_out);
|
||||
audio_write_lock.lock();
|
||||
|
||||
dout << "starting fsi:" << c->frame_sample_index << "abw:" << c->audio_buffer_write;
|
||||
|
||||
|
||||
|
||||
while (c->frame_sample_index < nb_bytes
|
||||
&& c->audio_buffer_write < audio_ibuffer_read+(audio_ibuffer_size>>1)
|
||||
&& c->audio_buffer_write < buffer_timeline_out) {
|
||||
@@ -403,6 +409,9 @@ void cache_audio_worker(Clip* c, bool scrubbing, QVector<Clip*>& nests) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QMetaObject::invokeMethod(panel_footage_viewer, "play_wake", Qt::QueuedConnection);
|
||||
QMetaObject::invokeMethod(panel_sequence_viewer, "play_wake", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void cache_video_worker(Clip* c, long playhead) {
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
#include <QMessageBox>
|
||||
#include <QFileInfo>
|
||||
#include <QDebug>
|
||||
#include <QDesktopServices>
|
||||
#include <QDir>
|
||||
#include <QProcess>
|
||||
|
||||
SourceTable::SourceTable(QWidget* parent) : QTreeWidget(parent) {
|
||||
editing_item = NULL;
|
||||
@@ -29,6 +32,8 @@ SourceTable::SourceTable(QWidget* parent) : QTreeWidget(parent) {
|
||||
connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(show_context_menu()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SourceTable::show_context_menu() {
|
||||
QMenu menu(this);
|
||||
|
||||
@@ -45,6 +50,15 @@ void SourceTable::show_context_menu() {
|
||||
if (type == MEDIA_TYPE_FOOTAGE) {
|
||||
QAction* replace_action = menu.addAction("Replace/Relink Media");
|
||||
connect(replace_action, SIGNAL(triggered(bool)), panel_project, SLOT(replace_selected_file()));
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
QAction* reveal_in_explorer = menu.addAction("Reveal in Explorer");
|
||||
#elif defined(Q_OS_MAC)
|
||||
QAction* reveal_in_explorer = menu.addAction("Reveal in Finder");
|
||||
#else
|
||||
QAction* reveal_in_explorer = menu.addAction("Reveal in File Manager");
|
||||
#endif
|
||||
connect(reveal_in_explorer, SIGNAL(triggered(bool)), this, SLOT(reveal_in_browser()));
|
||||
}
|
||||
if (type != MEDIA_TYPE_FOLDER) {
|
||||
QAction* replace_clip_media = menu.addAction("Replace Clips Using This Media");
|
||||
@@ -114,6 +128,29 @@ void SourceTable::create_seq_from_selected() {
|
||||
}
|
||||
}
|
||||
|
||||
void SourceTable::reveal_in_browser() {
|
||||
Media* m = get_footage_from_tree(selectedItems().at(0));
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
QStringList args;
|
||||
args << "/select," << QDir::toNativeSeparators(m->url);
|
||||
QProcess::startDetached("explorer", args);
|
||||
#elif defined(Q_OS_MAC)
|
||||
QStringList args;
|
||||
args << "-e";
|
||||
args << "tell application \"Finder\"";
|
||||
args << "-e";
|
||||
args << "activate";
|
||||
args << "-e";
|
||||
args << "select POSIX file \""+m->url+"\"";
|
||||
args << "-e";
|
||||
args << "end tell";
|
||||
QProcess::startDetached("osascript", args);
|
||||
#else
|
||||
QDesktopServices::openUrl(QUrl::fromLocalFile(m->url.left(m->url.lastIndexOf('/'))));
|
||||
#endif
|
||||
}
|
||||
|
||||
void SourceTable::item_renamed(QTreeWidgetItem* item) {
|
||||
if (editing_item == item) {
|
||||
MediaRename* mr = new MediaRename();
|
||||
|
||||
@@ -29,6 +29,7 @@ private slots:
|
||||
void item_renamed(QTreeWidgetItem *item);
|
||||
void show_context_menu();
|
||||
void create_seq_from_selected();
|
||||
void reveal_in_browser();
|
||||
};
|
||||
|
||||
#endif // SOURCETABLE_H
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
#include "project/undo.h"
|
||||
#include "panels/viewer.h"
|
||||
#include "io/config.h"
|
||||
#include "debug.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QMouseEvent>
|
||||
#include <QDebug>
|
||||
#include <QScrollArea>
|
||||
#include <QtMath>
|
||||
|
||||
@@ -82,6 +82,9 @@ void TimelineHeader::set_out_point(long new_out) {
|
||||
} else if (new_in > new_out) {
|
||||
new_in = 0;
|
||||
}
|
||||
|
||||
dout << new_in << new_out;
|
||||
|
||||
undo_stack.push(new SetTimelineInOutCommand(viewer->seq, true, new_in, new_out));
|
||||
update_parents();
|
||||
}
|
||||
|
||||
@@ -1488,7 +1488,7 @@ void TimelineWidget::update_ghosts(const QPoint& mouse_pos) {
|
||||
} else {
|
||||
s.out = s.old_out + frame_diff;
|
||||
}
|
||||
} else {
|
||||
} else if (clips_are_movable) {
|
||||
for (int i=0;i<sequence->selections.size();i++) {
|
||||
Selection& s = sequence->selections[i];
|
||||
s.in = s.old_in + frame_diff;
|
||||
|
||||
@@ -235,6 +235,8 @@ GLuint ViewerWidget::compose_sequence(QVector<Clip*>& nests, bool render_audio)
|
||||
}
|
||||
}
|
||||
|
||||
int audio_track_count = 0;
|
||||
|
||||
QVector<Clip*> current_clips;
|
||||
|
||||
for (int i=0;i<s->clips.size();i++) {
|
||||
@@ -258,6 +260,7 @@ GLuint ViewerWidget::compose_sequence(QVector<Clip*>& nests, bool render_audio)
|
||||
open_clip(c, !rendering);
|
||||
}
|
||||
clip_is_active = true;
|
||||
if (c->track >= 0) audio_track_count++;
|
||||
} else if (c->open) {
|
||||
close_clip(c);
|
||||
}
|
||||
@@ -486,6 +489,10 @@ GLuint ViewerWidget::compose_sequence(QVector<Clip*>& nests, bool render_audio)
|
||||
}
|
||||
}
|
||||
|
||||
if (audio_track_count == 0) {
|
||||
viewer->play_wake();
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
if (!nests.isEmpty() && nests.last()->fbo != NULL) {
|
||||
|
||||
Reference in New Issue
Block a user