-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Library: add overview column #13638
Library: add overview column #13638
Conversation
IIUC Each thread needs its own database connection, we cannot share/reuse them. Actually, I'm currently experimenting with using a dedicated thread to render overviews. I'll comment back when I get it working. |
I will def review this when you think it's ready for a look |
2fe92b6
to
132976a
Compare
In case you refer to this PR (thanks!), I think it's better to wait for @ninomp's update. |
132976a
to
4cf2f4d
Compare
5b84f24
to
be96671
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm afraid this needs a bunch of work before I trust it...
if (row == -1) { | ||
continue; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this needed here but not in slotOverviewChanged
?
column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_WAVESUMMARYHEX) || | ||
// column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_WAVESUMMARYHEX) || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove completely, right?
src/library/overviewcache.cpp
Outdated
QString pixmapCacheKey(TrackId trackId, QSize size, WOverview::Type type) { | ||
return QString("Overview_%1_%2_%3_%4") | ||
.arg(static_cast<int>(type)) | ||
.arg(trackId.toString()) | ||
.arg(size.width()) | ||
.arg(size.height()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
using a string as a cache key is not particularly efficient. a struct with a qHash
implementation would be better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(I think most of this is adopted from CoverArtCache)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about this?
https://doc.qt.io/qt-6/qpixmapcache-key.html#details
Use QPixmapCache::insert() to receive an instance of Key generated by the pixmap cache. You can store the key in your own objects for a very efficient one-to-one object-to-pixmap mapping.
Does such a one-to-one map QString <--> Key map/hash make sense performance wise?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably not, you're right. I didn't see that this was using QPixmapCache internally. The only improvement then is
QString pixmapCacheKey(TrackId trackId, QSize size, WOverview::Type type) { | |
return QString("Overview_%1_%2_%3_%4") | |
.arg(static_cast<int>(type)) | |
.arg(trackId.toString()) | |
.arg(size.width()) | |
.arg(size.height()); | |
} | |
QString pixmapCacheKey(TrackId trackId, QSize size, WOverview::Type type) { | |
return QStringLiteral("Overview_%1_%2_%3_%4") | |
.arg(static_cast<int>(type), | |
trackId.toString(), | |
size.width(), | |
size.height()); | |
} |
// The transformation mode when scaling images | ||
const Qt::TransformationMode kTransformationMode = Qt::SmoothTransformation; | ||
|
||
inline QImage resizeImageSize(const QImage& image, QSize size) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
inline QImage resizeImageSize(const QImage& image, QSize size) { | |
QImage resizeImageSize(const QImage& image, QSize size) { |
class WaveformOverviewRenderer : public Singleton<WaveformOverviewRenderer> { | ||
public: | ||
QImage render(ConstWaveformPointer, WOverview::Type type); | ||
void drawWaveformPartRGB( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this doesn't have internal state, nor does it need to be a singleton. Consider making this free functions instead and removing the static data. Pass it instead when calling the functions.
FYI I'll keep pushing fixups to hopefully make this safer and maybe a bit faster for my own builds. |
I just created a PR that contains the work I've done in the past week or so: #13644 |
be96671
to
45028bd
Compare
Jup, I'm only push updates to this one to polish it a bit for my personal branch until #13644 is usable for me. I can as well close this PR if it creates too much confusion. |
Well, personally, I'm not sure how to proceed. I tried implementing so many things, but saw little user visible improvement. Could we have a call/meeting to discuss these things before deciding how to proceed? When I say things, I mean:
|
yeah I would be willing to be on such a call though I don't have a lot of expertise in this particular area |
I'll close this one, moved it to ronso0#79 |
Personally I prefer a written discussion when it comes to technical stuff because I have time to look things up and think about it. IMO we could as well discuss it on Zulip.
Yes, if you refer to only the waveform image rendering. IMO we should not overload the tracks table with any kind of markers (except maybe minute markers, but even that could be too much).
I didn't fully understand the purpose of the first QImage cache. Is it supposed to speed up loading of overviews in WOverview when loading a track from the library? Or just save some CPU? |
One model that has worked well for me in the past is writing up a short doc with the relevant issues / references and then a meeting to talk it over. I think a meeting can be more effective to reach a consensus, but I agree that having a specific set of text to discuss helps in doing that. |
Actually, I was referring to overview normalization.
The idea was to copy implementation in WOverview where we have a full sized QImage which is updated as the track is being analyzed so that we can show analysis progress. Yes, I was trying to save a bit of CPU time, but it seems that I was just trading a bit of CPU time for a lot of memory usage and I agree with you that this isn't really worth it. @ronso0 I'm testing your branch and I can say that you managed to get this working very good. I'm currently thinking/considering closing my PR and going forward with yours. I can easily add some of my refactorings into a subsequent PR. |
Thanks, you provided a great foundation! FWIW my fork is here https://github.com/ronso0/mixxx/tree/lib-overview-column-ro / ronso0#79 |
I'll try to summarize, these would be nice to have:
|
@ronso0 I left a few comments on your PR. |
This is based on @ninomp's initial POC commit 9932cfc
https://github.com/ninomp/mixxx/tree/overviewsinlibrary
I removed the disabled parts and added some TODOs/concerns.
(I'll split up some of the commits so it's a bit easier to review)
(I adopted the RGB simplifications made by @Nino MP, and simplified the others, too)
Peforms nicely, though I bet some parts can be optimized.
For example, why pass a
mixxx::DbConnectionPoolPtr
tostatic FutureResult OverviewCache::prepareOverview
to create a AnyalysisDAO for each request, and not a AnyalysisDAO pointer (probably in TrackCollection)?