Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

render duration of intro & outro ranges on overview waveforms #2089

Merged
merged 8 commits into from
May 5, 2019
6 changes: 5 additions & 1 deletion res/skins/Deere/deck_overview.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,16 @@
<EndControl>intro_end_position</EndControl>
<Color>#0000FF</Color>
<VisibilityControl>[Skin],show_intro_outro_cues</VisibilityControl>
<DurationTextColor>#ffffff</DurationTextColor>
<DurationTextLocation>after</DurationTextLocation>
</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>
<DurationTextLocation>before</DurationTextLocation>
</MarkRange>
<Mark>
<Control>intro_start_position</Control>
Expand All @@ -67,7 +71,7 @@
<Mark>
<Control>outro_start_position</Control>
<Text>&#9699;</Text>
<Align>top|left</Align>
<Align>top|right</Align>
<Color>#0000FF</Color>
<TextColor>#FFFFFF</TextColor>
<VisibilityControl>[Skin],show_intro_outro_cues</VisibilityControl>
Expand Down
4 changes: 4 additions & 0 deletions res/skins/LateNight/deck_overview.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,16 @@
<EndControl>intro_end_position</EndControl>
<Color>#0000FF</Color>
<VisibilityControl>[Skin],show_intro_outro_cues</VisibilityControl>
<DurationTextColor>#ffffff</DurationTextColor>
<DurationTextLocation>after</DurationTextLocation>
</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>
<DurationTextLocation>before</DurationTextLocation>
</MarkRange>
<Mark>
<Control>intro_start_position</Control>
Expand Down
4 changes: 4 additions & 0 deletions res/skins/Shade/deck_overview.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,16 @@
<EndControl>intro_end_position</EndControl>
<Color>#0000FF</Color>
<VisibilityControl>[Skin],show_intro_outro_cues</VisibilityControl>
<DurationTextColor>#ffffff</DurationTextColor>
<DurationTextLocation>after</DurationTextLocation>
</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>
<DurationTextLocation>before</DurationTextLocation>
</MarkRange>
<Mark>
<Control>intro_start_position</Control>
Expand Down
4 changes: 4 additions & 0 deletions res/skins/Tango/deck_overview.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,16 @@ Variables:
<EndControl>intro_end_position</EndControl>
<Color>#0000FF</Color>
<VisibilityControl>[Skin],show_intro_outro_cues</VisibilityControl>
<DurationTextColor>#ffffff</DurationTextColor>
<DurationTextLocation>after</DurationTextLocation>
</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>
<DurationTextLocation>before</DurationTextLocation>
</MarkRange>
<Mark>
<Control>intro_start_position</Control>
Expand Down
12 changes: 6 additions & 6 deletions src/test/durationutiltest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,13 @@ TEST_F(DurationUtilTest, FormatSecondsNegative) {
}

TEST_F(DurationUtilTest, formatTime) {
formatTime("00:00.000", 0);
formatTime("00:01.000", 1);
formatTime("00:59.000", 59);
formatTime("01:00.000", 60);
formatTime("01:01.123", 61.1234);
formatTime("0:00.000", 0);
formatTime("0:01.000", 1);
formatTime("0:59.000", 59);
formatTime("1:00.000", 60);
formatTime("1:01.123", 61.1234);
formatTime("59:59.999", 3599.999);
formatTime("01:00:00.000", 3600);
formatTime("1:00:00.000", 3600);
formatTime("23:59:59.000", 24 * 3600 - 1);
formatTime("24:00:00.000", 24 * 3600);
formatTime("24:00:01.000", 24 * 3600 + 1);
Expand Down
4 changes: 4 additions & 0 deletions src/util/duration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ QString DurationBase::formatTime(double dSeconds, Precision precision) {
if (days > 0) {
durationString = QString("%1:").arg(days * 24 + t.hour()) % durationString;
}
// remove leading 0
if (durationString.at(0) == "0" && durationString.at(1) != ":") {
durationString = durationString.right(durationString.length() - 1);
}

// The format string gives us milliseconds but we want
// centiseconds. Slice one character off.
Expand Down
14 changes: 13 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 @@ -51,6 +52,13 @@ WaveformMarkRange::WaveformMarkRange(
ConfigKey key = ConfigKey::parseCommaSeparated(visibilityControl);
m_markVisibleControl = std::make_unique<ControlProxy>(key);
}

QString durationTextLocation = context.selectString(node, "DurationTextLocation");
if (durationTextLocation == "before") {
m_durationTextLocation = DurationTextLocation::Before;
} else {
m_durationTextLocation = DurationTextLocation::After;
}
}

bool WaveformMarkRange::active() const {
Expand Down Expand Up @@ -87,6 +95,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
14 changes: 14 additions & 0 deletions src/waveform/renderers/waveformmarkrange.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,17 @@ class WaveformMarkRange {
// Returns end value or -1 if the end control doesn't exist.
double end() const;

bool showDuration() const;

enum class DurationTextLocation {
Before = 0,
After = 1
};

DurationTextLocation durationTextLocation() const {
return m_durationTextLocation;
}

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

Expand All @@ -46,10 +57,13 @@ class WaveformMarkRange {

QColor m_activeColor;
QColor m_disabledColor;
QColor m_durationTextColor;

QImage m_activeImage;
QImage m_disabledImage;

DurationTextLocation m_durationTextLocation;

friend class WaveformRenderMarkRange;
friend class WOverview;
};
67 changes: 52 additions & 15 deletions src/widget/woverview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@

#include "control/controlobject.h"
#include "control/controlproxy.h"
#include "engine/engine.h"
#include "mixer/playermanager.h"
#include "woverview.h"
#include "wskincolor.h"
#include "widget/controlwidgetconnection.h"
#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 @@ -60,6 +62,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 @@ -272,6 +281,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 @@ -440,15 +453,19 @@ void WOverview::paintEvent(QPaintEvent * /*unused*/) {
const float offset = 1.0f;
const float gain = static_cast<float>(length() - 2) / trackSamples;

// Draw markers (Cue & hotcues)
QFont markerFont = painter.font();
markerFont.setPixelSize(10 * m_scaleFactor);

QFont shadowFont = painter.font();
shadowFont.setWeight(99);
shadowFont.setPixelSize(10 * m_scaleFactor);

painter.setOpacity(0.9);

// 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()) {
if (!markRange.active() || !markRange.visible()) {
continue;
}

Expand Down Expand Up @@ -482,17 +499,37 @@ void WOverview::paintEvent(QPaintEvent * /*unused*/) {
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);
// 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() / mixxx::kEngineChannelCount / rateRatio);

QFontMetrics fm(painter.font());
int textWidth = fm.width(duration);
float padding = 3.0;
float x;

WaveformMarkRange::DurationTextLocation textLocation = markRange.durationTextLocation();
if (textLocation == WaveformMarkRange::DurationTextLocation::Before) {
x = startPosition - textWidth - padding;
} else {
x = endPosition + padding;
}

QFont shadowFont = painter.font();
shadowFont.setWeight(99);
shadowFont.setPixelSize(10 * m_scaleFactor);
// Ensure the right end of the text does not get cut off by
// the end of the track
if (x + textWidth > width()) {
x = width() - textWidth;
}

painter.setOpacity(0.9);
painter.setOpacity(1.0);
painter.setPen(markRange.m_durationTextColor);
painter.drawText(QPointF(x, fm.ascent()), duration);
}
}

for (const auto& currentMark: m_marks) {
const WaveformMarkProperties& markProperties = currentMark->getProperties();
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