17 #include <QApplication>
18 #include <QCoreApplication>
47 : m_xscreensaverenable(screensaverenable)
67 p->fillRect(0, 0, size.width(), size.height(),
back);
71 QFont font = QApplication::font();
75 int logicalDpiY = 100;
76 HDC hdc = GetDC(
nullptr);
79 logicalDpiY = GetDeviceCaps(hdc, LOGPIXELSY);
80 ReleaseDC(
nullptr, hdc);
87 float floatSize = (16 * 100.0F) / logicalDpiY;
92 floatSize = floatSize * hmult;
94 font.setPointSize(lroundf(floatSize));
95 font.setWeight(QFont::Bold);
96 font.setPointSizeF(fontSize * (size.width() / 800.0));
99 p->drawText(0, 0, size.width(), size.height(), Qt::AlignVCenter | Qt::AlignHCenter | Qt::TextWordWrap, warning);
107 setMax(maxscale, maxrange);
117 if (maxscale == 0 || maxrange == 0)
125 auto domain = (
long double) maxscale;
126 auto range = (
long double) maxrange;
128 long double dx = 1.0;
129 long double e4 = 1.0E-8;
132 for (
int i = 0; i < maxrange; i++)
136 for (
uint i=0; i<10000 && (std::abs(dx) > e4); i++)
139 double y = (x *
t) -
range;
140 double yy =
t - (domain / (x + domain));
146 for (
int i = 1; i < (int) domain; i++)
148 int scaled = (int) floor(0.5 + (alpha *
log((
double(i) + alpha) / alpha)));
188 for (
int i = 0; i <
m_size.width(); i++)
190 auto indexTo = (
unsigned long)(index + step);
191 if (indexTo == (
unsigned long)(index))
192 indexTo = (
unsigned long)(index + 1);
225 for (
auto s = (
unsigned long)index; s < indexTo && s < node->
m_length; s++)
227 double adjHeight =
static_cast<double>(
m_size.height()) / 4.0;
228 double tmpL = ( ( node->
m_left ?
static_cast<double>(node->
m_left[s]) : 0.) *
229 adjHeight ) / 32768.0;
230 double tmpR = ( ( node->
m_right ?
static_cast<double>(node->
m_right[s]) : 0.) *
231 adjHeight ) / 32768.0;
233 valL = (tmpL > valL) ? tmpL : valL;
235 valL = (tmpL < valL) ? tmpL : valL;
237 valR = (tmpR > valR) ? tmpR : valR;
239 valR = (tmpR < valR) ? tmpR : valR;
242 if (valL != 0. || valR != 0.)
248 index = index + step;
254 for (
int i = 0; i <
m_size.width(); i++)
280 if (valL != 0. || valR != 0.)
290 for (
int i = 0; (unsigned) i <
m_magnitudes.size(); i++ )
299 if (
back != Qt::green)
301 for (
int i = 1; i <
m_size.width(); i++ )
305 double per = (
static_cast<double>(
m_magnitudes[i]) * 2.0 ) /
306 (
static_cast<double>(
m_size.height()) / 4.0 );
336 p->setPen( QColor(
int(r), int(g), int(b) ) );
340 double adjHeight =
static_cast<double>(
m_size.height()) / 4.0;
379 p->setPen( QColor(
int(r), int(g), int(b) ) );
383 adjHeight =
static_cast<double>(
m_size.height()) * 3.0 / 4.0;
404 for (
int i = 0; i <
m_size.width(); i++)
406 auto indexTo = (
unsigned long)(index + step);
407 if (indexTo == (
unsigned long)index)
408 indexTo = (
unsigned long)(index + 1);
433 for (
auto s = (
unsigned long)index; s < indexTo && s < node->
m_length; s++)
435 double tmp = (
static_cast<double>(node->
m_left[s]) +
437 :
static_cast<double>(node->
m_left[s])) *
438 (
static_cast<double>(
m_size.height()) / 2.0 ) ) / 65536.0;
441 val = (
tmp > val) ?
tmp : val;
445 val = (
tmp < val) ?
tmp : val;
454 index = index + step;
460 for (
int i = 0; i <
m_size.width(); i++) {
480 for (
int i = 0; i <
m_size.width(); i++ )
489 if (
back != Qt::green)
491 for (
int i = 1; i <
m_size.width(); i++ ) {
493 double per = (
static_cast<double>(
m_magnitudes[i]) * 2.0 ) /
494 (
static_cast<double>(
m_size.height()) / 4.0 );
524 p->setPen(QColor(
int(r), int(g), int(b)));
528 double adjHeight =
static_cast<double>(
m_size.height()) / 2.0;
549 QString cache =
GetConfDir() +
"/MythMusic/WaveForm";
559 filename = QString(
"%1/%2.png").arg(cache)
561 LOG(VB_PLAYBACK, LOG_INFO, QString(
"WF saving to %1").arg(
filename));
564 LOG(VB_GENERAL, LOG_ERR,
565 QString(
"WF saving to %1 failed: " +
ENO).arg(
filename));
571 filename = QString(
"%1/%2.png").arg(cache).arg(stream ? 0 : meta->
ID());
572 LOG(VB_PLAYBACK, LOG_INFO, QString(
"WF loading from %1").arg(
filename));
575 LOG(VB_GENERAL, LOG_WARNING,
576 QString(
"WF loading %1 failed, recreating").arg(
filename));
595 m_font = QApplication::font();
646 LOG(VB_PLAYBACK, LOG_DEBUG,
647 QString(
"WF process %1 samples at %2, display=%3").
648 arg(n).arg(
m_offset).arg(displayed));
653 for (
uint i = 0; i < n; i++)
655 short int val = node->
m_left[i];
691 LOG(VB_PLAYBACK, LOG_DEBUG,
692 QString(
"WF painting at %1,%2/%3").arg(x).arg(y).arg(yr));
694 painter.setPen(qRgb(0, 0, 0));
699 painter.setPen(qRgb(25, 25, 150));
700 painter.drawLine(x, y - h *
m_maxl / 32768,
701 x, y - h *
m_minl / 32768);
704 painter.drawLine(x, yr - h *
m_maxr / 32768,
705 x, yr - h *
m_minr / 32768);
707 painter.setPen(qRgb(150, 25, 25));
709 painter.drawLine(x, y - rmsl, x, y + rmsl);
713 painter.drawLine(x, yr - rmsr, x, yr + rmsr);
733 p->fillRect(0, 0, 0, 0,
back);
737 Qt::IgnoreAspectRatio,
738 Qt::SmoothTransformation));
743 p->setPen(Qt::yellow);
745 p->drawLine(x, 0, x,
m_size.height());
749 p->setPen(Qt::white);
751 QRect text(5, 5,
m_size.width() - 10,
m_size.height() - 10);
752 p->drawText(text, Qt::AlignTop | Qt::AlignLeft,
755 .arg(
m_offset / 1000 % 60, 2, 10, QChar(
'0')));
756 p->drawText(text, Qt::AlignTop | Qt::AlignRight,
759 .arg(
m_duration / 1000 % 60, 2, 10, QChar(
'0')));
760 p->drawText(text, Qt::AlignBottom | Qt::AlignLeft,
761 QString(
"%1 lines/s")
763 p->drawText(text, Qt::AlignBottom | Qt::AlignRight,
764 QString(
"%1 ms/line")
772 LOG(VB_PLAYBACK, LOG_INFO, QString(
"WF keypress = %1").arg(
action));
788 const QString &
name(
void)
const override
790 static QString s_name = QCoreApplication::translate(
"Visualizers",
814 const QString &
name(
void)
const override
816 static QString s_name = QCoreApplication::translate(
"Visualizers",
839 const QString &
name(
void)
const override
841 static QString s_name = QCoreApplication::translate(
"Visualizers",
865 LOG(VB_GENERAL, LOG_INFO, QString(
"Spectrum : Being Initialised"));
869 m_dftL =
static_cast<FFTComplex*
>(av_malloc(
sizeof(FFTComplex) *
FFTW_N));
870 m_dftR =
static_cast<FFTComplex*
>(av_malloc(
sizeof(FFTComplex) *
FFTW_N));
918 template<
typename T> T
sq(T a) {
return a*a; };
929 QRect *rectsp =
m_rects.data();
937 for (
unsigned long k = 0; k < node->
m_length; k++)
939 m_dftL[k] = (FFTComplex){ .re = (FFTSample)node->
m_left[k], .im = 0 };
941 m_dftR[k] = (FFTComplex){ .re = (FFTSample)node->
m_right[k], .im = 0 };
945 for (
auto k = i; k <
FFTW_N; k++)
947 m_dftL[k] = (FFTComplex){ .re = 0, .im = 0 };
948 m_dftL[k] = (FFTComplex){ .re = 0, .im = 0 };
969 double adjHeight =
static_cast<double>(
m_size.height()) / 2.0;
970 if (magL > adjHeight)
974 if (magL < magnitudesp[i])
988 if (magR > adjHeight)
1006 if (magR != 1 || magL != 1)
1011 magnitudesp[i] = magL;
1013 rectsp[i].setTop(
m_size.height() / 2 - int( magL ) );
1014 rectsp[i].setBottom(
m_size.height() / 2 + int( magR ) );
1040 QRect *rectsp =
m_rects.data();
1045 double per = double( rectsp[i].height() - 2 ) / double(
m_size.height() );
1047 per =
clamp(per, 1.0, 0.0);
1056 r =
clamp(r, 255.0, 0.0);
1057 g =
clamp(g, 255.0, 0.0);
1058 b =
clamp(b, 255.0, 0.0);
1060 if(rectsp[i].height() > 4)
1061 p->fillRect(rectsp[i], QColor(
int(r),
int(g),
int(b)));
1070 const QString &
name(
void)
const override
1072 static QString s_name = QCoreApplication::translate(
"Visualizers",
1109 int x = ((i / 2) * w) + correction;
1123 per =
clamp(per, 1.0, 0.0);
1132 r =
clamp(r, 255.0, 0.0);
1133 g =
clamp(g, 255.0, 0.0);
1134 b =
clamp(b, 255.0, 0.0);
1136 p->fillRect (x, y, w, h, QColor (
int(r),
int(g),
int(b)));
1146 QRect *rectsp =
m_rects.data();
1148 drawRect(
p, &(rectsp[i]), i, center, w, h);
1156 const QString &
name(
void)
const override
1158 static QString s_name = QCoreApplication::translate(
"Visualizers",
1181 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Piano : Being Initialised"));
1186 double sample_rate = 44100.0;
1190 double concert_A = 440.0;
1191 double semi_tone = pow(2.0, 1.0/12.0);
1194 double bottom_A = concert_A / 2.0 / 2.0 / 2.0 / 2.0;
1196 double current_freq = bottom_A;
1203 double samples_required = sample_rate/current_freq * 20.0;
1204 if (samples_required > sample_rate/4.0)
1207 samples_required = sample_rate/4.0;
1209 if (samples_required < sample_rate/(
double)
m_fps * 0.75)
1211 samples_required = sample_rate/(double)
m_fps * 0.75;
1216 current_freq *= semi_tone;
1256 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Piano : Being Resized"));
1261 double key_unit_size = (double)
m_size.width() / 54.0;
1262 if (key_unit_size < 10.0)
1263 key_unit_size = 10.0;
1265 double white_width_pct = .8;
1266 double black_width_pct = .6;
1267 double black_offset_pct = .05;
1269 double white_height_pct = 6;
1270 double black_height_pct = 4;
1274 double left = (double)
m_size.width() / 2.0 - (4.0*7.0 + 3.5) * key_unit_size;
1275 double top_of_keys = (double)
m_size.height() / 2.0 - key_unit_size * white_height_pct / 2.0;
1281 int note = ((int)key - 3 + 12) % 12;
1284 left += key_unit_size*7.0;
1287 double center = 0.0;
1288 double offset = 0.0;
1289 bool is_black =
false;
1293 case 0: center = 0.5;
break;
1294 case 1: center = 1.0; is_black =
true; offset = -1;
break;
1295 case 2: center = 1.5;
break;
1296 case 3: center = 2.0; is_black =
true; offset = +1;
break;
1297 case 4: center = 2.5;
break;
1298 case 5: center = 3.5;
break;
1299 case 6: center = 4.0; is_black =
true; offset = -2;
break;
1300 case 7: center = 4.5;
break;
1301 case 8: center = 5.0; is_black =
true; offset = 0;
break;
1302 case 9: center = 5.5;
break;
1303 case 10: center = 6.0; is_black =
true; offset = 2;
break;
1304 case 11: center = 6.5;
break;
1308 double width = (is_black ? black_width_pct:white_width_pct) * key_unit_size;
1309 double height = (is_black? black_height_pct:white_height_pct) * key_unit_size;
1312 left + center * key_unit_size
1314 + (is_black ? (offset * black_offset_pct * key_unit_size):0.0),
1356 bool allZero =
true;
1366 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Piano : Node offset=%1 too far backwards : NEW SONG").arg(node->
m_offset.count()));
1373 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Piano : Already seen node offset=%1, returning without processing").arg(node->
m_offset.count()));
1382 for (
uint i = 0; i < n; i++)
1389 for (
uint i = 0; i < n; i++)
1397 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Hit an empty node, and returning empty-handed"));
1407 for (
uint i = 0; i < n; i++)
1421 if (n_samples >
m_pianoData[key].samples_process_before_display_update)
1437 if(magnitude_av > 0.0F)
1439 magnitude_av =
log(magnitude_av);
1447 if (magnitude_av < 0.0F)
1459 if (
m_pianoData[key].max_magnitude_seen < magnitude_av)
1463 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Piano : Updated Key %1 from %2 samples, magnitude=%3")
1464 .arg(key).arg(n_samples).arg(magnitude_av));
1498 QRect *rectsp = (
m_rects).data();
1511 for (
uint key = 0; key < n; key++)
1513 if (
m_pianoData[key].max_magnitude_seen <
static_cast<float>(mag))
1528 for (
int key_i = n - 1; key_i >= 0; key_i--)
1531 if (
m_pianoData[key].max_magnitude_seen <
static_cast<float>(mag))
1547 for (
uint key = 0; key < n; key++)
1550 if (magnitude_max < mag)
1551 magnitude_max = mag;
1553 magnitudep[key] = mag;
1557 for (
uint key = 0; key < n; key++)
1562 double per = magnitudep[key] / magnitude_max;
1563 per =
clamp(per, 1.0, 0.0);
1567 LOG(VB_GENERAL, LOG_DEBUG, QString(
"Piano : Display key %1, magnitude=%2, seen=%3")
1568 .arg(key).arg(per*100.0).arg(
m_pianoData[key].max_magnitude_seen));
1574 p->fillRect(rectsp[key], QColor(
int(r), int(g), int(b)));
1578 for (
uint key = 0; key < n; key++)
1583 double per = magnitudep[key]/magnitude_max;
1584 per =
clamp(per, 1.0, 0.0);
1593 p->fillRect(rectsp[key], QColor(
int(r), int(g), int(b)));
1602 const QString &
name(
void)
const override
1604 static QString s_name = QCoreApplication::translate(
"Visualizers",
1622 m_lastCycle(QDateTime::currentDateTime())
1747 if (imageFilename.startsWith(
"myth://"))
1749 auto *rf =
new RemoteFile(imageFilename,
false,
false, 0ms);
1752 bool ret = rf->SaveAs(data);
1757 art.loadFromData(data);
1760 if (!imageFilename.isEmpty())
1761 art.load(imageFilename);
1770 m_image = art.scaled(
m_size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
1795 const QString &
name(
void)
const override
1797 static QString s_name = QCoreApplication::translate(
"Visualizers",
1841 const QString &
name(
void)
const override
1843 static QString s_name = QCoreApplication::translate(
"Visualizers",