Skip to content

Commit

Permalink
WIP track muting
Browse files Browse the repository at this point in the history
  • Loading branch information
darbyjohnston committed Jan 6, 2025
1 parent 96a895c commit 4f6094d
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 85 deletions.
156 changes: 81 additions & 75 deletions lib/tlTimeline/TimelinePrivate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,62 +175,65 @@ namespace tl
{
for (const auto& otioTrack : thread.otioTimeline->video_tracks())
{
for (const auto& otioChild : otioTrack->children())
if (otioTrack->enabled())
{
if (auto otioItem = dynamic_cast<otio::Item*>(otioChild.value))
for (const auto& otioChild : otioTrack->children())
{
const auto requestTime = request->time - timeRange.start_time();
otio::ErrorStatus errorStatus;
const auto range = otioItem->trimmed_range_in_parent(&errorStatus);
if (range.has_value() && range.value().contains(requestTime))
if (auto otioItem = dynamic_cast<otio::Item*>(otioChild.value))
{
VideoLayerData videoData;
try
const auto requestTime = request->time - timeRange.start_time();
otio::ErrorStatus errorStatus;
const auto range = otioItem->trimmed_range_in_parent(&errorStatus);
if (range.has_value() && range.value().contains(requestTime))
{
if (auto otioClip = dynamic_cast<const otio::Clip*>(otioItem))
{
videoData.image = readVideo(otioClip, requestTime, request->options);
}
const auto neighbors = otioTrack->neighbors_of(otioItem, &errorStatus);
if (auto otioTransition = dynamic_cast<otio::Transition*>(neighbors.second.value))
VideoLayerData videoData;
try
{
if (requestTime > range.value().end_time_inclusive() - otioTransition->in_offset())
if (auto otioClip = dynamic_cast<const otio::Clip*>(otioItem))
{
videoData.transition = toTransition(otioTransition->transition_type());
videoData.transitionValue = transitionValue(
requestTime.value(),
range.value().end_time_inclusive().value() - otioTransition->in_offset().value(),
range.value().end_time_inclusive().value() + otioTransition->out_offset().value() + 1.0);
const auto transitionNeighbors = otioTrack->neighbors_of(otioTransition, &errorStatus);
if (const auto otioClipB = dynamic_cast<otio::Clip*>(transitionNeighbors.second.value))
videoData.image = readVideo(otioClip, requestTime, request->options);
}
const auto neighbors = otioTrack->neighbors_of(otioItem, &errorStatus);
if (auto otioTransition = dynamic_cast<otio::Transition*>(neighbors.second.value))
{
if (requestTime > range.value().end_time_inclusive() - otioTransition->in_offset())
{
videoData.imageB = readVideo(otioClipB, requestTime, request->options);
videoData.transition = toTransition(otioTransition->transition_type());
videoData.transitionValue = transitionValue(
requestTime.value(),
range.value().end_time_inclusive().value() - otioTransition->in_offset().value(),
range.value().end_time_inclusive().value() + otioTransition->out_offset().value() + 1.0);
const auto transitionNeighbors = otioTrack->neighbors_of(otioTransition, &errorStatus);
if (const auto otioClipB = dynamic_cast<otio::Clip*>(transitionNeighbors.second.value))
{
videoData.imageB = readVideo(otioClipB, requestTime, request->options);
}
}
}
}
if (auto otioTransition = dynamic_cast<otio::Transition*>(neighbors.first.value))
{
if (requestTime < range.value().start_time() + otioTransition->out_offset())
if (auto otioTransition = dynamic_cast<otio::Transition*>(neighbors.first.value))
{
std::swap(videoData.image, videoData.imageB);
videoData.transition = toTransition(otioTransition->transition_type());
videoData.transitionValue = transitionValue(
requestTime.value(),
range.value().start_time().value() - otioTransition->in_offset().value() - 1.0,
range.value().start_time().value() + otioTransition->out_offset().value());
const auto transitionNeighbors = otioTrack->neighbors_of(otioTransition, &errorStatus);
if (const auto otioClipB = dynamic_cast<otio::Clip*>(transitionNeighbors.first.value))
if (requestTime < range.value().start_time() + otioTransition->out_offset())
{
videoData.image = readVideo(otioClipB, requestTime, request->options);
std::swap(videoData.image, videoData.imageB);
videoData.transition = toTransition(otioTransition->transition_type());
videoData.transitionValue = transitionValue(
requestTime.value(),
range.value().start_time().value() - otioTransition->in_offset().value() - 1.0,
range.value().start_time().value() + otioTransition->out_offset().value());
const auto transitionNeighbors = otioTrack->neighbors_of(otioTransition, &errorStatus);
if (const auto otioClipB = dynamic_cast<otio::Clip*>(transitionNeighbors.first.value))
{
videoData.image = readVideo(otioClipB, requestTime, request->options);
}
}
}
}
catch (const std::exception&)
{
//! \todo How should this be handled?
}
request->layerData.push_back(std::move(videoData));
}
catch (const std::exception&)
{
//! \todo How should this be handled?
}
request->layerData.push_back(std::move(videoData));
}
}
}
Expand All @@ -244,46 +247,49 @@ namespace tl
{
for (const auto& otioTrack : thread.otioTimeline->audio_tracks())
{
for (const auto& otioChild : otioTrack->children())
if (otioTrack->enabled())
{
if (auto otioClip = dynamic_cast<otio::Clip*>(otioChild.value))
for (const auto& otioChild : otioTrack->children())
{
const auto rangeOptional = otioClip->trimmed_range_in_parent();
if (rangeOptional.has_value())
if (auto otioClip = dynamic_cast<otio::Clip*>(otioChild.value))
{
const otime::TimeRange clipTimeRange(
rangeOptional.value().start_time().rescaled_to(1.0),
rangeOptional.value().duration().rescaled_to(1.0));
const double start = request->seconds -
timeRange.start_time().rescaled_to(1.0).value();
const otime::TimeRange requestTimeRange = otime::TimeRange(
otime::RationalTime(start, 1.0),
otime::RationalTime(1.0, 1.0));
if (requestTimeRange.intersects(clipTimeRange))
const auto rangeOptional = otioClip->trimmed_range_in_parent();
if (rangeOptional.has_value())
{
AudioLayerData audioData;
audioData.seconds = request->seconds;
try
{
//! \bug Why is otime::TimeRange::clamped() not giving us the
//! result we expect?
//audioData.timeRange = requestTimeRange.clamped(clipTimeRange);
const double start = std::max(
clipTimeRange.start_time().value(),
requestTimeRange.start_time().value());
const double end = std::min(
clipTimeRange.start_time().value() + clipTimeRange.duration().value(),
requestTimeRange.start_time().value() + requestTimeRange.duration().value());
audioData.timeRange = otime::TimeRange(
otime::RationalTime(start, 1.0),
otime::RationalTime(end - start, 1.0));
audioData.audio = readAudio(otioClip, audioData.timeRange, request->options);
}
catch (const std::exception&)
const otime::TimeRange clipTimeRange(
rangeOptional.value().start_time().rescaled_to(1.0),
rangeOptional.value().duration().rescaled_to(1.0));
const double start = request->seconds -
timeRange.start_time().rescaled_to(1.0).value();
const otime::TimeRange requestTimeRange = otime::TimeRange(
otime::RationalTime(start, 1.0),
otime::RationalTime(1.0, 1.0));
if (requestTimeRange.intersects(clipTimeRange))
{
//! \todo How should this be handled?
AudioLayerData audioData;
audioData.seconds = request->seconds;
try
{
//! \bug Why is otime::TimeRange::clamped() not giving us the
//! result we expect?
//audioData.timeRange = requestTimeRange.clamped(clipTimeRange);
const double start = std::max(
clipTimeRange.start_time().value(),
requestTimeRange.start_time().value());
const double end = std::min(
clipTimeRange.start_time().value() + clipTimeRange.duration().value(),
requestTimeRange.start_time().value() + requestTimeRange.duration().value());
audioData.timeRange = otime::TimeRange(
otime::RationalTime(start, 1.0),
otime::RationalTime(end - start, 1.0));
audioData.audio = readAudio(otioClip, audioData.timeRange, request->options);
}
catch (const std::exception&)
{
//! \todo How should this be handled?
}
request->layerData.push_back(std::move(audioData));
}
request->layerData.push_back(std::move(audioData));
}
}
}
Expand Down
62 changes: 52 additions & 10 deletions lib/tlTimelineUI/TimelineItem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ namespace tl
window);

const auto otioTimeline = p.player->getTimeline()->getTimeline();
int stackIndex = 0;
for (const auto& child : otioTimeline->tracks()->children())
{
if (auto otioTrack = otio::dynamic_retainer_cast<otio::Track>(child))
Expand All @@ -85,6 +86,18 @@ namespace tl
}
}
track.timeRange = otioTrack->trimmed_range();
track.enabledButton = ui::ToolButton::create(
context,
shared_from_this());
track.enabledButton->setIcon("CloseSmall");
track.enabledButton->setCheckable(true);
track.enabledButton->setChecked(otioTrack->enabled());
track.enabledButton->setCheckedCallback(
[this, stackIndex](bool value)
{
_setTrackEnabled(stackIndex, value);
});
track.enabledButton->setAcceptsKeyFocus(false);
track.label = ui::Label::create(
trackLabel,
context,
Expand Down Expand Up @@ -144,6 +157,7 @@ namespace tl

p.tracks.push_back(track);
}
++stackIndex;
}

_tracksUpdate();
Expand Down Expand Up @@ -269,24 +283,34 @@ namespace tl
{
const bool visible = _isTrackVisible(track.index);

math::Size2i buttonSizeHint;
math::Size2i labelSizeHint;
math::Size2i durationSizeHint;
int trackInfoHeight = 0;
if (visible && _displayOptions.trackInfo)
{
buttonSizeHint = track.enabledButton->getSizeHint();
labelSizeHint = track.label->getSizeHint();
durationSizeHint = track.durationLabel->getSizeHint();
trackInfoHeight = std::max(
buttonSizeHint.h,
std::max(
labelSizeHint.h,
durationSizeHint.h));
}
track.label->setGeometry(math::Box2i(
track.enabledButton->setGeometry(math::Box2i(
g.min.x,
y,
y + trackInfoHeight / 2 - buttonSizeHint.h / 2,
buttonSizeHint.w,
buttonSizeHint.h));
track.label->setGeometry(math::Box2i(
g.min.x + buttonSizeHint.w + p.size.spacing,
y + trackInfoHeight / 2 - labelSizeHint.h / 2,
labelSizeHint.w,
labelSizeHint.h));
math::Size2i durationSizeHint;
if (visible && _displayOptions.trackInfo)
{
durationSizeHint = track.durationLabel->getSizeHint();
}
track.durationLabel->setGeometry(math::Box2i(
g.min.x + track.size.w - durationSizeHint.w,
y,
y + trackInfoHeight / 2 - durationSizeHint.h / 2,
durationSizeHint.w,
durationSizeHint.h));

Expand Down Expand Up @@ -338,6 +362,7 @@ namespace tl
if (displayScaleChanged || p.size.sizeInit)
{
p.size.margin = event.style->getSizeRole(ui::SizeRole::MarginInside, _displayScale);
p.size.spacing = event.style->getSizeRole(ui::SizeRole::SpacingSmall, _displayScale);
p.size.border = event.style->getSizeRole(ui::SizeRole::Border, _displayScale);
p.size.handle = event.style->getSizeRole(ui::SizeRole::Handle, _displayScale);
p.size.fontInfo = image::FontInfo(
Expand Down Expand Up @@ -369,8 +394,10 @@ namespace tl
if (_displayOptions.trackInfo)
{
track.size.h += std::max(
track.label->getSizeHint().h,
track.durationLabel->getSizeHint().h);
track.enabledButton->getSizeHint().h,
std::max(
track.label->getSizeHint().h,
track.durationLabel->getSizeHint().h));
}
tracksHeight += track.size.h;
if (minimumTrackHeightInit)
Expand Down Expand Up @@ -635,6 +662,21 @@ namespace tl
index) != _displayOptions.tracks.end();
}

void TimelineItem::_setTrackEnabled(int stackIndex, bool enabled)
{
TLRENDER_P();
auto otioTimeline = timeline::copy(p.player->getTimeline()->getTimeline().value);
const auto& children = otioTimeline->tracks()->children();
if (stackIndex >= 0 && stackIndex < children.size())
{
if (auto item = OTIO_NS::dynamic_retainer_cast<OTIO_NS::Item>(children[stackIndex]))
{
item->set_enabled(enabled);
}
}
p.player->getTimeline()->setTimeline(otioTimeline);
}

void TimelineItem::_drawInOutPoints(
const math::Box2i& drawRect,
const ui::DrawEvent& event)
Expand Down
Loading

0 comments on commit 4f6094d

Please sign in to comment.