Skip to content

Commit

Permalink
render duration of intro & outro ranges on overview waveforms
Browse files Browse the repository at this point in the history
MarkRange elements in skins only have their durations rendered if they
specify a DurationTextColor. This avoids rendering the durations of
loops on the overview waveform.
  • Loading branch information
Be-ing committed Apr 23, 2019
1 parent 6b36e82 commit 5161968
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 45 deletions.
2 changes: 2 additions & 0 deletions res/skins/Deere/deck_overview.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,14 @@
<EndControl>intro_end_position</EndControl>
<Color>#0000FF</Color>
<VisibilityControl>[Skin],show_intro_outro_cues</VisibilityControl>
<DurationTextColor>#ffffff</DurationTextColor>
</MarkRange>
<MarkRange>
<StartControl>outro_start_position</StartControl>
<EndControl>outro_end_position</EndControl>
<Color>#0000FF</Color>
<VisibilityControl>[Skin],show_intro_outro_cues</VisibilityControl>
<DurationTextColor>#ffffff</DurationTextColor>
</MarkRange>
<Mark>
<Control>intro_start_position</Control>
Expand Down
2 changes: 2 additions & 0 deletions res/skins/LateNight/deck_overview.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,14 @@
<EndControl>intro_end_position</EndControl>
<Color>#0000FF</Color>
<VisibilityControl>[Skin],show_intro_outro_cues</VisibilityControl>
<DurationTextColor>#ffffff</DurationTextColor>
</MarkRange>
<MarkRange>
<StartControl>outro_start_position</StartControl>
<EndControl>outro_end_position</EndControl>
<Color>#0000FF</Color>
<VisibilityControl>[Skin],show_intro_outro_cues</VisibilityControl>
<DurationTextColor>#ffffff</DurationTextColor>
</MarkRange>
<Mark>
<Control>intro_start_position</Control>
Expand Down
2 changes: 2 additions & 0 deletions res/skins/Shade/deck_overview.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,14 @@
<EndControl>intro_end_position</EndControl>
<Color>#0000FF</Color>
<VisibilityControl>[Skin],show_intro_outro_cues</VisibilityControl>
<DurationTextColor>#ffffff</DurationTextColor>
</MarkRange>
<MarkRange>
<StartControl>outro_start_position</StartControl>
<EndControl>outro_end_position</EndControl>
<Color>#0000FF</Color>
<VisibilityControl>[Skin],show_intro_outro_cues</VisibilityControl>
<DurationTextColor>#ffffff</DurationTextColor>
</MarkRange>
<Mark>
<Control>intro_start_position</Control>
Expand Down
2 changes: 2 additions & 0 deletions res/skins/Tango/deck_overview.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,14 @@ Variables:
<EndControl>intro_end_position</EndControl>
<Color>#0000FF</Color>
<VisibilityControl>[Skin],show_intro_outro_cues</VisibilityControl>
<DurationTextColor>#ffffff</DurationTextColor>
</MarkRange>
<MarkRange>
<StartControl>outro_start_position</StartControl>
<EndControl>outro_end_position</EndControl>
<Color>#0000FF</Color>
<VisibilityControl>[Skin],show_intro_outro_cues</VisibilityControl>
<DurationTextColor>#ffffff</DurationTextColor>
</MarkRange>
<Mark>
<Control>intro_start_position</Control>
Expand Down
7 changes: 6 additions & 1 deletion src/waveform/renderers/waveformmarkrange.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ WaveformMarkRange::WaveformMarkRange(
const SkinContext& context,
const WaveformSignalColors& signalColors)
: m_activeColor(context.selectString(node, "Color")),
m_disabledColor(context.selectString(node, "DisabledColor")) {
m_disabledColor(context.selectString(node, "DisabledColor")),
m_durationTextColor(context.selectString(node, "DurationTextColor")) {
if (!m_activeColor.isValid()) {
//vRince kind of legacy fallback ...
// As a fallback, grab the mark color from the parent's MarkerColor
Expand Down Expand Up @@ -87,6 +88,10 @@ double WaveformMarkRange::end() const {
return end;
}

bool WaveformMarkRange::showDuration() const {
return m_durationTextColor.isValid() && start() != end() && start() != -1 && end() != -1;
}

void WaveformMarkRange::generateImage(int weidth, int height) {
m_activeImage = QImage(weidth, height, QImage::Format_ARGB32_Premultiplied);
m_disabledImage = QImage(weidth, height, QImage::Format_ARGB32_Premultiplied);
Expand Down
3 changes: 3 additions & 0 deletions src/waveform/renderers/waveformmarkrange.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class WaveformMarkRange {
// Returns end value or -1 if the end control doesn't exist.
double end() const;

bool showDuration() const;

private:
void generateImage(int weidth, int height);

Expand All @@ -46,6 +48,7 @@ class WaveformMarkRange {

QColor m_activeColor;
QColor m_disabledColor;
QColor m_durationTextColor;

QImage m_activeImage;
QImage m_disabledImage;
Expand Down
115 changes: 71 additions & 44 deletions src/widget/woverview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "track/track.h"
#include "analyzer/analyzerprogress.h"
#include "util/color/color.h"
#include "util/duration.h"
#include "util/math.h"
#include "util/timer.h"
#include "util/dnd.h"
Expand Down Expand Up @@ -59,6 +60,13 @@ WOverview::WOverview(
m_endOfTrackControl = new ControlProxy(
m_group, "end_of_track", this);
m_endOfTrackControl->connectValueChanged(this, &WOverview::onEndOfTrackChange);
m_pRateDirControl = new ControlProxy(m_group, "rate_dir", this);
m_pRateRangeControl = new ControlProxy(m_group, "rateRange", this);
m_pRateSliderControl = new ControlProxy(m_group, "rate", this);
// Needed to recalculate range durations when rate slider is moved without the deck playing
// TODO: connect to rate_ratio instead in PR #1765
m_pRateSliderControl->connectValueChanged(this, &WOverview::onRateSliderChange);
m_trackSampleRateControl = new ControlProxy(m_group, "track_samplerate", this);
m_trackSamplesControl =
new ControlProxy(m_group, "track_samples", this);
setAcceptDrops(true);
Expand Down Expand Up @@ -271,6 +279,10 @@ void WOverview::onMarkRangeChange(double /*v*/) {
update();
}

void WOverview::onRateSliderChange(double /*v*/) {
update();
}

// currently only updates the mark color but it could be easily extended.
void WOverview::updateCues(const QList<CuePointer> &loadedCues) {
for (CuePointer currentCue: loadedCues) {
Expand Down Expand Up @@ -434,50 +446,6 @@ void WOverview::paintEvent(QPaintEvent * /*unused*/) {
const float offset = 1.0f;
const float gain = static_cast<float>(length() - 2) / trackSamples;

// Draw range (loop)
for (auto&& markRange: m_markRanges) {
// If the mark range is not active we should not draw it.
if (!markRange.active()) {
continue;
}

// If the mark range is not visible we should not draw it.
if (!markRange.visible()) {
continue;
}

// Active mark ranges by definition have starts/ends that are not
// disabled.
const double startValue = markRange.start();
const double endValue = markRange.end();

const float startPosition = offset + startValue * gain;
const float endPosition = offset + endValue * gain;

if (startPosition < 0.0 && endPosition < 0.0) {
continue;
}

if (markRange.enabled()) {
painter.setOpacity(0.4);
painter.setPen(markRange.m_activeColor);
painter.setBrush(markRange.m_activeColor);
} else {
painter.setOpacity(0.2);
painter.setPen(markRange.m_disabledColor);
painter.setBrush(markRange.m_disabledColor);
}

// let top and bottom of the rect out of the widget
if (m_orientation == Qt::Horizontal) {
painter.drawRect(QRectF(QPointF(startPosition, -2.0),
QPointF(endPosition, height() + 1.0)));
} else {
painter.drawRect(QRectF(QPointF(-2.0, startPosition),
QPointF(width() + 1.0, endPosition)));
}
}

// Draw markers (Cue & hotcues)
QFont markerFont = painter.font();
markerFont.setPixelSize(10 * m_scaleFactor);
Expand Down Expand Up @@ -565,6 +533,65 @@ void WOverview::paintEvent(QPaintEvent * /*unused*/) {
}
}

// Draw range (loop)
for (auto&& markRange: m_markRanges) {
if (!markRange.active() || !markRange.visible()) {
continue;
}

// Active mark ranges by definition have starts/ends that are not
// disabled.
const double startValue = markRange.start();
const double endValue = markRange.end();

const float startPosition = offset + startValue * gain;
const float endPosition = offset + endValue * gain;

if (startPosition < 0.0 && endPosition < 0.0) {
continue;
}

if (markRange.enabled()) {
painter.setOpacity(0.4);
painter.setPen(markRange.m_activeColor);
painter.setBrush(markRange.m_activeColor);
} else {
painter.setOpacity(0.2);
painter.setPen(markRange.m_disabledColor);
painter.setBrush(markRange.m_disabledColor);
}

// let top and bottom of the rect out of the widget
if (m_orientation == Qt::Horizontal) {
painter.drawRect(QRectF(QPointF(startPosition, -2.0),
QPointF(endPosition, height() + 1.0)));
} else {
painter.drawRect(QRectF(QPointF(-2.0, startPosition),
QPointF(width() + 1.0, endPosition)));
}

// draw duration of range
if (markRange.showDuration()) {
// TODO: replace with rate_ratio in PR #1765
double rateRatio = 1.0 + m_pRateDirControl->get() * m_pRateRangeControl->get() * m_pRateSliderControl->get();
QString duration = mixxx::Duration::formatTime((endValue - startValue)
/ m_trackSampleRateControl->get() / 2 / rateRatio);

// Ensure the right end of the text does not get cut off by
// the end of the track
QFontMetrics fm(painter.font());
int textWidth = fm.width(duration);
float x = startPosition;
if (startPosition + textWidth > width()) {
x = width() - textWidth;
}

painter.setOpacity(1.0);
painter.setPen(markRange.m_durationTextColor);
painter.drawText(QPointF(x, height() - 2.0), duration);
}
}

if (m_orientation == Qt::Vertical) {
painter.setTransform(QTransform(0, 1, 1, 0, 0, 0));
}
Expand Down
5 changes: 5 additions & 0 deletions src/widget/woverview.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ class WOverview : public WWidget, public TrackDropTarget {

void onMarkChanged(double v);
void onMarkRangeChange(double v);
void onRateSliderChange(double v);
void receiveCuesUpdated();

void slotWaveformSummaryUpdated();
Expand All @@ -113,6 +114,10 @@ class WOverview : public WWidget, public TrackDropTarget {
UserSettingsPointer m_pConfig;
ControlProxy* m_endOfTrackControl;
bool m_endOfTrack;
ControlProxy* m_pRateDirControl;
ControlProxy* m_pRateRangeControl;
ControlProxy* m_pRateSliderControl;
ControlProxy* m_trackSampleRateControl;
ControlProxy* m_trackSamplesControl;

// Current active track
Expand Down

0 comments on commit 5161968

Please sign in to comment.