Compare commits
141 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
50e3eeaafd | ||
|
|
843f528ebc | ||
|
|
faa0076988 | ||
|
|
59622c52ad | ||
|
|
a8e9aba58b | ||
|
|
36563cd1e1 | ||
|
|
072e712f0d | ||
|
|
121a186160 | ||
|
|
15a2ccc21e | ||
|
|
dbd8ea69eb | ||
|
|
8a57356f64 | ||
|
|
c77cb002f3 | ||
|
|
aa83a2b40b | ||
|
|
65b04cac6e | ||
|
|
5e577190a8 | ||
|
|
0143617056 | ||
|
|
a77dde7d3b | ||
|
|
7dcdb7c673 | ||
|
|
6de8eb56cd | ||
|
|
04e272d9bc | ||
|
|
17fe201473 | ||
|
|
25249be37f | ||
|
|
97ec12b5b3 | ||
|
|
246f82bfad | ||
|
|
db5679bbe9 | ||
|
|
feb0e1c45b | ||
|
|
edba837295 | ||
|
|
55882360ef | ||
|
|
6039370ad6 | ||
|
|
2d238c08d3 | ||
|
|
9b337b6a34 | ||
|
|
370db791aa | ||
|
|
9e3c547580 | ||
|
|
ab5d9b62b8 | ||
|
|
8e35e0c476 | ||
|
|
9d9492b528 | ||
|
|
9732cc2ce2 | ||
|
|
a4beea3f34 | ||
|
|
c9256c52bf | ||
|
|
6563bec7e4 | ||
|
|
072facdf7b | ||
|
|
a0f07a7a67 | ||
|
|
1a7465ba94 | ||
|
|
be3862ec40 | ||
|
|
a5276a3b7e | ||
|
|
fc8a27f55b | ||
|
|
87718bee24 | ||
|
|
56f2e00990 | ||
|
|
27e3448dda | ||
|
|
9404e40cad | ||
|
|
982f399aff | ||
|
|
6d373737db | ||
|
|
7f9e196234 | ||
|
|
95d03de160 | ||
|
|
d43190a41f | ||
|
|
b5c0529969 | ||
|
|
621a5b1de8 | ||
|
|
e30f269412 | ||
|
|
494ac20cca | ||
|
|
bf997a6d2e | ||
|
|
bc0c0b7950 | ||
|
|
f202cf6988 | ||
|
|
e62fb964ff | ||
|
|
9014781336 | ||
|
|
e479e7e113 | ||
|
|
f9379961e9 | ||
|
|
e5e6cbf6e4 | ||
|
|
6d686ee66a | ||
|
|
19b645d731 | ||
|
|
28c685dcd8 | ||
|
|
0abeefd470 | ||
|
|
1562585561 | ||
|
|
0a64a2a394 | ||
|
|
440a223bfb | ||
|
|
36b0a22c79 | ||
|
|
032022c246 | ||
|
|
9e4f3f9867 | ||
|
|
1119c87b2f | ||
|
|
36ab26c49a | ||
|
|
460cddb3dc | ||
|
|
a5c2dfacf0 | ||
|
|
b9788ef4b5 | ||
|
|
4a124e596e | ||
|
|
994a400ac9 | ||
|
|
d08e6a1dca | ||
|
|
154136185b | ||
|
|
f86b10c71f | ||
|
|
0b3d84a65e | ||
|
|
ee78b6f2bb | ||
|
|
521d5cf4fa | ||
|
|
52cf4412c8 | ||
|
|
dcae67ac7b | ||
|
|
cd0ee282c6 | ||
|
|
9d7e5864de | ||
|
|
d426eb2e07 | ||
|
|
06bed7feb7 | ||
|
|
adc38c4b12 | ||
|
|
5af58c19ae | ||
|
|
ac6cac8da1 | ||
|
|
3b30e66e87 | ||
|
|
41b0b1efd4 | ||
|
|
099d098dc7 | ||
|
|
1a55b7f1b2 | ||
|
|
f5ba8da3c7 | ||
|
|
08fcedd925 | ||
|
|
57f6f40e7d | ||
|
|
4ca99dde43 | ||
|
|
c518e42e18 | ||
|
|
0c329e6d83 | ||
|
|
820124f9e1 | ||
|
|
26062bd07b | ||
|
|
73029ab7a2 | ||
|
|
c3e916d945 | ||
|
|
6ee9f9d1ad | ||
|
|
b2c26eb4ed | ||
|
|
e181b47e3f | ||
|
|
dc91f19f30 | ||
|
|
e260fc5057 | ||
|
|
2368fff243 | ||
|
|
70db0a33d1 | ||
|
|
56f47909f4 | ||
|
|
e22b47a9d1 | ||
|
|
e32ed02a24 | ||
|
|
eb5d72a940 | ||
|
|
cbd809621a | ||
|
|
ad5d5d0ecd | ||
|
|
6bc948453c | ||
|
|
803590daa8 | ||
|
|
c63399ee98 | ||
|
|
f5ff95dca4 | ||
|
|
998357c0bb | ||
|
|
b43331bc3c | ||
|
|
ecfeb17869 | ||
|
|
9d2c9c732e | ||
|
|
6478fadedc | ||
|
|
a62eaa919d | ||
|
|
328a86288c | ||
|
|
f1902a5b63 | ||
|
|
693bade5a6 | ||
|
|
ca2acb177a | ||
|
|
670cd4e081 |
4
.gitignore
vendored
@@ -34,6 +34,10 @@ Thumbs.db
|
||||
*.rc
|
||||
/.qmake.cache
|
||||
/.qmake.stash
|
||||
*.spec
|
||||
*.nsi
|
||||
*.plist
|
||||
maketarball.sh
|
||||
|
||||
# qtcreator generated files
|
||||
*.pro.user*
|
||||
|
||||
30
.travis.yml
Normal file
@@ -0,0 +1,30 @@
|
||||
sudo: required
|
||||
language: C++
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
services:
|
||||
- docker
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
|
||||
before_install:
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker build -f Dockerfile -t strawberry-build . ; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker run --name build -itd strawberry-build /bin/bash ; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker exec build git clone https://github.com/jonaski/strawberry ; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew unlink python ; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install glib pkgconfig protobuf protobuf-c qt ; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install sqlite --with-fts ; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install gstreamer gst-plugins-base ; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install gst-plugins-good --with-flac ; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install gst-plugins-bad gst-plugins-ugly ; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install chromaprint ; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export Qt5_DIR=/usr/local/opt/qt5/lib/cmake ; fi
|
||||
before_script:
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker exec build cmake -Hstrawberry -Bbuild ; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then mkdir build; cd build; cmake .. -DFORCE_GIT_REVISION="0.0.0-0-g0000000"; fi
|
||||
script:
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker exec build make -C build -j8 ; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then make -j8 ; fi
|
||||
45
3rdparty/qocoa/qsearchfield.h
vendored
@@ -6,43 +6,38 @@
|
||||
#include <QMenu>
|
||||
|
||||
class QSearchFieldPrivate;
|
||||
class QSearchField : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
class QSearchField : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged USER true);
|
||||
Q_PROPERTY(QString placeholderText READ placeholderText WRITE setPlaceholderText);
|
||||
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged USER true);
|
||||
Q_PROPERTY(QString placeholderText READ placeholderText WRITE setPlaceholderText);
|
||||
|
||||
public:
|
||||
explicit QSearchField(QWidget *parent);
|
||||
explicit QSearchField(QWidget *parent);
|
||||
|
||||
QString text() const;
|
||||
QString placeholderText() const;
|
||||
void setFocus(Qt::FocusReason);
|
||||
void setMenu(QMenu *menu);
|
||||
QString text() const;
|
||||
QString placeholderText() const;
|
||||
void setFocus(Qt::FocusReason);
|
||||
|
||||
public slots:
|
||||
void setText(const QString &text);
|
||||
void setPlaceholderText(const QString &text);
|
||||
void clear();
|
||||
void selectAll();
|
||||
void setFocus();
|
||||
void setText(const QString &text);
|
||||
void setPlaceholderText(const QString &text);
|
||||
void clear();
|
||||
void selectAll();
|
||||
void setFocus();
|
||||
|
||||
signals:
|
||||
void textChanged(const QString &text);
|
||||
void editingFinished();
|
||||
void returnPressed();
|
||||
|
||||
private slots:
|
||||
void popupMenu();
|
||||
void textChanged(const QString &text);
|
||||
void editingFinished();
|
||||
void returnPressed();
|
||||
|
||||
protected:
|
||||
void changeEvent(QEvent*);
|
||||
void resizeEvent(QResizeEvent*);
|
||||
void resizeEvent(QResizeEvent*);
|
||||
bool eventFilter(QObject*, QEvent*);
|
||||
|
||||
private:
|
||||
friend class QSearchFieldPrivate;
|
||||
QPointer <QSearchFieldPrivate> pimpl;
|
||||
friend class QSearchFieldPrivate;
|
||||
QPointer <QSearchFieldPrivate> pimpl;
|
||||
};
|
||||
|
||||
#endif // QSEARCHFIELD_H
|
||||
|
||||
327
3rdparty/qocoa/qsearchfield_mac.mm
vendored
@@ -32,57 +32,50 @@ THE SOFTWARE.
|
||||
#include <QKeyEvent>
|
||||
#include <QClipboard>
|
||||
|
||||
class QSearchFieldPrivate : public QObject
|
||||
{
|
||||
class QSearchFieldPrivate : public QObject {
|
||||
public:
|
||||
QSearchFieldPrivate(QSearchField *qSearchField, NSSearchField *nsSearchField)
|
||||
: QObject(qSearchField), qSearchField(qSearchField), nsSearchField(nsSearchField) {}
|
||||
QSearchFieldPrivate(QSearchField *qSearchField, NSSearchField *nsSearchField)
|
||||
: QObject(qSearchField), qSearchField(qSearchField), nsSearchField(nsSearchField) {}
|
||||
|
||||
void textDidChange(const QString &text)
|
||||
{
|
||||
if (qSearchField)
|
||||
emit qSearchField->textChanged(text);
|
||||
void textDidChange(const QString &text) {
|
||||
if (qSearchField) emit qSearchField->textChanged(text);
|
||||
}
|
||||
|
||||
void textDidEndEditing() {
|
||||
if (qSearchField)
|
||||
emit qSearchField->editingFinished();
|
||||
}
|
||||
|
||||
void textDidEndEditing()
|
||||
{
|
||||
if (qSearchField)
|
||||
emit qSearchField->editingFinished();
|
||||
void returnPressed() {
|
||||
if (qSearchField) {
|
||||
emit qSearchField->returnPressed();
|
||||
QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier);
|
||||
QApplication::postEvent(qSearchField, event);
|
||||
}
|
||||
}
|
||||
|
||||
void returnPressed()
|
||||
{
|
||||
if (qSearchField) {
|
||||
emit qSearchField->returnPressed();
|
||||
QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Return, Qt::NoModifier);
|
||||
QApplication::postEvent(qSearchField, event);
|
||||
}
|
||||
void keyDownPressed() {
|
||||
if (qSearchField) {
|
||||
QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier);
|
||||
QApplication::postEvent(qSearchField, event);
|
||||
}
|
||||
}
|
||||
|
||||
void keyDownPressed()
|
||||
{
|
||||
if (qSearchField) {
|
||||
QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier);
|
||||
QApplication::postEvent(qSearchField, event);
|
||||
}
|
||||
void keyUpPressed() {
|
||||
if (qSearchField) {
|
||||
QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier);
|
||||
QApplication::postEvent(qSearchField, event);
|
||||
}
|
||||
}
|
||||
|
||||
void keyUpPressed()
|
||||
{
|
||||
if (qSearchField) {
|
||||
QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, Qt::Key_Up, Qt::NoModifier);
|
||||
QApplication::postEvent(qSearchField, event);
|
||||
}
|
||||
}
|
||||
QPointer<QSearchField> qSearchField;
|
||||
NSSearchField *nsSearchField;
|
||||
|
||||
QPointer<QSearchField> qSearchField;
|
||||
NSSearchField *nsSearchField;
|
||||
};
|
||||
|
||||
@interface QSearchFieldDelegate : NSObject<NSTextFieldDelegate>
|
||||
{
|
||||
@interface QSearchFieldDelegate : NSObject<NSTextFieldDelegate> {
|
||||
@public
|
||||
QPointer<QSearchFieldPrivate> pimpl;
|
||||
QPointer<QSearchFieldPrivate> pimpl;
|
||||
}
|
||||
-(void)controlTextDidChange:(NSNotification*)notification;
|
||||
-(void)controlTextDidEndEditing:(NSNotification*)notification;
|
||||
@@ -90,35 +83,33 @@ public:
|
||||
|
||||
@implementation QSearchFieldDelegate
|
||||
-(void)controlTextDidChange:(NSNotification*)notification {
|
||||
Q_ASSERT(pimpl);
|
||||
if (pimpl)
|
||||
pimpl->textDidChange(toQString([[notification object] stringValue]));
|
||||
Q_ASSERT(pimpl);
|
||||
if (pimpl) pimpl->textDidChange(toQString([[notification object] stringValue]));
|
||||
}
|
||||
|
||||
-(void)controlTextDidEndEditing:(NSNotification*)notification {
|
||||
Q_UNUSED(notification);
|
||||
// No Q_ASSERT here as it is called on destruction.
|
||||
if (pimpl)
|
||||
pimpl->textDidEndEditing();
|
||||
|
||||
if ([[[notification userInfo] objectForKey:@"NSTextMovement"] intValue] == NSReturnTextMovement)
|
||||
pimpl->returnPressed();
|
||||
Q_UNUSED(notification);
|
||||
// No Q_ASSERT here as it is called on destruction.
|
||||
if (!pimpl) return;
|
||||
pimpl->textDidEndEditing();
|
||||
if ([[[notification userInfo] objectForKey:@"NSTextMovement"] intValue] == NSReturnTextMovement)
|
||||
pimpl->returnPressed();
|
||||
}
|
||||
|
||||
-(BOOL)control: (NSControl *)control textView:
|
||||
(NSTextView *)textView doCommandBySelector:
|
||||
(SEL)commandSelector {
|
||||
Q_ASSERT(pimpl);
|
||||
if (!pimpl) return NO;
|
||||
|
||||
if (commandSelector == @selector(moveDown:)) {
|
||||
pimpl->keyDownPressed();
|
||||
return YES;
|
||||
} else if (commandSelector == @selector(moveUp:)) {
|
||||
pimpl->keyUpPressed();
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
(NSTextView *)textView doCommandBySelector:
|
||||
(SEL)commandSelector {
|
||||
Q_ASSERT(pimpl);
|
||||
if (!pimpl) return NO;
|
||||
if (commandSelector == @selector(moveDown:)) {
|
||||
pimpl->keyDownPressed();
|
||||
return YES;
|
||||
}
|
||||
else if (commandSelector == @selector(moveUp:)) {
|
||||
pimpl->keyUpPressed();
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -129,169 +120,109 @@ public:
|
||||
|
||||
@implementation QocoaSearchField
|
||||
-(BOOL)performKeyEquivalent:(NSEvent*)event {
|
||||
// First, check if we have the focus.
|
||||
// If no, it probably means this event isn't for us.
|
||||
NSResponder* firstResponder = [[NSApp keyWindow] firstResponder];
|
||||
if ([firstResponder isKindOfClass:[NSText class]] &&
|
||||
[(NSText*)firstResponder delegate] == self) {
|
||||
// First, check if we have the focus.
|
||||
// If no, it probably means this event isn't for us.
|
||||
NSResponder* firstResponder = [[NSApp keyWindow] firstResponder];
|
||||
if ([firstResponder isKindOfClass:[NSText class]] && [(NSText*)firstResponder delegate] == self) {
|
||||
|
||||
if ([event type] == NSEventTypeKeyDown && [event modifierFlags] & NSEventModifierFlagCommand)
|
||||
{
|
||||
QString keyString = toQString([event characters]);
|
||||
if (keyString == "a") // Cmd+a
|
||||
{
|
||||
[self performSelector:@selector(selectText:)];
|
||||
return YES;
|
||||
}
|
||||
else if (keyString == "c") // Cmd+c
|
||||
{
|
||||
[[self currentEditor] copy: nil];
|
||||
return YES;
|
||||
}
|
||||
else if (keyString == "v") // Cmd+v
|
||||
{
|
||||
[[self currentEditor] paste: nil];
|
||||
return YES;
|
||||
}
|
||||
else if (keyString == "x") // Cmd+x
|
||||
{
|
||||
[[self currentEditor] cut: nil];
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
if ([event type] == NSEventTypeKeyDown && [event modifierFlags] & NSEventModifierFlagCommand) {
|
||||
QString keyString = toQString([event characters]);
|
||||
if (keyString == "a") // Cmd+a
|
||||
{
|
||||
[self performSelector:@selector(selectText:)];
|
||||
return YES;
|
||||
}
|
||||
else if (keyString == "c") // Cmd+c
|
||||
{
|
||||
[[self currentEditor] copy: nil];
|
||||
return YES;
|
||||
}
|
||||
else if (keyString == "v") // Cmd+v
|
||||
{
|
||||
[[self currentEditor] paste: nil];
|
||||
return YES;
|
||||
}
|
||||
else if (keyString == "x") // Cmd+x
|
||||
{
|
||||
[[self currentEditor] cut: nil];
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NO;
|
||||
return NO;
|
||||
}
|
||||
@end
|
||||
|
||||
QSearchField::QSearchField(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
NSSearchField *search = [[QocoaSearchField alloc] init];
|
||||
|
||||
QSearchFieldDelegate *delegate = [[QSearchFieldDelegate alloc] init];
|
||||
pimpl = delegate->pimpl = new QSearchFieldPrivate(this, search);
|
||||
[search setDelegate:delegate];
|
||||
|
||||
setupLayout(search, this);
|
||||
|
||||
setFixedHeight(24);
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
|
||||
[search release];
|
||||
|
||||
[pool drain];
|
||||
QSearchField::QSearchField(QWidget *parent) : QWidget(parent) {
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSSearchField *search = [[QocoaSearchField alloc] init];
|
||||
QSearchFieldDelegate *delegate = [[QSearchFieldDelegate alloc] init];
|
||||
pimpl = delegate->pimpl = new QSearchFieldPrivate(this, search);
|
||||
[search setDelegate:delegate];
|
||||
setupLayout(search, this);
|
||||
setFixedHeight(24);
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
[search release];
|
||||
[pool drain];
|
||||
}
|
||||
|
||||
void QSearchField::setMenu(QMenu *menu)
|
||||
{
|
||||
Q_ASSERT(pimpl);
|
||||
if (!pimpl)
|
||||
return;
|
||||
void QSearchField::setText(const QString &text) {
|
||||
Q_ASSERT(pimpl);
|
||||
if (!pimpl) return;
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||
NSMenu *nsMenu = menu->macMenu();
|
||||
#else
|
||||
NSMenu *nsMenu = menu->toNSMenu();
|
||||
#endif
|
||||
|
||||
[[pimpl->nsSearchField cell] setSearchMenuTemplate:nsMenu];
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
[pimpl->nsSearchField setStringValue:fromQString(text)];
|
||||
if (!text.isEmpty()) {
|
||||
[pimpl->nsSearchField selectText:pimpl->nsSearchField];
|
||||
[[pimpl->nsSearchField currentEditor] setSelectedRange:NSMakeRange([[pimpl->nsSearchField stringValue] length], 0)];
|
||||
}
|
||||
[pool drain];
|
||||
}
|
||||
|
||||
void QSearchField::popupMenu()
|
||||
{
|
||||
void QSearchField::setPlaceholderText(const QString &text) {
|
||||
Q_ASSERT(pimpl);
|
||||
if (!pimpl) return;
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
[[pimpl->nsSearchField cell] setPlaceholderString:fromQString(text)];
|
||||
[pool drain];
|
||||
}
|
||||
|
||||
void QSearchField::setText(const QString &text)
|
||||
{
|
||||
Q_ASSERT(pimpl);
|
||||
if (!pimpl)
|
||||
return;
|
||||
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
[pimpl->nsSearchField setStringValue:fromQString(text)];
|
||||
[pool drain];
|
||||
void QSearchField::clear() {
|
||||
Q_ASSERT(pimpl);
|
||||
if (!pimpl) return;
|
||||
[pimpl->nsSearchField setStringValue:@""];
|
||||
emit textChanged(QString());
|
||||
}
|
||||
|
||||
void QSearchField::setPlaceholderText(const QString &text)
|
||||
{
|
||||
Q_ASSERT(pimpl);
|
||||
if (!pimpl)
|
||||
return;
|
||||
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
[[pimpl->nsSearchField cell] setPlaceholderString:fromQString(text)];
|
||||
[pool drain];
|
||||
void QSearchField::selectAll() {
|
||||
Q_ASSERT(pimpl);
|
||||
if (!pimpl) return;
|
||||
[pimpl->nsSearchField performSelector:@selector(selectText:)];
|
||||
}
|
||||
|
||||
void QSearchField::clear()
|
||||
{
|
||||
Q_ASSERT(pimpl);
|
||||
if (!pimpl)
|
||||
return;
|
||||
|
||||
[pimpl->nsSearchField setStringValue:@""];
|
||||
emit textChanged(QString());
|
||||
QString QSearchField::text() const {
|
||||
Q_ASSERT(pimpl);
|
||||
if (!pimpl) return QString();
|
||||
return toQString([pimpl->nsSearchField stringValue]);
|
||||
}
|
||||
|
||||
void QSearchField::selectAll()
|
||||
{
|
||||
Q_ASSERT(pimpl);
|
||||
if (!pimpl)
|
||||
return;
|
||||
|
||||
[pimpl->nsSearchField performSelector:@selector(selectText:)];
|
||||
QString QSearchField::placeholderText() const {
|
||||
Q_ASSERT(pimpl);
|
||||
return toQString([[pimpl->nsSearchField cell] placeholderString]);
|
||||
}
|
||||
|
||||
QString QSearchField::text() const
|
||||
{
|
||||
Q_ASSERT(pimpl);
|
||||
if (!pimpl)
|
||||
return QString();
|
||||
void QSearchField::setFocus(Qt::FocusReason) {}
|
||||
|
||||
return toQString([pimpl->nsSearchField stringValue]);
|
||||
void QSearchField::setFocus() {
|
||||
setFocus(Qt::OtherFocusReason);
|
||||
}
|
||||
|
||||
QString QSearchField::placeholderText() const
|
||||
{
|
||||
Q_ASSERT(pimpl);
|
||||
if (!pimpl)
|
||||
return QString();
|
||||
|
||||
return toQString([[pimpl->nsSearchField cell] placeholderString]);
|
||||
void QSearchField::resizeEvent(QResizeEvent *resizeEvent) {
|
||||
QWidget::resizeEvent(resizeEvent);
|
||||
}
|
||||
|
||||
void QSearchField::setFocus(Qt::FocusReason)
|
||||
{
|
||||
Q_ASSERT(pimpl);
|
||||
if (!pimpl)
|
||||
return;
|
||||
|
||||
if ([pimpl->nsSearchField acceptsFirstResponder])
|
||||
[[pimpl->nsSearchField window] makeFirstResponder: pimpl->nsSearchField];
|
||||
bool QSearchField::eventFilter(QObject *o, QEvent *e) {
|
||||
return QWidget::eventFilter(o, e);
|
||||
}
|
||||
|
||||
void QSearchField::setFocus()
|
||||
{
|
||||
setFocus(Qt::OtherFocusReason);
|
||||
}
|
||||
|
||||
void QSearchField::changeEvent(QEvent* event)
|
||||
{
|
||||
if (event->type() == QEvent::EnabledChange) {
|
||||
Q_ASSERT(pimpl);
|
||||
if (!pimpl)
|
||||
return;
|
||||
|
||||
const bool enabled = isEnabled();
|
||||
[pimpl->nsSearchField setEnabled: enabled];
|
||||
}
|
||||
QWidget::changeEvent(event);
|
||||
}
|
||||
|
||||
void QSearchField::resizeEvent(QResizeEvent *resizeEvent)
|
||||
{
|
||||
QWidget::resizeEvent(resizeEvent);
|
||||
}
|
||||
|
||||
297
3rdparty/qocoa/qsearchfield_nonmac.cpp
vendored
@@ -22,235 +22,140 @@ THE SOFTWARE.
|
||||
|
||||
#include "qsearchfield.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
#include <QLineEdit>
|
||||
#include <QVBoxLayout>
|
||||
#include <QToolButton>
|
||||
#include <QStyle>
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
#include <QEvent>
|
||||
|
||||
#include <QDir>
|
||||
#include <QDebug>
|
||||
|
||||
class QSearchFieldPrivate : public QObject
|
||||
{
|
||||
#include "../../src/core/iconloader.h"
|
||||
|
||||
class QSearchFieldPrivate : public QObject {
|
||||
public:
|
||||
QSearchFieldPrivate(QSearchField *searchField, QLineEdit *lineEdit, QToolButton *clearButton, QToolButton *searchButton)
|
||||
: QObject(searchField), lineEdit(lineEdit), clearButton(clearButton), searchButton(searchButton) {}
|
||||
QSearchFieldPrivate(QSearchField *searchField, QLineEdit *lineEdit, QToolButton *clearButton)
|
||||
: QObject(searchField), lineEdit(lineEdit), clearButton(clearButton) {}
|
||||
|
||||
int lineEditFrameWidth() const {
|
||||
return lineEdit->style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
|
||||
}
|
||||
int lineEditFrameWidth() const {
|
||||
return lineEdit->style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
|
||||
}
|
||||
|
||||
int clearButtonPaddedWidth() const {
|
||||
return clearButton->width() + lineEditFrameWidth() * 2;
|
||||
}
|
||||
int clearButtonPaddedWidth() const {
|
||||
return clearButton->width() + lineEditFrameWidth() * 2;
|
||||
}
|
||||
|
||||
int clearButtonPaddedHeight() const {
|
||||
return clearButton->height() + lineEditFrameWidth() * 2;
|
||||
}
|
||||
int clearButtonPaddedHeight() const {
|
||||
return clearButton->height() + lineEditFrameWidth() * 2;
|
||||
}
|
||||
|
||||
int searchButtonPaddedWidth() const {
|
||||
return searchButton->width() + lineEditFrameWidth() * 2;
|
||||
}
|
||||
|
||||
int searchButtonPaddedHeight() const {
|
||||
return searchButton->height() + lineEditFrameWidth() * 2;
|
||||
}
|
||||
|
||||
QPointer<QLineEdit> lineEdit;
|
||||
QPointer<QToolButton> clearButton;
|
||||
QPointer<QToolButton> searchButton;
|
||||
QPointer<QMenu> searchMenu;
|
||||
QPointer<QLineEdit> lineEdit;
|
||||
QPointer<QToolButton> clearButton;
|
||||
};
|
||||
|
||||
QSearchField::QSearchField(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
QLineEdit *lineEdit = new QLineEdit(this);
|
||||
connect(lineEdit, SIGNAL(textChanged(QString)),
|
||||
this, SIGNAL(textChanged(QString)));
|
||||
connect(lineEdit, SIGNAL(editingFinished()),
|
||||
this, SIGNAL(editingFinished()));
|
||||
connect(lineEdit, SIGNAL(returnPressed()),
|
||||
this, SIGNAL(returnPressed()));
|
||||
connect(lineEdit, SIGNAL(textChanged(QString)),
|
||||
this, SLOT(setText(QString)));
|
||||
QSearchField::QSearchField(QWidget *parent) : QWidget(parent) {
|
||||
|
||||
int iconsize = style()->pixelMetric(QStyle::PM_SmallIconSize);
|
||||
QToolButton *clearButton = new QToolButton(this);
|
||||
QIcon clearIcon = QIcon::fromTheme(QLatin1String("edit-clear"),
|
||||
QIcon(QLatin1String(":/Qocoa/qsearchfield_nonmac_clear.png")));
|
||||
clearButton->setIcon(clearIcon);
|
||||
clearButton->setIconSize(QSize(iconsize, iconsize));
|
||||
clearButton->setFixedSize(QSize(iconsize, iconsize));
|
||||
clearButton->setStyleSheet("border: none;");
|
||||
clearButton->hide();
|
||||
connect(clearButton, SIGNAL(clicked()), this, SLOT(clear()));
|
||||
QLineEdit *lineEdit = new QLineEdit(this);
|
||||
connect(lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(textChanged(QString)));
|
||||
connect(lineEdit, SIGNAL(editingFinished()), this, SIGNAL(editingFinished()));
|
||||
connect(lineEdit, SIGNAL(returnPressed()), this, SIGNAL(returnPressed()));
|
||||
connect(lineEdit, SIGNAL(textChanged(QString)), this, SLOT(setText(QString)));
|
||||
|
||||
QToolButton *searchButton = new QToolButton(this);
|
||||
QIcon searchIcon = QIcon(QLatin1String(":/Qocoa/qsearchfield_nonmac_magnifier.png"));
|
||||
searchButton->setIcon(searchIcon);
|
||||
searchButton->setIconSize(QSize(iconsize, iconsize));
|
||||
searchButton->setFixedSize(QSize(iconsize, iconsize));
|
||||
searchButton->setStyleSheet("border: none;");
|
||||
searchButton->setPopupMode(QToolButton::InstantPopup);
|
||||
searchButton->setEnabled(false);
|
||||
connect(searchButton, SIGNAL(clicked()), this, SLOT(popupMenu()));
|
||||
QToolButton *clearButton = new QToolButton(this);
|
||||
QIcon clearIcon(IconLoader::Load("edit-clear-locationbar-ltr"));
|
||||
|
||||
pimpl = new QSearchFieldPrivate(this, lineEdit, clearButton, searchButton);
|
||||
clearButton->setIcon(clearIcon);
|
||||
clearButton->setIconSize(QSize(16, 16));
|
||||
clearButton->setStyleSheet("border: none; padding: 0px;");
|
||||
clearButton->resize(clearButton->sizeHint());
|
||||
|
||||
lineEdit->setStyleSheet(QString("QLineEdit { padding-left: %1px; padding-right: %2px; } ")
|
||||
.arg(pimpl->searchButtonPaddedWidth())
|
||||
.arg(pimpl->clearButtonPaddedWidth()));
|
||||
const int width = qMax(lineEdit->minimumSizeHint().width(), pimpl->clearButtonPaddedWidth() + pimpl->searchButtonPaddedWidth());
|
||||
const int height = qMax(lineEdit->minimumSizeHint().height(),
|
||||
qMax(pimpl->clearButtonPaddedHeight(),
|
||||
pimpl->searchButtonPaddedHeight()));
|
||||
lineEdit->setMinimumSize(width, height);
|
||||
connect(clearButton, SIGNAL(clicked()), this, SLOT(clear()));
|
||||
|
||||
pimpl = new QSearchFieldPrivate(this, lineEdit, clearButton);
|
||||
|
||||
const int frame_width = lineEdit->style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
|
||||
|
||||
lineEdit->setStyleSheet(QString("QLineEdit { padding-left: %1px; } ").arg(clearButton->width()));
|
||||
const int width = frame_width + qMax(lineEdit->minimumSizeHint().width(), pimpl->clearButtonPaddedWidth());
|
||||
const int height = frame_width + qMax(lineEdit->minimumSizeHint().height(), pimpl->clearButtonPaddedHeight());
|
||||
lineEdit->setMinimumSize(width, height);
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
layout->setMargin(0);
|
||||
layout->addWidget(lineEdit);
|
||||
|
||||
lineEdit->installEventFilter(this);
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
layout->setMargin(0);
|
||||
layout->addWidget(lineEdit);
|
||||
}
|
||||
|
||||
void QSearchField::setMenu(QMenu *menu)
|
||||
{
|
||||
Q_ASSERT(pimpl);
|
||||
if (!pimpl)
|
||||
return;
|
||||
void QSearchField::setText(const QString &text) {
|
||||
|
||||
pimpl->searchMenu = menu;
|
||||
Q_ASSERT(pimpl && pimpl->clearButton && pimpl->lineEdit);
|
||||
if (!(pimpl && pimpl->clearButton && pimpl->lineEdit)) return;
|
||||
if (text != this->text()) pimpl->lineEdit->setText(text);
|
||||
|
||||
QIcon searchIcon = menu ? QIcon(QLatin1String(":/Qocoa/qsearchfield_nonmac_magnifier_menu.png"))
|
||||
: QIcon(QLatin1String(":/Qocoa/qsearchfield_nonmac_magnifier.png"));
|
||||
pimpl->searchButton->setIcon(searchIcon);
|
||||
pimpl->searchButton->setEnabled(isEnabled() && menu);
|
||||
}
|
||||
|
||||
void QSearchField::popupMenu()
|
||||
{
|
||||
Q_ASSERT(pimpl);
|
||||
if (!pimpl)
|
||||
return;
|
||||
|
||||
if (pimpl->searchMenu) {
|
||||
const QRect screenRect = qApp->desktop()->availableGeometry(pimpl->searchButton);
|
||||
const QSize sizeHint = pimpl->searchMenu->sizeHint();
|
||||
const QRect rect = pimpl->searchButton->rect();
|
||||
const int x = pimpl->searchButton->isRightToLeft()
|
||||
? rect.right() - sizeHint.width()
|
||||
: rect.left();
|
||||
const int y = pimpl->searchButton->mapToGlobal(QPoint(0, rect.bottom())).y() + sizeHint.height() <= screenRect.height()
|
||||
? rect.bottom()
|
||||
: rect.top() - sizeHint.height();
|
||||
QPoint point = pimpl->searchButton->mapToGlobal(QPoint(x, y));
|
||||
point.rx() = qMax(screenRect.left(), qMin(point.x(), screenRect.right() - sizeHint.width()));
|
||||
point.ry() += 1;
|
||||
|
||||
pimpl->searchMenu->popup(point);
|
||||
}
|
||||
}
|
||||
|
||||
void QSearchField::changeEvent(QEvent* event)
|
||||
{
|
||||
if (event->type() == QEvent::EnabledChange) {
|
||||
Q_ASSERT(pimpl);
|
||||
if (!pimpl)
|
||||
return;
|
||||
|
||||
const bool enabled = isEnabled();
|
||||
pimpl->searchButton->setEnabled(enabled && pimpl->searchMenu);
|
||||
pimpl->lineEdit->setEnabled(enabled);
|
||||
pimpl->clearButton->setEnabled(enabled);
|
||||
}
|
||||
QWidget::changeEvent(event);
|
||||
}
|
||||
|
||||
void QSearchField::setText(const QString &text)
|
||||
{
|
||||
Q_ASSERT(pimpl && pimpl->clearButton && pimpl->lineEdit);
|
||||
if (!(pimpl && pimpl->clearButton && pimpl->lineEdit))
|
||||
return;
|
||||
|
||||
pimpl->clearButton->setVisible(!text.isEmpty());
|
||||
|
||||
if (text != this->text())
|
||||
pimpl->lineEdit->setText(text);
|
||||
}
|
||||
|
||||
void QSearchField::setPlaceholderText(const QString &text)
|
||||
{
|
||||
Q_ASSERT(pimpl && pimpl->lineEdit);
|
||||
if (!(pimpl && pimpl->lineEdit))
|
||||
return;
|
||||
|
||||
#if QT_VERSION >= 0x040700
|
||||
pimpl->lineEdit->setPlaceholderText(text);
|
||||
#endif
|
||||
}
|
||||
|
||||
void QSearchField::clear()
|
||||
{
|
||||
Q_ASSERT(pimpl && pimpl->lineEdit);
|
||||
if (!(pimpl && pimpl->lineEdit))
|
||||
return;
|
||||
|
||||
pimpl->lineEdit->clear();
|
||||
}
|
||||
|
||||
void QSearchField::selectAll()
|
||||
{
|
||||
Q_ASSERT(pimpl && pimpl->lineEdit);
|
||||
if (!(pimpl && pimpl->lineEdit))
|
||||
return;
|
||||
|
||||
pimpl->lineEdit->selectAll();
|
||||
}
|
||||
|
||||
QString QSearchField::text() const
|
||||
{
|
||||
Q_ASSERT(pimpl && pimpl->lineEdit);
|
||||
if (!(pimpl && pimpl->lineEdit))
|
||||
return QString();
|
||||
|
||||
return pimpl->lineEdit->text();
|
||||
void QSearchField::setPlaceholderText(const QString &text) {
|
||||
Q_ASSERT(pimpl && pimpl->lineEdit);
|
||||
if (!(pimpl && pimpl->lineEdit)) return;
|
||||
pimpl->lineEdit->setPlaceholderText(text);
|
||||
}
|
||||
|
||||
QString QSearchField::placeholderText() const {
|
||||
Q_ASSERT(pimpl && pimpl->lineEdit);
|
||||
if (!(pimpl && pimpl->lineEdit))
|
||||
return QString();
|
||||
|
||||
#if QT_VERSION >= 0x040700
|
||||
return pimpl->lineEdit->placeholderText();
|
||||
#else
|
||||
return QString();
|
||||
#endif
|
||||
return pimpl->lineEdit->placeholderText();
|
||||
}
|
||||
|
||||
void QSearchField::setFocus(Qt::FocusReason reason)
|
||||
{
|
||||
Q_ASSERT(pimpl && pimpl->lineEdit);
|
||||
if (pimpl && pimpl->lineEdit)
|
||||
pimpl->lineEdit->setFocus(reason);
|
||||
void QSearchField::setFocus(Qt::FocusReason reason) {
|
||||
Q_ASSERT(pimpl && pimpl->lineEdit);
|
||||
if (pimpl && pimpl->lineEdit) pimpl->lineEdit->setFocus(reason);
|
||||
}
|
||||
|
||||
void QSearchField::setFocus()
|
||||
{
|
||||
setFocus(Qt::OtherFocusReason);
|
||||
void QSearchField::setFocus() {
|
||||
setFocus(Qt::OtherFocusReason);
|
||||
}
|
||||
|
||||
void QSearchField::resizeEvent(QResizeEvent *resizeEvent)
|
||||
{
|
||||
Q_ASSERT(pimpl && pimpl->clearButton && pimpl->lineEdit);
|
||||
if (!(pimpl && pimpl->clearButton && pimpl->lineEdit))
|
||||
return;
|
||||
|
||||
QWidget::resizeEvent(resizeEvent);
|
||||
const int x = width() - pimpl->clearButtonPaddedWidth();
|
||||
const int y = (height() - pimpl->clearButton->height())/2;
|
||||
pimpl->clearButton->move(x, y);
|
||||
|
||||
pimpl->searchButton->move(pimpl->lineEditFrameWidth() * 2,
|
||||
(height() - pimpl->searchButton->height())/2);
|
||||
void QSearchField::clear() {
|
||||
Q_ASSERT(pimpl && pimpl->lineEdit);
|
||||
if (!(pimpl && pimpl->lineEdit)) return;
|
||||
pimpl->lineEdit->clear();
|
||||
}
|
||||
|
||||
void QSearchField::selectAll() {
|
||||
Q_ASSERT(pimpl && pimpl->lineEdit);
|
||||
if (!(pimpl && pimpl->lineEdit)) return;
|
||||
pimpl->lineEdit->selectAll();
|
||||
}
|
||||
|
||||
QString QSearchField::text() const {
|
||||
Q_ASSERT(pimpl && pimpl->lineEdit);
|
||||
if (!(pimpl && pimpl->lineEdit)) return QString();
|
||||
return pimpl->lineEdit->text();
|
||||
}
|
||||
|
||||
void QSearchField::resizeEvent(QResizeEvent *resizeEvent) {
|
||||
Q_ASSERT(pimpl && pimpl->clearButton && pimpl->lineEdit);
|
||||
if (!(pimpl && pimpl->clearButton && pimpl->lineEdit)) return;
|
||||
|
||||
QWidget::resizeEvent(resizeEvent);
|
||||
const int x = pimpl->lineEditFrameWidth();
|
||||
const int y = (height() - pimpl->clearButton->height())/2;
|
||||
pimpl->clearButton->move(x, y);
|
||||
}
|
||||
|
||||
bool QSearchField::eventFilter(QObject *o, QEvent *e) {
|
||||
if (pimpl && pimpl->lineEdit && o == pimpl->lineEdit) {
|
||||
// Forward some lineEdit events to QSearchField (only those we need for
|
||||
// now, but some might be added later if needed)
|
||||
switch (e->type()) {
|
||||
case QEvent::FocusIn:
|
||||
case QEvent::FocusOut:
|
||||
QApplication::sendEvent(this, e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QWidget::eventFilter(o, e);
|
||||
}
|
||||
|
||||
2
3rdparty/qtsingleapplication/CMakeLists.txt
vendored
@@ -27,3 +27,5 @@ ADD_LIBRARY(qtsingleapplication STATIC
|
||||
)
|
||||
|
||||
target_link_libraries(qtsingleapplication Qt5::Core Qt5::Widgets Qt5::Network)
|
||||
|
||||
include_directories(${CMAKE_BINARY_DIR}/src)
|
||||
|
||||
2
3rdparty/qtsingleapplication/qtlockedfile.h
vendored
@@ -45,7 +45,7 @@
|
||||
#include <QVector>
|
||||
#endif
|
||||
|
||||
#if defined(Q_WS_WIN) || defined(Q_OS_WIN)
|
||||
#if defined(Q_OS_WIN)
|
||||
# if !defined(QT_QTLOCKEDFILE_EXPORT) && !defined(QT_QTLOCKEDFILE_IMPORT)
|
||||
# define QT_QTLOCKEDFILE_EXPORT
|
||||
# elif defined(QT_QTLOCKEDFILE_IMPORT)
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "qtsingleapplication.h"
|
||||
|
||||
@@ -44,6 +45,10 @@
|
||||
#include <QWidget>
|
||||
#include <QString>
|
||||
|
||||
#ifdef HAVE_X11_ // FIXME
|
||||
# include <X11/Xlib.h>
|
||||
#endif
|
||||
|
||||
#include "qtlocalpeer.h"
|
||||
|
||||
/*!
|
||||
@@ -173,14 +178,14 @@ QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char *
|
||||
}
|
||||
|
||||
|
||||
#if defined(Q_WS_X11)
|
||||
#if defined(HAVE_X11_) // FIXME
|
||||
/*!
|
||||
Special constructor for X11, ref. the documentation of
|
||||
QApplication's corresponding constructor. The application identifier
|
||||
will be QCoreApplication::applicationFilePath(). \a dpy, \a visual,
|
||||
and \a cmap are passed on to the QApplication constructor.
|
||||
*/
|
||||
QtSingleApplication::QtSingleApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE cmap)
|
||||
QtSingleApplication::QtSingleApplication(Display *dpy, Qt::HANDLE visual, Qt::HANDLE cmap)
|
||||
: QApplication(dpy, visual, cmap)
|
||||
{
|
||||
sysInit();
|
||||
@@ -206,7 +211,7 @@ QtSingleApplication::QtSingleApplication(Display *dpy, int &argc, char **argv, Q
|
||||
argv, \a visual, and \a cmap are passed on to the QApplication
|
||||
constructor.
|
||||
*/
|
||||
QtSingleApplication::QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap)
|
||||
QtSingleApplication::QtSingleApplication(Display *dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap)
|
||||
: QApplication(dpy, argc, argv, visual, cmap)
|
||||
{
|
||||
sysInit(appId);
|
||||
|
||||
@@ -40,14 +40,21 @@
|
||||
#ifndef QTSINGLEAPPLICATION_H
|
||||
#define QTSINGLEAPPLICATION_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QObject>
|
||||
#include <QWidget>
|
||||
#include <QApplication>
|
||||
#include <QString>
|
||||
|
||||
#if defined(HAVE_X11_) // FIXME
|
||||
# include <X11/Xlib.h>
|
||||
#endif
|
||||
|
||||
class QtLocalPeer;
|
||||
|
||||
#if defined(Q_WS_WIN) || defined(Q_OS_WIN32)
|
||||
#if defined(Q_OS_WIN) || defined(Q_OS_WIN32)
|
||||
# if !defined(QT_QTSINGLEAPPLICATION_EXPORT) && !defined(QT_QTSINGLEAPPLICATION_IMPORT)
|
||||
# define QT_QTSINGLEAPPLICATION_EXPORT
|
||||
# elif defined(QT_QTSINGLEAPPLICATION_IMPORT)
|
||||
@@ -70,10 +77,10 @@ class QT_QTSINGLEAPPLICATION_EXPORT QtSingleApplication : public QApplication
|
||||
public:
|
||||
QtSingleApplication(int &argc, char **argv, bool GUIenabled = true);
|
||||
QtSingleApplication(const QString &id, int &argc, char **argv);
|
||||
#if defined(Q_WS_X11)
|
||||
QtSingleApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0);
|
||||
#if defined(HAVE_X11_) // FIXME
|
||||
QtSingleApplication(Display *dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0);
|
||||
QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0);
|
||||
QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0);
|
||||
QtSingleApplication(Display *dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0);
|
||||
#endif
|
||||
|
||||
bool isRunning();
|
||||
|
||||
@@ -40,6 +40,8 @@
|
||||
#ifndef QTSINGLECOREAPPLICATION_H
|
||||
#define QTSINGLECOREAPPLICATION_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
14
3rdparty/qtwin/CMakeLists.txt
vendored
@@ -1,14 +0,0 @@
|
||||
cmake_minimum_required(VERSION 2.8.11)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
set(QTWIN-SOURCES
|
||||
qtwin.cpp
|
||||
)
|
||||
|
||||
ADD_LIBRARY(qtwin STATIC
|
||||
${QTWIN-SOURCES}
|
||||
)
|
||||
|
||||
target_link_libraries(qtwin
|
||||
Qt5::Widgets
|
||||
)
|
||||
229
3rdparty/qtwin/qtwin.cpp
vendored
@@ -1,229 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Use, modification and distribution is allowed without limitation,
|
||||
** warranty, liability or support of any kind.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qtwin.h"
|
||||
#include <QLibrary>
|
||||
#include <QApplication>
|
||||
#include <QWidget>
|
||||
#include <QList>
|
||||
#include <QPointer>
|
||||
|
||||
#ifdef Q_WS_WIN
|
||||
|
||||
#include <qt_windows.h>
|
||||
|
||||
// Blur behind data structures
|
||||
#define DWM_BB_ENABLE 0x00000001 // fEnable has been specified
|
||||
#define DWM_BB_BLURREGION 0x00000002 // hRgnBlur has been specified
|
||||
#define DWM_BB_TRANSITIONONMAXIMIZED 0x00000004 // fTransitionOnMaximized has been specified
|
||||
#define WM_DWMCOMPOSITIONCHANGED 0x031E // Composition changed window message
|
||||
|
||||
typedef struct _DWM_BLURBEHIND
|
||||
{
|
||||
DWORD dwFlags;
|
||||
BOOL fEnable;
|
||||
HRGN hRgnBlur;
|
||||
BOOL fTransitionOnMaximized;
|
||||
} DWM_BLURBEHIND, *PDWM_BLURBEHIND;
|
||||
|
||||
typedef struct _MARGINS
|
||||
{
|
||||
int cxLeftWidth;
|
||||
int cxRightWidth;
|
||||
int cyTopHeight;
|
||||
int cyBottomHeight;
|
||||
} MARGINS, *PMARGINS;
|
||||
|
||||
typedef HRESULT (WINAPI *PtrDwmIsCompositionEnabled)(BOOL* pfEnabled);
|
||||
typedef HRESULT (WINAPI *PtrDwmExtendFrameIntoClientArea)(HWND hWnd, const MARGINS* pMarInset);
|
||||
typedef HRESULT (WINAPI *PtrDwmEnableBlurBehindWindow)(HWND hWnd, const DWM_BLURBEHIND* pBlurBehind);
|
||||
typedef HRESULT (WINAPI *PtrDwmGetColorizationColor)(DWORD *pcrColorization, BOOL *pfOpaqueBlend);
|
||||
|
||||
static PtrDwmIsCompositionEnabled pDwmIsCompositionEnabled= 0;
|
||||
static PtrDwmEnableBlurBehindWindow pDwmEnableBlurBehindWindow = 0;
|
||||
static PtrDwmExtendFrameIntoClientArea pDwmExtendFrameIntoClientArea = 0;
|
||||
static PtrDwmGetColorizationColor pDwmGetColorizationColor = 0;
|
||||
|
||||
|
||||
/*
|
||||
* Internal helper class that notifies windows if the
|
||||
* DWM compositing state changes and updates the widget
|
||||
* flags correspondingly.
|
||||
*/
|
||||
class WindowNotifier : public QWidget
|
||||
{
|
||||
public:
|
||||
WindowNotifier() { winId(); }
|
||||
void addWidget(QWidget *widget) { widgets.append(widget); }
|
||||
void removeWidget(QWidget *widget) { widgets.removeAll(widget); }
|
||||
bool winEvent(MSG *message, long *result);
|
||||
|
||||
private:
|
||||
QWidgetList widgets;
|
||||
};
|
||||
|
||||
static bool resolveLibs()
|
||||
{
|
||||
if (!pDwmIsCompositionEnabled) {
|
||||
QLibrary dwmLib(QString::toLatin1("dwmapi"));
|
||||
pDwmIsCompositionEnabled =(PtrDwmIsCompositionEnabled)dwmLib.resolve("DwmIsCompositionEnabled");
|
||||
pDwmExtendFrameIntoClientArea = (PtrDwmExtendFrameIntoClientArea)dwmLib.resolve("DwmExtendFrameIntoClientArea");
|
||||
pDwmEnableBlurBehindWindow = (PtrDwmEnableBlurBehindWindow)dwmLib.resolve("DwmEnableBlurBehindWindow");
|
||||
pDwmGetColorizationColor = (PtrDwmGetColorizationColor)dwmLib.resolve("DwmGetColorizationColor");
|
||||
}
|
||||
return pDwmIsCompositionEnabled != 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* Chekcs and returns true if Windows DWM composition
|
||||
* is currently enabled on the system.
|
||||
*
|
||||
* To get live notification on the availability of
|
||||
* this feature, you will currently have to
|
||||
* reimplement winEvent() on your widget and listen
|
||||
* for the WM_DWMCOMPOSITIONCHANGED event to occur.
|
||||
*
|
||||
*/
|
||||
bool QtWin::isCompositionEnabled()
|
||||
{
|
||||
#ifdef Q_WS_WIN
|
||||
if (resolveLibs()) {
|
||||
HRESULT hr = S_OK;
|
||||
BOOL isEnabled = false;
|
||||
hr = pDwmIsCompositionEnabled(&isEnabled);
|
||||
if (SUCCEEDED(hr))
|
||||
return isEnabled;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Enables Blur behind on a Widget.
|
||||
*
|
||||
* \a enable tells if the blur should be enabled or not
|
||||
*/
|
||||
bool QtWin::enableBlurBehindWindow(QWidget *widget, bool enable,
|
||||
const QRegion ®ion)
|
||||
{
|
||||
Q_ASSERT(widget);
|
||||
bool result = false;
|
||||
#ifdef Q_WS_WIN
|
||||
if (resolveLibs()) {
|
||||
DWM_BLURBEHIND bb = {0};
|
||||
HRESULT hr = S_OK;
|
||||
bb.fEnable = enable;
|
||||
bb.dwFlags = DWM_BB_ENABLE;
|
||||
bb.hRgnBlur = NULL;
|
||||
|
||||
if (!region.isEmpty()) {
|
||||
bb.dwFlags |= DWM_BB_BLURREGION;
|
||||
bb.hRgnBlur = region.handle();
|
||||
}
|
||||
|
||||
widget->setAttribute(Qt::WA_TranslucentBackground, enable);
|
||||
widget->setAttribute(Qt::WA_NoSystemBackground, enable);
|
||||
hr = pDwmEnableBlurBehindWindow(widget->winId(), &bb);
|
||||
if (SUCCEEDED(hr)) {
|
||||
result = true;
|
||||
windowNotifier()->addWidget(widget);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
* ExtendFrameIntoClientArea.
|
||||
*
|
||||
* This controls the rendering of the frame inside the window.
|
||||
* Note that passing margins of -1 (the default value) will completely
|
||||
* remove the frame from the window.
|
||||
*
|
||||
* \note you should not call enableBlurBehindWindow before calling
|
||||
* this functions
|
||||
*
|
||||
* \a enable tells if the blur should be enabled or not
|
||||
*/
|
||||
bool QtWin::extendFrameIntoClientArea(QWidget *widget, int left, int top, int right, int bottom)
|
||||
{
|
||||
|
||||
Q_ASSERT(widget);
|
||||
Q_UNUSED(left);
|
||||
Q_UNUSED(top);
|
||||
Q_UNUSED(right);
|
||||
Q_UNUSED(bottom);
|
||||
|
||||
bool result = false;
|
||||
#ifdef Q_WS_WIN
|
||||
if (resolveLibs()) {
|
||||
QLibrary dwmLib(QString::toLatin1("dwmapi"));
|
||||
HRESULT hr = S_OK;
|
||||
MARGINS m = {left, top, right, bottom};
|
||||
hr = pDwmExtendFrameIntoClientArea(widget->winId(), &m);
|
||||
if (SUCCEEDED(hr)) {
|
||||
result = true;
|
||||
windowNotifier()->addWidget(widget);
|
||||
}
|
||||
widget->setAttribute(Qt::WA_TranslucentBackground, result);
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns the current colorizationColor for the window.
|
||||
*
|
||||
* \a enable tells if the blur should be enabled or not
|
||||
*/
|
||||
QColor QtWin::colorizatinColor()
|
||||
{
|
||||
QColor resultColor = QApplication::palette().window().color();
|
||||
|
||||
#ifdef Q_WS_WIN
|
||||
if (resolveLibs()) {
|
||||
DWORD color = 0;
|
||||
BOOL opaque = FALSE;
|
||||
QLibrary dwmLib(QString::toLatin1("dwmapi"));
|
||||
HRESULT hr = S_OK;
|
||||
hr = pDwmGetColorizationColor(&color, &opaque);
|
||||
if (SUCCEEDED(hr))
|
||||
resultColor = QColor(color);
|
||||
}
|
||||
#endif
|
||||
return resultColor;
|
||||
}
|
||||
|
||||
#ifdef Q_WS_WIN
|
||||
WindowNotifier *QtWin::windowNotifier()
|
||||
{
|
||||
static WindowNotifier *windowNotifierInstance = 0;
|
||||
if (!windowNotifierInstance)
|
||||
windowNotifierInstance = new WindowNotifier;
|
||||
return windowNotifierInstance;
|
||||
}
|
||||
|
||||
|
||||
/* Notify all enabled windows that the DWM state changed */
|
||||
bool WindowNotifier::winEvent(MSG *message, long *result)
|
||||
{
|
||||
if (message && message->message == WM_DWMCOMPOSITIONCHANGED) {
|
||||
bool compositionEnabled = QtWin::isCompositionEnabled();
|
||||
foreach(QWidget * widget, widgets) {
|
||||
if (widget) {
|
||||
widget->setAttribute(Qt::WA_NoSystemBackground, compositionEnabled);
|
||||
}
|
||||
widget->update();
|
||||
}
|
||||
}
|
||||
return QWidget::winEvent(message, result);
|
||||
}
|
||||
#endif
|
||||
38
3rdparty/qtwin/qtwin.h
vendored
@@ -1,38 +0,0 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Use, modification and distribution is allowed without limitation,
|
||||
** warranty, liability or support of any kind.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QTWIN_H
|
||||
#define QTWIN_H
|
||||
|
||||
#include <QColor>
|
||||
#include <QWidget>
|
||||
/**
|
||||
* This is a helper class for using the Desktop Window Manager
|
||||
* functionality on Windows 7 and Windows Vista. On other platforms
|
||||
* these functions will simply not do anything.
|
||||
*/
|
||||
|
||||
class WindowNotifier;
|
||||
|
||||
class QtWin
|
||||
{
|
||||
public:
|
||||
static bool enableBlurBehindWindow(QWidget *widget, bool enable = true,
|
||||
const QRegion& region = QRegion());
|
||||
static bool extendFrameIntoClientArea(QWidget *widget,
|
||||
int left = -1, int top = -1,
|
||||
int right = -1, int bottom = -1);
|
||||
static bool isCompositionEnabled();
|
||||
static QColor colorizatinColor();
|
||||
|
||||
private:
|
||||
static WindowNotifier *windowNotifier();
|
||||
};
|
||||
|
||||
#endif // QTWIN_H
|
||||
9
3rdparty/qxt/CMakeLists.txt
vendored
@@ -1,6 +1,14 @@
|
||||
cmake_minimum_required(VERSION 2.8.11)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS})
|
||||
if (NOT WIN32 AND NOT APPLE)
|
||||
find_path(HAVE_QPA_QPLATFORMNATIVEINTERFACE_H qpa/qplatformnativeinterface.h PATHS ${Qt5Gui_PRIVATE_INCLUDE_DIRS})
|
||||
if(NOT HAVE_QPA_QPLATFORMNATIVEINTERFACE_H)
|
||||
message(FATAL_ERROR "Missing qpa/qplatformnativeinterface.h, check that you got the QT private headers installed (package libQt5Gui-private-headers-devel, qtbase5-private-dev or similar)")
|
||||
endif(NOT HAVE_QPA_QPLATFORMNATIVEINTERFACE_H)
|
||||
endif(NOT WIN32 AND NOT APPLE)
|
||||
|
||||
set(QXT-SOURCES
|
||||
qxtglobal.cpp
|
||||
qxtglobalshortcut.cpp
|
||||
@@ -12,7 +20,6 @@ set(QXT-MOC-HEADERS
|
||||
|
||||
find_package(X11)
|
||||
include_directories(${X11_INCLUDE_DIR})
|
||||
include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS})
|
||||
|
||||
if(WIN32)
|
||||
set(QXT-SOURCES ${QXT-SOURCES} qxtglobalshortcut_win.cpp)
|
||||
|
||||
12
3rdparty/qxt/qxtglobalshortcut.cpp
vendored
@@ -38,36 +38,36 @@
|
||||
#include "qxtglobalshortcut_p.h"
|
||||
|
||||
bool QxtGlobalShortcutPrivate::error = false;
|
||||
#ifndef Q_WS_MAC
|
||||
#ifndef Q_OS_MAC
|
||||
int QxtGlobalShortcutPrivate::ref = 0;
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||
QAbstractEventDispatcher::EventFilter QxtGlobalShortcutPrivate::prevEventFilter = 0;
|
||||
#endif
|
||||
#endif // Q_WS_MAC
|
||||
#endif // Q_OS_MAC
|
||||
QHash<QPair<quint32, quint32>, QxtGlobalShortcut*> QxtGlobalShortcutPrivate::shortcuts;
|
||||
|
||||
QxtGlobalShortcutPrivate::QxtGlobalShortcutPrivate() : enabled(true), key(Qt::Key(0)), mods(Qt::NoModifier)
|
||||
{
|
||||
#ifndef Q_WS_MAC
|
||||
#ifndef Q_OS_MAC
|
||||
if (!ref++)
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||
prevEventFilter = QAbstractEventDispatcher::instance()->setEventFilter(eventFilter);
|
||||
#else
|
||||
QAbstractEventDispatcher::instance()->installNativeEventFilter(this);
|
||||
#endif
|
||||
#endif // Q_WS_MAC
|
||||
#endif // Q_OS_MAC
|
||||
}
|
||||
|
||||
QxtGlobalShortcutPrivate::~QxtGlobalShortcutPrivate()
|
||||
{
|
||||
#ifndef Q_WS_MAC
|
||||
#ifndef Q_OS_MAC
|
||||
if (!--ref)
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||
QAbstractEventDispatcher::instance()->setEventFilter(prevEventFilter);
|
||||
#else
|
||||
QAbstractEventDispatcher::instance()->removeNativeEventFilter(this);
|
||||
#endif
|
||||
#endif // Q_WS_MAC
|
||||
#endif // Q_OS_MAC
|
||||
}
|
||||
|
||||
bool QxtGlobalShortcutPrivate::setShortcut(const QKeySequence& shortcut)
|
||||
|
||||
4
3rdparty/qxt/qxtglobalshortcut_p.h
vendored
@@ -59,7 +59,7 @@ public:
|
||||
bool unsetShortcut();
|
||||
|
||||
static bool error;
|
||||
#ifndef Q_WS_MAC
|
||||
#ifndef Q_OS_MAC
|
||||
static int ref;
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||
static QAbstractEventDispatcher::EventFilter prevEventFilter;
|
||||
@@ -67,7 +67,7 @@ public:
|
||||
#else
|
||||
virtual bool nativeEventFilter(const QByteArray & eventType, void * message, long * result);
|
||||
#endif // QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||
#endif // Q_WS_MAC
|
||||
#endif // Q_OS_MAC
|
||||
|
||||
static void activateShortcut(quint32 nativeKey, quint32 nativeMods);
|
||||
|
||||
|
||||
4
3rdparty/sha2/sha2.cpp
vendored
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* FILE: sha2.c
|
||||
* AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2000-2001, Aaron D. Gifford
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -16,7 +16,7 @@
|
||||
* 3. Neither the name of the copyright holder nor the names of contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
|
||||
4
3rdparty/sha2/sha2.h
vendored
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* FILE: sha2.h
|
||||
* AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2000-2001, Aaron D. Gifford
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -16,7 +16,7 @@
|
||||
* 3. Neither the name of the copyright holder nor the names of contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
|
||||
20
3rdparty/taglib/CMakeLists.txt
vendored
@@ -47,6 +47,8 @@ include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/s3m
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/it
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/xm
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/dsf
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/dsdiff
|
||||
${CMAKE_SOURCE_DIR}/3rdparty
|
||||
)
|
||||
|
||||
@@ -161,6 +163,11 @@ set(tag_HDRS
|
||||
s3m/s3mproperties.h
|
||||
xm/xmfile.h
|
||||
xm/xmproperties.h
|
||||
dsf/dsffile.h
|
||||
dsf/dsfproperties.h
|
||||
dsdiff/dsdifffile.h
|
||||
dsdiff/dsdiffproperties.h
|
||||
dsdiff/dsdiffdiintag.h
|
||||
)
|
||||
|
||||
set(mpeg_SRCS
|
||||
@@ -316,6 +323,17 @@ set(xm_SRCS
|
||||
xm/xmproperties.cpp
|
||||
)
|
||||
|
||||
set(dsf_SRCS
|
||||
dsf/dsffile.cpp
|
||||
dsf/dsfproperties.cpp
|
||||
)
|
||||
|
||||
set(dsdiff_SRCS
|
||||
dsdiff/dsdifffile.cpp
|
||||
dsdiff/dsdiffproperties.cpp
|
||||
dsdiff/dsdiffdiintag.cpp
|
||||
)
|
||||
|
||||
set(toolkit_SRCS
|
||||
toolkit/tstring.cpp
|
||||
toolkit/tstringlist.cpp
|
||||
@@ -347,7 +365,7 @@ set(tag_LIB_SRCS
|
||||
${mpeg_SRCS} ${id3v1_SRCS} ${id3v2_SRCS} ${frames_SRCS} ${ogg_SRCS}
|
||||
${vorbis_SRCS} ${oggflacs_SRCS} ${mpc_SRCS} ${ape_SRCS} ${toolkit_SRCS} ${flacs_SRCS}
|
||||
${wavpack_SRCS} ${speex_SRCS} ${trueaudio_SRCS} ${riff_SRCS} ${aiff_SRCS} ${wav_SRCS}
|
||||
${asf_SRCS} ${mp4_SRCS} ${mod_SRCS} ${s3m_SRCS} ${it_SRCS} ${xm_SRCS} ${opus_SRCS}
|
||||
${asf_SRCS} ${mp4_SRCS} ${mod_SRCS} ${s3m_SRCS} ${it_SRCS} ${xm_SRCS} ${opus_SRCS} ${dsf_SRCS} ${dsdiff_SRCS}
|
||||
${zlib_SRCS}
|
||||
tag.cpp
|
||||
tagunion.cpp
|
||||
|
||||
6
3rdparty/taglib/audioproperties.cpp
vendored
@@ -38,6 +38,8 @@
|
||||
#include "vorbisproperties.h"
|
||||
#include "wavproperties.h"
|
||||
#include "wavpackproperties.h"
|
||||
#include "dsfproperties.h"
|
||||
#include "dsdiffproperties.h"
|
||||
|
||||
#include "audioproperties.h"
|
||||
|
||||
@@ -73,6 +75,10 @@ using namespace TagLib;
|
||||
return dynamic_cast<const Vorbis::Properties*>(this)->function_name(); \
|
||||
else if(dynamic_cast<const WavPack::Properties*>(this)) \
|
||||
return dynamic_cast<const WavPack::Properties*>(this)->function_name(); \
|
||||
else if(dynamic_cast<const DSF::Properties*>(this)) \
|
||||
return dynamic_cast<const DSF::Properties*>(this)->function_name(); \
|
||||
else if(dynamic_cast<const DSDIFF::Properties*>(this)) \
|
||||
return dynamic_cast<const DSDIFF::Properties*>(this)->function_name(); \
|
||||
else \
|
||||
return (default_value);
|
||||
|
||||
|
||||
162
3rdparty/taglib/dsdiff/dsdiffdiintag.cpp
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2016 by Damien Plisson, Audirvana
|
||||
email : damien78@audirvana.com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include "dsdiffdiintag.h"
|
||||
#include "tstringlist.h"
|
||||
#include "tpropertymap.h"
|
||||
|
||||
using namespace TagLib;
|
||||
using namespace DSDIFF::DIIN;
|
||||
|
||||
class DSDIFF::DIIN::Tag::TagPrivate
|
||||
{
|
||||
public:
|
||||
TagPrivate()
|
||||
{
|
||||
}
|
||||
|
||||
String title;
|
||||
String artist;
|
||||
};
|
||||
|
||||
DSDIFF::DIIN::Tag::Tag() : TagLib::Tag()
|
||||
{
|
||||
d = new TagPrivate;
|
||||
}
|
||||
|
||||
DSDIFF::DIIN::Tag::~Tag()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
String DSDIFF::DIIN::Tag::title() const
|
||||
{
|
||||
return d->title;
|
||||
}
|
||||
|
||||
String DSDIFF::DIIN::Tag::artist() const
|
||||
{
|
||||
return d->artist;
|
||||
}
|
||||
|
||||
String DSDIFF::DIIN::Tag::album() const
|
||||
{
|
||||
return String();
|
||||
}
|
||||
|
||||
String DSDIFF::DIIN::Tag::comment() const
|
||||
{
|
||||
return String();
|
||||
}
|
||||
|
||||
String DSDIFF::DIIN::Tag::genre() const
|
||||
{
|
||||
return String();
|
||||
}
|
||||
|
||||
unsigned int DSDIFF::DIIN::Tag::year() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int DSDIFF::DIIN::Tag::track() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DSDIFF::DIIN::Tag::setTitle(const String &title)
|
||||
{
|
||||
if(title.isNull() || title.isEmpty())
|
||||
d->title = String();
|
||||
else
|
||||
d->title = title;
|
||||
}
|
||||
|
||||
void DSDIFF::DIIN::Tag::setArtist(const String &artist)
|
||||
{
|
||||
if(artist.isNull() || artist.isEmpty())
|
||||
d->artist = String();
|
||||
else
|
||||
d->artist = artist;
|
||||
}
|
||||
|
||||
void DSDIFF::DIIN::Tag::setAlbum(const String &)
|
||||
{
|
||||
}
|
||||
|
||||
void DSDIFF::DIIN::Tag::setComment(const String &)
|
||||
{
|
||||
}
|
||||
|
||||
void DSDIFF::DIIN::Tag::setGenre(const String &)
|
||||
{
|
||||
}
|
||||
|
||||
void DSDIFF::DIIN::Tag::setYear(unsigned int)
|
||||
{
|
||||
}
|
||||
|
||||
void DSDIFF::DIIN::Tag::setTrack(unsigned int)
|
||||
{
|
||||
}
|
||||
|
||||
PropertyMap DSDIFF::DIIN::Tag::properties() const
|
||||
{
|
||||
PropertyMap properties;
|
||||
properties["TITLE"] = d->title;
|
||||
properties["ARTIST"] = d->artist;
|
||||
return properties;
|
||||
}
|
||||
|
||||
PropertyMap DSDIFF::DIIN::Tag::setProperties(const PropertyMap &origProps)
|
||||
{
|
||||
PropertyMap properties(origProps);
|
||||
properties.removeEmpty();
|
||||
StringList oneValueSet;
|
||||
|
||||
if(properties.contains("TITLE")) {
|
||||
d->title = properties["TITLE"].front();
|
||||
oneValueSet.append("TITLE");
|
||||
} else
|
||||
d->title = String();
|
||||
|
||||
if(properties.contains("ARTIST")) {
|
||||
d->artist = properties["ARTIST"].front();
|
||||
oneValueSet.append("ARTIST");
|
||||
} else
|
||||
d->artist = String();
|
||||
|
||||
// for each tag that has been set above, remove the first entry in the corresponding
|
||||
// value list. The others will be returned as unsupported by this format.
|
||||
for(StringList::Iterator it = oneValueSet.begin(); it != oneValueSet.end(); ++it) {
|
||||
if(properties[*it].size() == 1)
|
||||
properties.erase(*it);
|
||||
else
|
||||
properties[*it].erase(properties[*it].begin());
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
150
3rdparty/taglib/dsdiff/dsdiffdiintag.h
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2016 by Damien Plisson, Audirvana
|
||||
email : damien78@audirvana.com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_DSDIFFDIINTAG_H
|
||||
#define TAGLIB_DSDIFFDIINTAG_H
|
||||
|
||||
#include "tag.h"
|
||||
|
||||
namespace TagLib {
|
||||
|
||||
namespace DSDIFF {
|
||||
|
||||
namespace DIIN {
|
||||
|
||||
/*!
|
||||
* Tags from the Edited Master Chunk Info
|
||||
*
|
||||
* Only Title and Artist tags are supported
|
||||
*/
|
||||
class TAGLIB_EXPORT Tag : public TagLib::Tag
|
||||
{
|
||||
public:
|
||||
Tag();
|
||||
virtual ~Tag();
|
||||
|
||||
/*!
|
||||
* Returns the track name; if no track name is present in the tag
|
||||
* String() will be returned.
|
||||
*/
|
||||
String title() const;
|
||||
|
||||
/*!
|
||||
* Returns the artist name; if no artist name is present in the tag
|
||||
* String() will be returned.
|
||||
*/
|
||||
String artist() const;
|
||||
|
||||
/*!
|
||||
* Not supported. Therefore always returns String().
|
||||
*/
|
||||
String album() const;
|
||||
|
||||
/*!
|
||||
* Not supported. Therefore always returns String().
|
||||
*/
|
||||
String comment() const;
|
||||
|
||||
/*!
|
||||
* Not supported. Therefore always returns String().
|
||||
*/
|
||||
String genre() const;
|
||||
|
||||
/*!
|
||||
* Not supported. Therefore always returns 0.
|
||||
*/
|
||||
unsigned int year() const;
|
||||
|
||||
/*!
|
||||
* Not supported. Therefore always returns 0.
|
||||
*/
|
||||
unsigned int track() const;
|
||||
|
||||
/*!
|
||||
* Sets the title to \a title. If \a title is String() then this
|
||||
* value will be cleared.
|
||||
*/
|
||||
void setTitle(const String &title);
|
||||
|
||||
/*!
|
||||
* Sets the artist to \a artist. If \a artist is String() then this
|
||||
* value will be cleared.
|
||||
*/
|
||||
void setArtist(const String &artist);
|
||||
|
||||
/*!
|
||||
* Not supported and therefore ignored.
|
||||
*/
|
||||
void setAlbum(const String &album);
|
||||
|
||||
/*!
|
||||
* Not supported and therefore ignored.
|
||||
*/
|
||||
void setComment(const String &comment);
|
||||
|
||||
/*!
|
||||
* Not supported and therefore ignored.
|
||||
*/
|
||||
void setGenre(const String &genre);
|
||||
|
||||
/*!
|
||||
* Not supported and therefore ignored.
|
||||
*/
|
||||
void setYear(unsigned int year);
|
||||
|
||||
/*!
|
||||
* Not supported and therefore ignored.
|
||||
*/
|
||||
void setTrack(unsigned int track);
|
||||
|
||||
/*!
|
||||
* Implements the unified property interface -- export function.
|
||||
* Since the DIIN tag is very limited, the exported map is as well.
|
||||
*/
|
||||
PropertyMap properties() const;
|
||||
|
||||
/*!
|
||||
* Implements the unified property interface -- import function.
|
||||
* Because of the limitations of the DIIN file tag, any tags besides
|
||||
* TITLE and ARTIST, will be
|
||||
* returned. Additionally, if the map contains tags with multiple values,
|
||||
* all but the first will be contained in the returned map of unsupported
|
||||
* properties.
|
||||
*/
|
||||
PropertyMap setProperties(const PropertyMap &);
|
||||
|
||||
private:
|
||||
Tag(const Tag &);
|
||||
Tag &operator=(const Tag &);
|
||||
|
||||
class TagPrivate;
|
||||
TagPrivate *d;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
799
3rdparty/taglib/dsdiff/dsdifffile.cpp
vendored
Normal file
@@ -0,0 +1,799 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2016 by Damien Plisson, Audirvana
|
||||
email : damien78@audirvana.com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include <tbytevector.h>
|
||||
#include <tdebug.h>
|
||||
#include <id3v2tag.h>
|
||||
#include <tstringlist.h>
|
||||
#include <tpropertymap.h>
|
||||
|
||||
#include "tagunion.h"
|
||||
#include "dsdifffile.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
struct Chunk64
|
||||
{
|
||||
ByteVector name;
|
||||
unsigned long long offset;
|
||||
unsigned long long size;
|
||||
char padding;
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
enum {
|
||||
ID3v2Index = 0,
|
||||
DIINIndex = 1
|
||||
};
|
||||
enum {
|
||||
PROPChunk = 0,
|
||||
DIINChunk = 1
|
||||
};
|
||||
}
|
||||
|
||||
class DSDIFF::File::FilePrivate
|
||||
{
|
||||
public:
|
||||
FilePrivate() :
|
||||
endianness(BigEndian),
|
||||
size(0),
|
||||
isID3InPropChunk(false),
|
||||
duplicateID3V2chunkIndex(-1),
|
||||
properties(0),
|
||||
id3v2TagChunkID("ID3 "),
|
||||
hasID3v2(false),
|
||||
hasDiin(false)
|
||||
{
|
||||
childChunkIndex[ID3v2Index] = -1;
|
||||
childChunkIndex[DIINIndex] = -1;
|
||||
}
|
||||
|
||||
~FilePrivate()
|
||||
{
|
||||
delete properties;
|
||||
}
|
||||
|
||||
Endianness endianness;
|
||||
ByteVector type;
|
||||
unsigned long long size;
|
||||
ByteVector format;
|
||||
std::vector<Chunk64> chunks;
|
||||
std::vector<Chunk64> childChunks[2];
|
||||
int childChunkIndex[2];
|
||||
bool isID3InPropChunk; // Two possibilities can be found: ID3V2 chunk inside PROP chunk or at root level
|
||||
int duplicateID3V2chunkIndex; // 2 ID3 chunks are present. This is then the index of the one in
|
||||
// PROP chunk that will be removed upon next save to remove duplicates.
|
||||
|
||||
Properties *properties;
|
||||
|
||||
TagUnion tag;
|
||||
|
||||
ByteVector id3v2TagChunkID;
|
||||
|
||||
bool hasID3v2;
|
||||
bool hasDiin;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DSDIFF::File::File(FileName file, bool readProperties,
|
||||
Properties::ReadStyle propertiesStyle) : TagLib::File(file)
|
||||
{
|
||||
d = new FilePrivate;
|
||||
d->endianness = BigEndian;
|
||||
if(isOpen())
|
||||
read(readProperties, propertiesStyle);
|
||||
}
|
||||
|
||||
DSDIFF::File::File(IOStream *stream, bool readProperties,
|
||||
Properties::ReadStyle propertiesStyle) : TagLib::File(stream)
|
||||
{
|
||||
d = new FilePrivate;
|
||||
d->endianness = BigEndian;
|
||||
if(isOpen())
|
||||
read(readProperties, propertiesStyle);
|
||||
}
|
||||
|
||||
DSDIFF::File::~File()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
TagLib::Tag *DSDIFF::File::tag() const
|
||||
{
|
||||
return &d->tag;
|
||||
}
|
||||
|
||||
ID3v2::Tag *DSDIFF::File::ID3v2Tag() const
|
||||
{
|
||||
return d->tag.access<ID3v2::Tag>(ID3v2Index, false);
|
||||
}
|
||||
|
||||
bool DSDIFF::File::hasID3v2Tag() const
|
||||
{
|
||||
return d->hasID3v2;
|
||||
}
|
||||
|
||||
DSDIFF::DIIN::Tag *DSDIFF::File::DIINTag() const
|
||||
{
|
||||
return d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, false);
|
||||
}
|
||||
|
||||
bool DSDIFF::File::hasDIINTag() const
|
||||
{
|
||||
return d->hasDiin;
|
||||
}
|
||||
|
||||
PropertyMap DSDIFF::File::properties() const
|
||||
{
|
||||
if(d->hasID3v2)
|
||||
return d->tag.access<ID3v2::Tag>(ID3v2Index, false)->properties();
|
||||
|
||||
return PropertyMap();
|
||||
}
|
||||
|
||||
void DSDIFF::File::removeUnsupportedProperties(const StringList &unsupported)
|
||||
{
|
||||
if(d->hasID3v2)
|
||||
d->tag.access<ID3v2::Tag>(ID3v2Index, false)->removeUnsupportedProperties(unsupported);
|
||||
|
||||
if(d->hasDiin)
|
||||
d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, false)->removeUnsupportedProperties(unsupported);
|
||||
}
|
||||
|
||||
PropertyMap DSDIFF::File::setProperties(const PropertyMap &properties)
|
||||
{
|
||||
return d->tag.access<ID3v2::Tag>(ID3v2Index, true)->setProperties(properties);
|
||||
}
|
||||
|
||||
DSDIFF::Properties *DSDIFF::File::audioProperties() const
|
||||
{
|
||||
return d->properties;
|
||||
}
|
||||
|
||||
bool DSDIFF::File::save()
|
||||
{
|
||||
if(readOnly()) {
|
||||
debug("DSDIFF::File::save() -- File is read only.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!isValid()) {
|
||||
debug("DSDIFF::File::save() -- Trying to save invalid file.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// First: save ID3V2 chunk
|
||||
ID3v2::Tag *id3v2Tag = d->tag.access<ID3v2::Tag>(ID3v2Index, false);
|
||||
if(d->isID3InPropChunk) {
|
||||
if(id3v2Tag != NULL && !id3v2Tag->isEmpty()) {
|
||||
setChildChunkData(d->id3v2TagChunkID, id3v2Tag->render(), PROPChunk);
|
||||
d->hasID3v2 = true;
|
||||
}
|
||||
else {
|
||||
// Empty tag: remove it
|
||||
setChildChunkData(d->id3v2TagChunkID, ByteVector(), PROPChunk);
|
||||
d->hasID3v2 = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(id3v2Tag != NULL && !id3v2Tag->isEmpty()) {
|
||||
setRootChunkData(d->id3v2TagChunkID, id3v2Tag->render());
|
||||
d->hasID3v2 = true;
|
||||
}
|
||||
else {
|
||||
// Empty tag: remove it
|
||||
setRootChunkData(d->id3v2TagChunkID, ByteVector());
|
||||
d->hasID3v2 = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Second: save the DIIN chunk
|
||||
if(d->hasDiin) {
|
||||
DSDIFF::DIIN::Tag *diinTag = d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, false);
|
||||
|
||||
if(!diinTag->title().isNull() && !diinTag->title().isEmpty()) {
|
||||
ByteVector diinTitle;
|
||||
diinTitle.append(ByteVector::fromUInt(diinTag->title().size(), d->endianness == BigEndian));
|
||||
diinTitle.append(ByteVector::fromCString(diinTag->title().toCString()));
|
||||
setChildChunkData("DITI", diinTitle, DIINChunk);
|
||||
}
|
||||
else
|
||||
setChildChunkData("DITI", ByteVector(), DIINChunk);
|
||||
|
||||
if(!diinTag->artist().isNull() && !diinTag->artist().isEmpty()) {
|
||||
ByteVector diinArtist;
|
||||
diinArtist.append(ByteVector::fromUInt(diinTag->artist().size(), d->endianness == BigEndian));
|
||||
diinArtist.append(ByteVector::fromCString(diinTag->artist().toCString()));
|
||||
setChildChunkData("DIAR", diinArtist, DIINChunk);
|
||||
}
|
||||
else
|
||||
setChildChunkData("DIAR", ByteVector(), DIINChunk);
|
||||
}
|
||||
|
||||
// Third: remove the duplicate ID3V2 chunk (inside PROP chunk) if any
|
||||
if(d->duplicateID3V2chunkIndex>=0) {
|
||||
setChildChunkData(d->duplicateID3V2chunkIndex, ByteVector(), PROPChunk);
|
||||
d->duplicateID3V2chunkIndex = -1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DSDIFF::File::setRootChunkData(unsigned int i, const ByteVector &data)
|
||||
{
|
||||
if(data.isNull() || data.isEmpty()) {
|
||||
// Null data: remove chunk
|
||||
// Update global size
|
||||
unsigned long long removedChunkTotalSize = d->chunks[i].size + d->chunks[i].padding + 12;
|
||||
d->size -= removedChunkTotalSize;
|
||||
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
|
||||
|
||||
removeBlock(d->chunks[i].offset - 12, removedChunkTotalSize);
|
||||
|
||||
// Update the internal offsets
|
||||
for(unsigned long r = i + 1; r < d->chunks.size(); r++)
|
||||
d->chunks[r].offset = d->chunks[r - 1].offset + 12
|
||||
+ d->chunks[r - 1].size + d->chunks[r - 1].padding;
|
||||
|
||||
d->chunks.erase(d->chunks.begin() + i);
|
||||
}
|
||||
else {
|
||||
// Non null data: update chunk
|
||||
// First we update the global size
|
||||
d->size += ((data.size() + 1) & ~1) - (d->chunks[i].size + d->chunks[i].padding);
|
||||
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
|
||||
|
||||
// Now update the specific chunk
|
||||
writeChunk(d->chunks[i].name,
|
||||
data,
|
||||
d->chunks[i].offset - 12,
|
||||
d->chunks[i].size + d->chunks[i].padding + 12);
|
||||
|
||||
d->chunks[i].size = data.size();
|
||||
d->chunks[i].padding = (data.size() & 0x01) ? 1 : 0;
|
||||
|
||||
// Finally update the internal offsets
|
||||
updateRootChunksStructure(i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void DSDIFF::File::setRootChunkData(const ByteVector &name, const ByteVector &data)
|
||||
{
|
||||
if(d->chunks.size() == 0) {
|
||||
debug("DSDIFF::File::setPropChunkData - No valid chunks found.");
|
||||
return;
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < d->chunks.size(); i++) {
|
||||
if(d->chunks[i].name == name) {
|
||||
setRootChunkData(i, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Couldn't find an existing chunk, so let's create a new one.
|
||||
unsigned int i = d->chunks.size() - 1;
|
||||
unsigned long offset = d->chunks[i].offset + d->chunks[i].size + d->chunks[i].padding;
|
||||
|
||||
// First we update the global size
|
||||
d->size += (offset & 1) + ((data.size() + 1) & ~1) + 12;
|
||||
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
|
||||
|
||||
// Now add the chunk to the file
|
||||
writeChunk(name,
|
||||
data,
|
||||
offset,
|
||||
std::max<unsigned long long>(0, length() - offset),
|
||||
(offset & 1) ? 1 : 0);
|
||||
|
||||
Chunk64 chunk;
|
||||
chunk.name = name;
|
||||
chunk.size = data.size();
|
||||
chunk.offset = offset + 12;
|
||||
chunk.padding = (data.size() & 0x01) ? 1 : 0;
|
||||
|
||||
d->chunks.push_back(chunk);
|
||||
}
|
||||
|
||||
void DSDIFF::File::setChildChunkData(unsigned int i,
|
||||
const ByteVector &data,
|
||||
unsigned int childChunkNum)
|
||||
{
|
||||
std::vector<Chunk64> &childChunks = d->childChunks[childChunkNum];
|
||||
|
||||
if(data.isNull() || data.isEmpty()) {
|
||||
// Null data: remove chunk
|
||||
// Update global size
|
||||
unsigned long long removedChunkTotalSize = childChunks[i].size + childChunks[i].padding + 12;
|
||||
d->size -= removedChunkTotalSize;
|
||||
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
|
||||
// Update child chunk size
|
||||
d->chunks[d->childChunkIndex[childChunkNum]].size -= removedChunkTotalSize;
|
||||
insert(ByteVector::fromLongLong(d->chunks[d->childChunkIndex[childChunkNum]].size,
|
||||
d->endianness == BigEndian),
|
||||
d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8);
|
||||
// Remove the chunk
|
||||
removeBlock(childChunks[i].offset - 12, removedChunkTotalSize);
|
||||
|
||||
// Update the internal offsets
|
||||
// For child chunks
|
||||
if((i + 1) < childChunks.size()) {
|
||||
childChunks[i + 1].offset = childChunks[i].offset;
|
||||
i++;
|
||||
for(i++; i < childChunks.size(); i++)
|
||||
childChunks[i].offset = childChunks[i - 1].offset + 12
|
||||
+ childChunks[i - 1].size + childChunks[i - 1].padding;
|
||||
}
|
||||
|
||||
// And for root chunks
|
||||
for(i = d->childChunkIndex[childChunkNum] + 1; i < d->chunks.size(); i++)
|
||||
d->chunks[i].offset = d->chunks[i - 1].offset + 12
|
||||
+ d->chunks[i - 1].size + d->chunks[i - 1].padding;
|
||||
|
||||
childChunks.erase(childChunks.begin() + i);
|
||||
}
|
||||
else {
|
||||
// Non null data: update chunk
|
||||
// First we update the global size
|
||||
d->size += ((data.size() + 1) & ~1) - (childChunks[i].size + childChunks[i].padding);
|
||||
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
|
||||
// And the PROP chunk size
|
||||
d->chunks[d->childChunkIndex[childChunkNum]].size += ((data.size() + 1) & ~1)
|
||||
- (childChunks[i].size + childChunks[i].padding);
|
||||
insert(ByteVector::fromLongLong(d->chunks[d->childChunkIndex[childChunkNum]].size,
|
||||
d->endianness == BigEndian),
|
||||
d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8);
|
||||
|
||||
// Now update the specific chunk
|
||||
writeChunk(childChunks[i].name,
|
||||
data,
|
||||
childChunks[i].offset - 12,
|
||||
childChunks[i].size + childChunks[i].padding + 12);
|
||||
|
||||
childChunks[i].size = data.size();
|
||||
childChunks[i].padding = (data.size() & 0x01) ? 1 : 0;
|
||||
|
||||
// Now update the internal offsets
|
||||
// For child Chunks
|
||||
for(i++; i < childChunks.size(); i++)
|
||||
childChunks[i].offset = childChunks[i - 1].offset + 12
|
||||
+ childChunks[i - 1].size + childChunks[i - 1].padding;
|
||||
|
||||
// And for root chunks
|
||||
updateRootChunksStructure(d->childChunkIndex[childChunkNum] + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void DSDIFF::File::setChildChunkData(const ByteVector &name,
|
||||
const ByteVector &data,
|
||||
unsigned int childChunkNum)
|
||||
{
|
||||
std::vector<Chunk64> &childChunks = d->childChunks[childChunkNum];
|
||||
|
||||
if(childChunks.size() == 0) {
|
||||
debug("DSDIFF::File::setPropChunkData - No valid chunks found.");
|
||||
return;
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < childChunks.size(); i++) {
|
||||
if(childChunks[i].name == name) {
|
||||
setChildChunkData(i, data, childChunkNum);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Do not attempt to remove a non existing chunk
|
||||
if(data.isNull() || data.isEmpty())
|
||||
return;
|
||||
|
||||
// Couldn't find an existing chunk, so let's create a new one.
|
||||
unsigned int i = childChunks.size() - 1;
|
||||
unsigned long offset = childChunks[i].offset + childChunks[i].size + childChunks[i].padding;
|
||||
|
||||
// First we update the global size
|
||||
d->size += (offset & 1) + ((data.size() + 1) & ~1) + 12;
|
||||
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
|
||||
// And the child chunk size
|
||||
d->chunks[d->childChunkIndex[childChunkNum]].size += (offset & 1)
|
||||
+ ((data.size() + 1) & ~1) + 12;
|
||||
insert(ByteVector::fromLongLong(d->chunks[d->childChunkIndex[childChunkNum]].size,
|
||||
d->endianness == BigEndian),
|
||||
d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8);
|
||||
|
||||
// Now add the chunk to the file
|
||||
unsigned long long nextRootChunkIdx = length();
|
||||
if((d->childChunkIndex[childChunkNum] + 1) < static_cast<int>(d->chunks.size()))
|
||||
nextRootChunkIdx = d->chunks[d->childChunkIndex[childChunkNum] + 1].offset - 12;
|
||||
|
||||
writeChunk(name, data, offset,
|
||||
std::max<unsigned long long>(0, nextRootChunkIdx - offset),
|
||||
(offset & 1) ? 1 : 0);
|
||||
|
||||
// For root chunks
|
||||
updateRootChunksStructure(d->childChunkIndex[childChunkNum] + 1);
|
||||
|
||||
Chunk64 chunk;
|
||||
chunk.name = name;
|
||||
chunk.size = data.size();
|
||||
chunk.offset = offset + 12;
|
||||
chunk.padding = (data.size() & 0x01) ? 1 : 0;
|
||||
|
||||
childChunks.push_back(chunk);
|
||||
}
|
||||
|
||||
static bool isValidChunkID(const ByteVector &name)
|
||||
{
|
||||
if(name.size() != 4)
|
||||
return false;
|
||||
|
||||
for(int i = 0; i < 4; i++) {
|
||||
if(name[i] < 32 || name[i] > 127)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DSDIFF::File::updateRootChunksStructure(unsigned int startingChunk)
|
||||
{
|
||||
for(unsigned int i = startingChunk; i < d->chunks.size(); i++)
|
||||
d->chunks[i].offset = d->chunks[i - 1].offset + 12
|
||||
+ d->chunks[i - 1].size + d->chunks[i - 1].padding;
|
||||
|
||||
// Update childchunks structure as well
|
||||
if(d->childChunkIndex[PROPChunk] >= static_cast<int>(startingChunk)) {
|
||||
std::vector<Chunk64> &childChunksToUpdate = d->childChunks[PROPChunk];
|
||||
if(childChunksToUpdate.size() > 0) {
|
||||
childChunksToUpdate[0].offset = d->chunks[d->childChunkIndex[PROPChunk]].offset + 12;
|
||||
for(unsigned int i = 1; i < childChunksToUpdate.size(); i++)
|
||||
childChunksToUpdate[i].offset = childChunksToUpdate[i - 1].offset + 12
|
||||
+ childChunksToUpdate[i - 1].size + childChunksToUpdate[i - 1].padding;
|
||||
}
|
||||
}
|
||||
if(d->childChunkIndex[DIINChunk] >= static_cast<int>(startingChunk)) {
|
||||
std::vector<Chunk64> &childChunksToUpdate = d->childChunks[DIINChunk];
|
||||
if(childChunksToUpdate.size() > 0) {
|
||||
childChunksToUpdate[0].offset = d->chunks[d->childChunkIndex[DIINChunk]].offset + 12;
|
||||
for(unsigned int i = 1; i < childChunksToUpdate.size(); i++)
|
||||
childChunksToUpdate[i].offset = childChunksToUpdate[i - 1].offset + 12
|
||||
+ childChunksToUpdate[i - 1].size + childChunksToUpdate[i - 1].padding;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesStyle)
|
||||
{
|
||||
bool bigEndian = (d->endianness == BigEndian);
|
||||
|
||||
d->type = readBlock(4);
|
||||
d->size = readBlock(8).toLongLong(bigEndian);
|
||||
d->format = readBlock(4);
|
||||
|
||||
// + 12: chunk header at least, fix for additional junk bytes
|
||||
while(tell() + 12 <= length()) {
|
||||
ByteVector chunkName = readBlock(4);
|
||||
unsigned long long chunkSize = readBlock(8).toLongLong(bigEndian);
|
||||
|
||||
if(!isValidChunkID(chunkName)) {
|
||||
debug("DSDIFF::File::read() -- Chunk '" + chunkName + "' has invalid ID");
|
||||
setValid(false);
|
||||
break;
|
||||
}
|
||||
|
||||
if(static_cast<unsigned long long>(tell()) + chunkSize > static_cast<unsigned long long>(length())) {
|
||||
debug("DSDIFF::File::read() -- Chunk '" + chunkName
|
||||
+ "' has invalid size (larger than the file size)");
|
||||
setValid(false);
|
||||
break;
|
||||
}
|
||||
|
||||
Chunk64 chunk;
|
||||
chunk.name = chunkName;
|
||||
chunk.size = chunkSize;
|
||||
chunk.offset = tell();
|
||||
|
||||
seek(chunk.size, Current);
|
||||
|
||||
// Check padding
|
||||
chunk.padding = 0;
|
||||
long uPosNotPadded = tell();
|
||||
if((uPosNotPadded & 0x01) != 0) {
|
||||
ByteVector iByte = readBlock(1);
|
||||
if((iByte.size() != 1) || (iByte[0] != 0))
|
||||
// Not well formed, re-seek
|
||||
seek(uPosNotPadded, Beginning);
|
||||
else
|
||||
chunk.padding = 1;
|
||||
}
|
||||
d->chunks.push_back(chunk);
|
||||
}
|
||||
|
||||
unsigned long long lengthDSDSamplesTimeChannels = 0; // For DSD uncompressed
|
||||
unsigned long long audioDataSizeinBytes = 0; // For computing bitrate
|
||||
unsigned long dstNumFrames = 0; // For DST compressed frames
|
||||
unsigned short dstFrameRate = 0; // For DST compressed frames
|
||||
|
||||
for(unsigned int i = 0; i < d->chunks.size(); i++) {
|
||||
if(d->chunks[i].name == "DSD ") {
|
||||
lengthDSDSamplesTimeChannels = d->chunks[i].size * 8;
|
||||
audioDataSizeinBytes = d->chunks[i].size;
|
||||
}
|
||||
else if(d->chunks[i].name == "DST ") {
|
||||
// Now decode the chunks inside the DST chunk to read the DST Frame Information one
|
||||
long long dstChunkEnd = d->chunks[i].offset + d->chunks[i].size;
|
||||
seek(d->chunks[i].offset);
|
||||
|
||||
audioDataSizeinBytes = d->chunks[i].size;
|
||||
|
||||
while(tell() + 12 <= dstChunkEnd) {
|
||||
ByteVector dstChunkName = readBlock(4);
|
||||
long long dstChunkSize = readBlock(8).toLongLong(bigEndian);
|
||||
|
||||
if(!isValidChunkID(dstChunkName)) {
|
||||
debug("DSDIFF::File::read() -- DST Chunk '" + dstChunkName + "' has invalid ID");
|
||||
setValid(false);
|
||||
break;
|
||||
}
|
||||
|
||||
if(static_cast<long long>(tell()) + dstChunkSize > dstChunkEnd) {
|
||||
debug("DSDIFF::File::read() -- DST Chunk '" + dstChunkName
|
||||
+ "' has invalid size (larger than the DST chunk)");
|
||||
setValid(false);
|
||||
break;
|
||||
}
|
||||
|
||||
if(dstChunkName == "FRTE") {
|
||||
// Found the DST frame information chunk
|
||||
dstNumFrames = readBlock(4).toUInt(bigEndian);
|
||||
dstFrameRate = readBlock(2).toUShort(bigEndian);
|
||||
break; // Found the wanted one, no need to look at the others
|
||||
}
|
||||
|
||||
seek(dstChunkSize, Current);
|
||||
|
||||
// Check padding
|
||||
long uPosNotPadded = tell();
|
||||
if((uPosNotPadded & 0x01) != 0) {
|
||||
ByteVector iByte = readBlock(1);
|
||||
if((iByte.size() != 1) || (iByte[0] != 0))
|
||||
// Not well formed, re-seek
|
||||
seek(uPosNotPadded, Beginning);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(d->chunks[i].name == "PROP") {
|
||||
d->childChunkIndex[PROPChunk] = i;
|
||||
// Now decodes the chunks inside the PROP chunk
|
||||
long long propChunkEnd = d->chunks[i].offset + d->chunks[i].size;
|
||||
seek(d->chunks[i].offset + 4); // +4 to remove the 'SND ' marker at beginning of 'PROP' chunk
|
||||
while(tell() + 12 <= propChunkEnd) {
|
||||
ByteVector propChunkName = readBlock(4);
|
||||
long long propChunkSize = readBlock(8).toLongLong(bigEndian);
|
||||
|
||||
if(!isValidChunkID(propChunkName)) {
|
||||
debug("DSDIFF::File::read() -- PROP Chunk '" + propChunkName + "' has invalid ID");
|
||||
setValid(false);
|
||||
break;
|
||||
}
|
||||
|
||||
if(static_cast<long long>(tell()) + propChunkSize > propChunkEnd) {
|
||||
debug("DSDIFF::File::read() -- PROP Chunk '" + propChunkName
|
||||
+ "' has invalid size (larger than the PROP chunk)");
|
||||
setValid(false);
|
||||
break;
|
||||
}
|
||||
|
||||
Chunk64 chunk;
|
||||
chunk.name = propChunkName;
|
||||
chunk.size = propChunkSize;
|
||||
chunk.offset = tell();
|
||||
|
||||
seek(chunk.size, Current);
|
||||
|
||||
// Check padding
|
||||
chunk.padding = 0;
|
||||
long uPosNotPadded = tell();
|
||||
if((uPosNotPadded & 0x01) != 0) {
|
||||
ByteVector iByte = readBlock(1);
|
||||
if((iByte.size() != 1) || (iByte[0] != 0))
|
||||
// Not well formed, re-seek
|
||||
seek(uPosNotPadded, Beginning);
|
||||
else
|
||||
chunk.padding = 1;
|
||||
}
|
||||
d->childChunks[PROPChunk].push_back(chunk);
|
||||
}
|
||||
}
|
||||
else if(d->chunks[i].name == "DIIN") {
|
||||
d->childChunkIndex[DIINChunk] = i;
|
||||
d->hasDiin = true;
|
||||
// Now decode the chunks inside the DIIN chunk
|
||||
long long diinChunkEnd = d->chunks[i].offset + d->chunks[i].size;
|
||||
seek(d->chunks[i].offset);
|
||||
|
||||
while(tell() + 12 <= diinChunkEnd) {
|
||||
ByteVector diinChunkName = readBlock(4);
|
||||
long long diinChunkSize = readBlock(8).toLongLong(bigEndian);
|
||||
|
||||
if(!isValidChunkID(diinChunkName)) {
|
||||
debug("DSDIFF::File::read() -- DIIN Chunk '" + diinChunkName + "' has invalid ID");
|
||||
setValid(false);
|
||||
break;
|
||||
}
|
||||
|
||||
if(static_cast<long long>(tell()) + diinChunkSize > diinChunkEnd) {
|
||||
debug("DSDIFF::File::read() -- DIIN Chunk '" + diinChunkName
|
||||
+ "' has invalid size (larger than the DIIN chunk)");
|
||||
setValid(false);
|
||||
break;
|
||||
}
|
||||
|
||||
Chunk64 chunk;
|
||||
chunk.name = diinChunkName;
|
||||
chunk.size = diinChunkSize;
|
||||
chunk.offset = tell();
|
||||
|
||||
seek(chunk.size, Current);
|
||||
|
||||
// Check padding
|
||||
chunk.padding = 0;
|
||||
long uPosNotPadded = tell();
|
||||
if((uPosNotPadded & 0x01) != 0) {
|
||||
ByteVector iByte = readBlock(1);
|
||||
if((iByte.size() != 1) || (iByte[0] != 0))
|
||||
// Not well formed, re-seek
|
||||
seek(uPosNotPadded, Beginning);
|
||||
else
|
||||
chunk.padding = 1;
|
||||
}
|
||||
d->childChunks[DIINChunk].push_back(chunk);
|
||||
}
|
||||
}
|
||||
else if(d->chunks[i].name == "ID3 " || d->chunks[i].name == "id3 ") {
|
||||
d->id3v2TagChunkID = d->chunks[i].name;
|
||||
d->tag.set(ID3v2Index, new ID3v2::Tag(this, d->chunks[i].offset));
|
||||
d->isID3InPropChunk = false;
|
||||
d->hasID3v2 = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!isValid())
|
||||
return;
|
||||
|
||||
if(d->childChunkIndex[PROPChunk] < 0) {
|
||||
debug("DSDIFF::File::read() -- no PROP chunk found");
|
||||
setValid(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Read properties
|
||||
|
||||
unsigned int sampleRate=0;
|
||||
unsigned short channels=0;
|
||||
|
||||
for(unsigned int i = 0; i < d->childChunks[PROPChunk].size(); i++) {
|
||||
if(d->childChunks[PROPChunk][i].name == "ID3 " || d->childChunks[PROPChunk][i].name == "id3 ") {
|
||||
if(d->hasID3v2) {
|
||||
d->duplicateID3V2chunkIndex = i;
|
||||
continue; // ID3V2 tag has already been found at root level
|
||||
}
|
||||
d->id3v2TagChunkID = d->childChunks[PROPChunk][i].name;
|
||||
d->tag.set(ID3v2Index, new ID3v2::Tag(this, d->childChunks[PROPChunk][i].offset));
|
||||
d->isID3InPropChunk = true;
|
||||
d->hasID3v2 = true;
|
||||
}
|
||||
else if(d->childChunks[PROPChunk][i].name == "FS ") {
|
||||
// Sample rate
|
||||
seek(d->childChunks[PROPChunk][i].offset);
|
||||
sampleRate = readBlock(4).toUInt(0, 4, bigEndian);
|
||||
}
|
||||
else if(d->childChunks[PROPChunk][i].name == "CHNL") {
|
||||
// Channels
|
||||
seek(d->childChunks[PROPChunk][i].offset);
|
||||
channels = readBlock(2).toShort(0, bigEndian);
|
||||
}
|
||||
}
|
||||
|
||||
// Read title & artist from DIIN chunk
|
||||
d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, true);
|
||||
|
||||
if(d->hasDiin) {
|
||||
for(unsigned int i = 0; i < d->childChunks[DIINChunk].size(); i++) {
|
||||
if(d->childChunks[DIINChunk][i].name == "DITI") {
|
||||
seek(d->childChunks[DIINChunk][i].offset);
|
||||
unsigned int titleStrLength = readBlock(4).toUInt(0, 4, bigEndian);
|
||||
if(titleStrLength <= d->childChunks[DIINChunk][i].size) {
|
||||
ByteVector titleStr = readBlock(titleStrLength);
|
||||
d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, false)->setTitle(titleStr);
|
||||
}
|
||||
}
|
||||
else if(d->childChunks[DIINChunk][i].name == "DIAR") {
|
||||
seek(d->childChunks[DIINChunk][i].offset);
|
||||
unsigned int artistStrLength = readBlock(4).toUInt(0, 4, bigEndian);
|
||||
if(artistStrLength <= d->childChunks[DIINChunk][i].size) {
|
||||
ByteVector artistStr = readBlock(artistStrLength);
|
||||
d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, false)->setArtist(artistStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(readProperties) {
|
||||
if(lengthDSDSamplesTimeChannels == 0) {
|
||||
// DST compressed signal : need to compute length of DSD uncompressed frames
|
||||
if(dstFrameRate > 0)
|
||||
lengthDSDSamplesTimeChannels = (unsigned long long)dstNumFrames
|
||||
* (unsigned long long)sampleRate / (unsigned long long)dstFrameRate;
|
||||
else
|
||||
lengthDSDSamplesTimeChannels = 0;
|
||||
}
|
||||
else {
|
||||
// In DSD uncompressed files, the read number of samples is the total for each channel
|
||||
if(channels > 0)
|
||||
lengthDSDSamplesTimeChannels /= channels;
|
||||
}
|
||||
int bitrate = 0;
|
||||
if(lengthDSDSamplesTimeChannels > 0)
|
||||
bitrate = (audioDataSizeinBytes*8*sampleRate) / lengthDSDSamplesTimeChannels / 1000;
|
||||
|
||||
d->properties = new Properties(sampleRate,
|
||||
channels,
|
||||
lengthDSDSamplesTimeChannels,
|
||||
bitrate,
|
||||
propertiesStyle);
|
||||
}
|
||||
|
||||
if(!ID3v2Tag()) {
|
||||
d->tag.access<ID3v2::Tag>(ID3v2Index, true);
|
||||
d->isID3InPropChunk = false; // By default, ID3 chunk is at root level
|
||||
d->hasID3v2 = false;
|
||||
}
|
||||
}
|
||||
|
||||
void DSDIFF::File::writeChunk(const ByteVector &name, const ByteVector &data,
|
||||
unsigned long long offset, unsigned long replace,
|
||||
unsigned int leadingPadding)
|
||||
{
|
||||
ByteVector combined;
|
||||
if(leadingPadding)
|
||||
combined.append(ByteVector(leadingPadding, '\x00'));
|
||||
|
||||
combined.append(name);
|
||||
combined.append(ByteVector::fromLongLong(data.size(), d->endianness == BigEndian));
|
||||
combined.append(data);
|
||||
if((data.size() & 0x01) != 0)
|
||||
combined.append('\x00');
|
||||
|
||||
insert(combined, offset, replace);
|
||||
}
|
||||
|
||||
251
3rdparty/taglib/dsdiff/dsdifffile.h
vendored
Normal file
@@ -0,0 +1,251 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2016 by Damien Plisson, Audirvana
|
||||
email : damien78@audirvana.com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_DSDIFFFILE_H
|
||||
#define TAGLIB_DSDIFFFILE_H
|
||||
|
||||
#include "rifffile.h"
|
||||
#include "id3v2tag.h"
|
||||
#include "dsdiffproperties.h"
|
||||
#include "dsdiffdiintag.h"
|
||||
|
||||
namespace TagLib {
|
||||
|
||||
//! An implementation of DSDIFF metadata
|
||||
|
||||
/*!
|
||||
* This is implementation of DSDIFF metadata.
|
||||
*
|
||||
* This supports an ID3v2 tag as well as reading stream from the ID3 RIFF
|
||||
* chunk as well as properties from the file.
|
||||
* Description of the DSDIFF format is available
|
||||
* at http://dsd-guide.com/sites/default/files/white-papers/DSDIFF_1.5_Spec.pdf
|
||||
* DSDIFF standard does not explictly specify the ID3V2 chunk
|
||||
* It can be found at the root level, but also sometimes inside the PROP chunk
|
||||
* In addition, title and artist info are stored as part of the standard
|
||||
*/
|
||||
|
||||
namespace DSDIFF {
|
||||
|
||||
//! An implementation of TagLib::File with DSDIFF specific methods
|
||||
|
||||
/*!
|
||||
* This implements and provides an interface for DSDIFF files to the
|
||||
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
|
||||
* the abstract TagLib::File API as well as providing some additional
|
||||
* information specific to DSDIFF files.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT File : public TagLib::File
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* Constructs an DSDIFF file from \a file. If \a readProperties is true
|
||||
* the file's audio properties will also be read.
|
||||
*
|
||||
* \note In the current implementation, \a propertiesStyle is ignored.
|
||||
*/
|
||||
File(FileName file, bool readProperties = true,
|
||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||
|
||||
/*!
|
||||
* Constructs an DSDIFF file from \a stream. If \a readProperties is true
|
||||
* the file's audio properties will also be read.
|
||||
*
|
||||
* \note TagLib will *not* take ownership of the stream, the caller is
|
||||
* responsible for deleting it after the File object.
|
||||
*
|
||||
* \note In the current implementation, \a propertiesStyle is ignored.
|
||||
*/
|
||||
File(IOStream *stream, bool readProperties = true,
|
||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||
|
||||
/*!
|
||||
* Destroys this instance of the File.
|
||||
*/
|
||||
virtual ~File();
|
||||
|
||||
/*!
|
||||
* Returns a pointer to a tag that is the union of the ID3v2 and DIIN
|
||||
* tags. The ID3v2 tag is given priority in reading the information -- if
|
||||
* requested information exists in both the ID3v2 tag and the ID3v1 tag,
|
||||
* the information from the ID3v2 tag will be returned.
|
||||
*
|
||||
* If you would like more granular control over the content of the tags,
|
||||
* with the concession of generality, use the tag-type specific calls.
|
||||
*
|
||||
* \note As this tag is not implemented as an ID3v2 tag or a DIIN tag,
|
||||
* but a union of the two this pointer may not be cast to the specific
|
||||
* tag types.
|
||||
*
|
||||
* \see ID3v2Tag()
|
||||
* \see DIINTag()
|
||||
*/
|
||||
virtual Tag *tag() const;
|
||||
|
||||
/*!
|
||||
* Returns the ID3V2 Tag for this file.
|
||||
*
|
||||
* \note This always returns a valid pointer regardless of whether or not
|
||||
* the file on disk has an ID3v2 tag. Use hasID3v2Tag() to check if the
|
||||
* file on disk actually has an ID3v2 tag.
|
||||
*
|
||||
* \see hasID3v2Tag()
|
||||
*/
|
||||
virtual ID3v2::Tag *ID3v2Tag() const;
|
||||
|
||||
/*!
|
||||
* Returns the DSDIFF DIIN Tag for this file
|
||||
*
|
||||
*/
|
||||
DSDIFF::DIIN::Tag *DIINTag() const;
|
||||
|
||||
/*!
|
||||
* Implements the unified property interface -- export function.
|
||||
* This method forwards to ID3v2::Tag::properties().
|
||||
*/
|
||||
PropertyMap properties() const;
|
||||
|
||||
void removeUnsupportedProperties(const StringList &properties);
|
||||
|
||||
/*!
|
||||
* Implements the unified property interface -- import function.
|
||||
* This method forwards to ID3v2::Tag::setProperties().
|
||||
*/
|
||||
PropertyMap setProperties(const PropertyMap &);
|
||||
|
||||
/*!
|
||||
* Returns the AIFF::Properties for this file. If no audio properties
|
||||
* were read then this will return a null pointer.
|
||||
*/
|
||||
virtual Properties *audioProperties() const;
|
||||
|
||||
/*!
|
||||
* Save the file. If at least one tag -- ID3v1 or DIIN -- exists this
|
||||
* will duplicate its content into the other tag. This returns true
|
||||
* if saving was successful.
|
||||
*
|
||||
* If neither exists or if both tags are empty, this will strip the tags
|
||||
* from the file.
|
||||
*
|
||||
* This is the same as calling save(AllTags);
|
||||
*
|
||||
* If you would like more granular control over the content of the tags,
|
||||
* with the concession of generality, use paramaterized save call below.
|
||||
*
|
||||
* \see save(int tags)
|
||||
*/
|
||||
virtual bool save();
|
||||
|
||||
/*!
|
||||
* Save the file. This will attempt to save all of the tag types that are
|
||||
* specified by OR-ing together TagTypes values. The save() method above
|
||||
* uses AllTags. This returns true if saving was successful.
|
||||
*
|
||||
* This strips all tags not included in the mask, but does not modify them
|
||||
* in memory, so later calls to save() which make use of these tags will
|
||||
* remain valid. This also strips empty tags.
|
||||
*/
|
||||
bool save(int tags);
|
||||
|
||||
/*!
|
||||
* Returns whether or not the file on disk actually has an ID3v2 tag.
|
||||
*
|
||||
* \see ID3v2Tag()
|
||||
*/
|
||||
bool hasID3v2Tag() const;
|
||||
|
||||
/*!
|
||||
* Returns whether or not the file on disk actually has the DSDIFF
|
||||
* Title & Artist tag.
|
||||
*
|
||||
* \see DIINTag()
|
||||
*/
|
||||
bool hasDIINTag() const;
|
||||
|
||||
protected:
|
||||
enum Endianness { BigEndian, LittleEndian };
|
||||
|
||||
File(FileName file, Endianness endianness);
|
||||
File(IOStream *stream, Endianness endianness);
|
||||
|
||||
private:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
|
||||
/*!
|
||||
* Sets the data for the the specified chunk at root level to \a data.
|
||||
*
|
||||
* \warning This will update the file immediately.
|
||||
*/
|
||||
void setRootChunkData(unsigned int i, const ByteVector &data);
|
||||
|
||||
/*!
|
||||
* Sets the data for the root-level chunk \a name to \a data.
|
||||
* If a root-level chunk with the given name already exists
|
||||
* it will be overwritten, otherwise it will be
|
||||
* created after the existing chunks.
|
||||
*
|
||||
* \warning This will update the file immediately.
|
||||
*/
|
||||
void setRootChunkData(const ByteVector &name, const ByteVector &data);
|
||||
|
||||
/*!
|
||||
* Sets the data for the the specified child chunk to \a data.
|
||||
*
|
||||
* If data is null, then remove the chunk
|
||||
*
|
||||
* \warning This will update the file immediately.
|
||||
*/
|
||||
void setChildChunkData(unsigned int i, const ByteVector &data,
|
||||
unsigned int childChunkNum);
|
||||
|
||||
/*!
|
||||
* Sets the data for the child chunk \a name to \a data. If a chunk with
|
||||
* the given name already exists it will be overwritten, otherwise it will
|
||||
* be created after the existing chunks inside child chunk.
|
||||
*
|
||||
* If data is null, then remove the chunks with \a name name
|
||||
*
|
||||
* \warning This will update the file immediately.
|
||||
*/
|
||||
void setChildChunkData(const ByteVector &name, const ByteVector &data,
|
||||
unsigned int childChunkNum);
|
||||
|
||||
void updateRootChunksStructure(unsigned int startingChunk);
|
||||
|
||||
void read(bool readProperties, Properties::ReadStyle propertiesStyle);
|
||||
void writeChunk(const ByteVector &name, const ByteVector &data,
|
||||
unsigned long long offset, unsigned long replace = 0,
|
||||
unsigned int leadingPadding = 0);
|
||||
|
||||
class FilePrivate;
|
||||
FilePrivate *d;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
120
3rdparty/taglib/dsdiff/dsdiffproperties.cpp
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2016 by Damien Plisson, Audirvana
|
||||
email : damien78@audirvana.com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include <tstring.h>
|
||||
#include <tdebug.h>
|
||||
|
||||
#include "dsdiffproperties.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
class DSDIFF::Properties::PropertiesPrivate
|
||||
{
|
||||
public:
|
||||
PropertiesPrivate() :
|
||||
length(0),
|
||||
bitrate(0),
|
||||
sampleRate(0),
|
||||
channels(0),
|
||||
sampleWidth(0),
|
||||
sampleCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
int length;
|
||||
int bitrate;
|
||||
int sampleRate;
|
||||
int channels;
|
||||
int sampleWidth;
|
||||
unsigned long long sampleCount;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DSDIFF::Properties::Properties(const unsigned int sampleRate,
|
||||
const unsigned short channels,
|
||||
const unsigned long long samplesCount,
|
||||
const int bitrate,
|
||||
ReadStyle style) : AudioProperties(style)
|
||||
{
|
||||
d = new PropertiesPrivate;
|
||||
|
||||
d->channels = channels;
|
||||
d->sampleCount = samplesCount;
|
||||
d->sampleWidth = 1;
|
||||
d->sampleRate = sampleRate;
|
||||
d->bitrate = bitrate;
|
||||
d->length = d->sampleRate > 0
|
||||
? static_cast<int>((d->sampleCount * 1000.0) / d->sampleRate + 0.5)
|
||||
: 0;
|
||||
}
|
||||
|
||||
DSDIFF::Properties::~Properties()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
int DSDIFF::Properties::length() const
|
||||
{
|
||||
return lengthInSeconds();
|
||||
}
|
||||
|
||||
int DSDIFF::Properties::lengthInSeconds() const
|
||||
{
|
||||
return d->length / 1000;
|
||||
}
|
||||
|
||||
int DSDIFF::Properties::lengthInMilliseconds() const
|
||||
{
|
||||
return d->length;
|
||||
}
|
||||
|
||||
int DSDIFF::Properties::bitrate() const
|
||||
{
|
||||
return d->bitrate;
|
||||
}
|
||||
|
||||
int DSDIFF::Properties::sampleRate() const
|
||||
{
|
||||
return d->sampleRate;
|
||||
}
|
||||
|
||||
int DSDIFF::Properties::channels() const
|
||||
{
|
||||
return d->channels;
|
||||
}
|
||||
|
||||
int DSDIFF::Properties::bitsPerSample() const
|
||||
{
|
||||
return d->sampleWidth;
|
||||
}
|
||||
|
||||
long long DSDIFF::Properties::sampleCount() const
|
||||
{
|
||||
return d->sampleCount;
|
||||
}
|
||||
|
||||
83
3rdparty/taglib/dsdiff/dsdiffproperties.h
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2016 by Damien Plisson, Audirvana
|
||||
email : damien78@audirvana.com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_DSDIFFPROPERTIES_H
|
||||
#define TAGLIB_DSDIFFPROPERTIES_H
|
||||
|
||||
#include "audioproperties.h"
|
||||
|
||||
namespace TagLib {
|
||||
|
||||
namespace DSDIFF {
|
||||
|
||||
class File;
|
||||
|
||||
//! An implementation of audio property reading for DSDIFF
|
||||
|
||||
/*!
|
||||
* This reads the data from an DSDIFF stream found in the AudioProperties
|
||||
* API.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT Properties : public AudioProperties
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* Create an instance of DSDIFF::Properties with the data read from the
|
||||
* ByteVector \a data.
|
||||
*/
|
||||
Properties(const unsigned int sampleRate, const unsigned short channels,
|
||||
const unsigned long long samplesCount, const int bitrate,
|
||||
ReadStyle style);
|
||||
|
||||
/*!
|
||||
* Destroys this DSDIFF::Properties instance.
|
||||
*/
|
||||
virtual ~Properties();
|
||||
|
||||
// Reimplementations.
|
||||
|
||||
virtual int length() const;
|
||||
virtual int lengthInSeconds() const;
|
||||
virtual int lengthInMilliseconds() const;
|
||||
virtual int bitrate() const;
|
||||
virtual int sampleRate() const;
|
||||
virtual int channels() const;
|
||||
|
||||
int bitsPerSample() const;
|
||||
long long sampleCount() const;
|
||||
|
||||
private:
|
||||
Properties(const Properties &);
|
||||
Properties &operator=(const Properties &);
|
||||
|
||||
class PropertiesPrivate;
|
||||
PropertiesPrivate *d;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
229
3rdparty/taglib/dsf/dsffile.cpp
vendored
Normal file
@@ -0,0 +1,229 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2013 by Stephen F. Booth
|
||||
email : me@sbooth.org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include <tbytevector.h>
|
||||
#include <tdebug.h>
|
||||
#include <id3v2tag.h>
|
||||
#include <tstringlist.h>
|
||||
#include <tpropertymap.h>
|
||||
|
||||
#include "dsffile.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
// The DSF specification is located at http://dsd-guide.com/sites/default/files/white-papers/DSFFileFormatSpec_E.pdf
|
||||
|
||||
class DSF::File::FilePrivate
|
||||
{
|
||||
public:
|
||||
FilePrivate() :
|
||||
properties(0),
|
||||
tag(0)
|
||||
{
|
||||
}
|
||||
|
||||
~FilePrivate()
|
||||
{
|
||||
delete properties;
|
||||
delete tag;
|
||||
}
|
||||
|
||||
long long fileSize;
|
||||
long long metadataOffset;
|
||||
Properties *properties;
|
||||
ID3v2::Tag *tag;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DSF::File::File(FileName file, bool readProperties,
|
||||
Properties::ReadStyle propertiesStyle) :
|
||||
TagLib::File(file),
|
||||
d(new FilePrivate())
|
||||
{
|
||||
if(isOpen())
|
||||
read(readProperties, propertiesStyle);
|
||||
}
|
||||
|
||||
DSF::File::File(IOStream *stream, bool readProperties,
|
||||
Properties::ReadStyle propertiesStyle) :
|
||||
TagLib::File(stream),
|
||||
d(new FilePrivate())
|
||||
{
|
||||
if(isOpen())
|
||||
read(readProperties, propertiesStyle);
|
||||
}
|
||||
|
||||
DSF::File::~File()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
ID3v2::Tag *DSF::File::tag() const
|
||||
{
|
||||
return d->tag;
|
||||
}
|
||||
|
||||
PropertyMap DSF::File::properties() const
|
||||
{
|
||||
return d->tag->properties();
|
||||
}
|
||||
|
||||
PropertyMap DSF::File::setProperties(const PropertyMap &properties)
|
||||
{
|
||||
return d->tag->setProperties(properties);
|
||||
}
|
||||
|
||||
DSF::Properties *DSF::File::audioProperties() const
|
||||
{
|
||||
return d->properties;
|
||||
}
|
||||
|
||||
bool DSF::File::save()
|
||||
{
|
||||
if(readOnly()) {
|
||||
debug("DSF::File::save() -- File is read only.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!isValid()) {
|
||||
debug("DSF::File::save() -- Trying to save invalid file.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Three things must be updated: the file size, the tag data, and the metadata offset
|
||||
|
||||
if(d->tag->isEmpty()) {
|
||||
long long newFileSize = d->metadataOffset ? d->metadataOffset : d->fileSize;
|
||||
|
||||
// Update the file size
|
||||
if(d->fileSize != newFileSize) {
|
||||
insert(ByteVector::fromLongLong(newFileSize, false), 12, 8);
|
||||
d->fileSize = newFileSize;
|
||||
}
|
||||
|
||||
// Update the metadata offset to 0 since there is no longer a tag
|
||||
if(d->metadataOffset) {
|
||||
insert(ByteVector::fromLongLong(0ULL, false), 20, 8);
|
||||
d->metadataOffset = 0;
|
||||
}
|
||||
|
||||
// Delete the old tag
|
||||
truncate(newFileSize);
|
||||
}
|
||||
else {
|
||||
ByteVector tagData = d->tag->render();
|
||||
|
||||
long long newMetadataOffset = d->metadataOffset ? d->metadataOffset : d->fileSize;
|
||||
long long newFileSize = newMetadataOffset + tagData.size();
|
||||
long long oldTagSize = d->fileSize - newMetadataOffset;
|
||||
|
||||
// Update the file size
|
||||
if(d->fileSize != newFileSize) {
|
||||
insert(ByteVector::fromLongLong(newFileSize, false), 12, 8);
|
||||
d->fileSize = newFileSize;
|
||||
}
|
||||
|
||||
// Update the metadata offset
|
||||
if(d->metadataOffset != newMetadataOffset) {
|
||||
insert(ByteVector::fromLongLong(newMetadataOffset, false), 20, 8);
|
||||
d->metadataOffset = newMetadataOffset;
|
||||
}
|
||||
|
||||
// Delete the old tag and write the new one
|
||||
insert(tagData, newMetadataOffset, static_cast<size_t>(oldTagSize));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void DSF::File::read(bool readProperties, Properties::ReadStyle propertiesStyle)
|
||||
{
|
||||
// A DSF file consists of four chunks: DSD chunk, format chunk, data chunk, and metadata chunk
|
||||
// The file format is not chunked in the sense of a RIFF File, though
|
||||
|
||||
// DSD chunk
|
||||
ByteVector chunkName = readBlock(4);
|
||||
if(chunkName != "DSD ") {
|
||||
debug("DSF::File::read() -- Not a DSF file.");
|
||||
setValid(false);
|
||||
return;
|
||||
}
|
||||
|
||||
long long chunkSize = readBlock(8).toLongLong(false);
|
||||
|
||||
// Integrity check
|
||||
if(28 != chunkSize) {
|
||||
debug("DSF::File::read() -- File is corrupted, wrong chunk size");
|
||||
setValid(false);
|
||||
return;
|
||||
}
|
||||
|
||||
d->fileSize = readBlock(8).toLongLong(false);
|
||||
|
||||
// File is malformed or corrupted
|
||||
if(d->fileSize != length()) {
|
||||
debug("DSF::File::read() -- File is corrupted wrong length");
|
||||
setValid(false);
|
||||
return;
|
||||
}
|
||||
|
||||
d->metadataOffset = readBlock(8).toLongLong(false);
|
||||
|
||||
// File is malformed or corrupted
|
||||
if(d->metadataOffset > d->fileSize) {
|
||||
debug("DSF::File::read() -- Invalid metadata offset.");
|
||||
setValid(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Format chunk
|
||||
chunkName = readBlock(4);
|
||||
if(chunkName != "fmt ") {
|
||||
debug("DSF::File::read() -- Missing 'fmt ' chunk.");
|
||||
setValid(false);
|
||||
return;
|
||||
}
|
||||
|
||||
chunkSize = readBlock(8).toLongLong(false);
|
||||
|
||||
d->properties = new Properties(readBlock(chunkSize), propertiesStyle);
|
||||
|
||||
// Skip the data chunk
|
||||
|
||||
// A metadata offset of 0 indicates the absence of an ID3v2 tag
|
||||
if(0 == d->metadataOffset)
|
||||
d->tag = new ID3v2::Tag();
|
||||
else
|
||||
d->tag = new ID3v2::Tag(this, d->metadataOffset);
|
||||
}
|
||||
|
||||
119
3rdparty/taglib/dsf/dsffile.h
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2013 by Stephen F. Booth
|
||||
email : me@sbooth.org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_DSFFILE_H
|
||||
#define TAGLIB_DSFFILE_H
|
||||
|
||||
#include "tfile.h"
|
||||
#include "id3v2tag.h"
|
||||
#include "dsfproperties.h"
|
||||
|
||||
namespace TagLib {
|
||||
|
||||
//! An implementation of DSF metadata
|
||||
|
||||
/*!
|
||||
* This is implementation of DSF metadata.
|
||||
*
|
||||
* This supports an ID3v2 tag as well as properties from the file.
|
||||
*/
|
||||
|
||||
namespace DSF {
|
||||
|
||||
//! An implementation of TagLib::File with DSF specific methods
|
||||
|
||||
/*!
|
||||
* This implements and provides an interface for DSF files to the
|
||||
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
|
||||
* the abstract TagLib::File API as well as providing some additional
|
||||
* information specific to DSF files.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT File : public TagLib::File
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* Contructs an DSF file from \a file. If \a readProperties is true the
|
||||
* file's audio properties will also be read using \a propertiesStyle. If
|
||||
* false, \a propertiesStyle is ignored.
|
||||
*/
|
||||
File(FileName file, bool readProperties = true,
|
||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||
|
||||
/*!
|
||||
* Contructs an DSF file from \a file. If \a readProperties is true the
|
||||
* file's audio properties will also be read using \a propertiesStyle. If
|
||||
* false, \a propertiesStyle is ignored.
|
||||
*/
|
||||
File(IOStream *stream, bool readProperties = true,
|
||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||
|
||||
/*!
|
||||
* Destroys this instance of the File.
|
||||
*/
|
||||
virtual ~File();
|
||||
|
||||
/*!
|
||||
* Returns the Tag for this file.
|
||||
*/
|
||||
ID3v2::Tag *tag() const;
|
||||
|
||||
/*!
|
||||
* Implements the unified property interface -- export function.
|
||||
* This method forwards to ID3v2::Tag::properties().
|
||||
*/
|
||||
PropertyMap properties() const;
|
||||
|
||||
/*!
|
||||
* Implements the unified property interface -- import function.
|
||||
* This method forwards to ID3v2::Tag::setProperties().
|
||||
*/
|
||||
PropertyMap setProperties(const PropertyMap &);
|
||||
|
||||
/*!
|
||||
* Returns the DSF::AudioProperties for this file. If no audio properties
|
||||
* were read then this will return a null pointer.
|
||||
*/
|
||||
virtual Properties *audioProperties() const;
|
||||
|
||||
/*!
|
||||
* Saves the file.
|
||||
*/
|
||||
virtual bool save();
|
||||
|
||||
private:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
|
||||
void read(bool readProperties, Properties::ReadStyle propertiesStyle);
|
||||
|
||||
class FilePrivate;
|
||||
FilePrivate *d;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
161
3rdparty/taglib/dsf/dsfproperties.cpp
vendored
Normal file
@@ -0,0 +1,161 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2013 by Stephen F. Booth
|
||||
email : me@sbooth.org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include <tstring.h>
|
||||
#include <tdebug.h>
|
||||
|
||||
#include "dsfproperties.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
class DSF::Properties::PropertiesPrivate
|
||||
{
|
||||
public:
|
||||
PropertiesPrivate() :
|
||||
formatVersion(0),
|
||||
formatID(0),
|
||||
channelType(0),
|
||||
channelNum(0),
|
||||
samplingFrequency(0),
|
||||
bitsPerSample(0),
|
||||
sampleCount(0),
|
||||
blockSizePerChannel(0),
|
||||
bitrate(0),
|
||||
length(0)
|
||||
{
|
||||
}
|
||||
|
||||
// Nomenclature is from DSF file format specification
|
||||
unsigned int formatVersion;
|
||||
unsigned int formatID;
|
||||
unsigned int channelType;
|
||||
unsigned int channelNum;
|
||||
unsigned int samplingFrequency;
|
||||
unsigned int bitsPerSample;
|
||||
long long sampleCount;
|
||||
unsigned int blockSizePerChannel;
|
||||
|
||||
// Computed
|
||||
unsigned int bitrate;
|
||||
unsigned int length;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DSF::Properties::Properties(const ByteVector &data, ReadStyle style) : TagLib::AudioProperties(style)
|
||||
{
|
||||
d = new PropertiesPrivate;
|
||||
read(data);
|
||||
}
|
||||
|
||||
DSF::Properties::~Properties()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
int DSF::Properties::length() const
|
||||
{
|
||||
return lengthInSeconds();
|
||||
}
|
||||
|
||||
int DSF::Properties::lengthInSeconds() const
|
||||
{
|
||||
return d->length / 1000;
|
||||
}
|
||||
|
||||
int DSF::Properties::lengthInMilliseconds() const
|
||||
{
|
||||
return d->length;
|
||||
}
|
||||
|
||||
int DSF::Properties::bitrate() const
|
||||
{
|
||||
return d->bitrate;
|
||||
}
|
||||
|
||||
int DSF::Properties::sampleRate() const
|
||||
{
|
||||
return d->samplingFrequency;
|
||||
}
|
||||
|
||||
int DSF::Properties::channels() const
|
||||
{
|
||||
return d->channelNum;
|
||||
}
|
||||
|
||||
// DSF specific
|
||||
int DSF::Properties::formatVersion() const
|
||||
{
|
||||
return d->formatVersion;
|
||||
}
|
||||
|
||||
int DSF::Properties::formatID() const
|
||||
{
|
||||
return d->formatID;
|
||||
}
|
||||
|
||||
int DSF::Properties::channelType() const
|
||||
{
|
||||
return d->channelType;
|
||||
}
|
||||
|
||||
int DSF::Properties::bitsPerSample() const
|
||||
{
|
||||
return d->bitsPerSample;
|
||||
}
|
||||
|
||||
long long DSF::Properties::sampleCount() const
|
||||
{
|
||||
return d->sampleCount;
|
||||
}
|
||||
|
||||
int DSF::Properties::blockSizePerChannel() const
|
||||
{
|
||||
return d->blockSizePerChannel;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DSF::Properties::read(const ByteVector &data)
|
||||
{
|
||||
d->formatVersion = data.toUInt(0U,false);
|
||||
d->formatID = data.toUInt(4U,false);
|
||||
d->channelType = data.toUInt(8U,false);
|
||||
d->channelNum = data.toUInt(12U,false);
|
||||
d->samplingFrequency = data.toUInt(16U,false);
|
||||
d->bitsPerSample = data.toUInt(20U,false);
|
||||
d->sampleCount = data.toLongLong(24U,false);
|
||||
d->blockSizePerChannel = data.toUInt(32U,false);
|
||||
|
||||
d->bitrate
|
||||
= static_cast<unsigned int>((d->samplingFrequency * d->bitsPerSample * d->channelNum) / 1000.0 + 0.5);
|
||||
d->length
|
||||
= d->samplingFrequency > 0 ? static_cast<unsigned int>(d->sampleCount * 1000.0 / d->samplingFrequency + 0.5) : 0;
|
||||
}
|
||||
|
||||
92
3rdparty/taglib/dsf/dsfproperties.h
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2013 by Stephen F. Booth
|
||||
email : me@sbooth.org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
|
||||
* 02110-1301 USA *
|
||||
* *
|
||||
* Alternatively, this file is available under the Mozilla Public *
|
||||
* License Version 1.1. You may obtain a copy of the License at *
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_DSFPROPERTIES_H
|
||||
#define TAGLIB_DSFPROPERTIES_H
|
||||
|
||||
#include "audioproperties.h"
|
||||
|
||||
namespace TagLib {
|
||||
|
||||
namespace DSF {
|
||||
|
||||
class File;
|
||||
|
||||
//! An implementation of audio property reading for DSF
|
||||
|
||||
/*!
|
||||
* This reads the data from a DSF stream found in the AudioProperties
|
||||
* API.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT Properties : public TagLib::AudioProperties
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* Create an instance of DSF::AudioProperties with the data read from the
|
||||
* ByteVector \a data.
|
||||
*/
|
||||
Properties(const ByteVector &data, ReadStyle style);
|
||||
|
||||
/*!
|
||||
* Destroys this DSF::AudioProperties instance.
|
||||
*/
|
||||
virtual ~Properties();
|
||||
|
||||
// Reimplementations.
|
||||
|
||||
virtual int length() const;
|
||||
virtual int lengthInSeconds() const;
|
||||
virtual int lengthInMilliseconds() const;
|
||||
virtual int bitrate() const;
|
||||
virtual int sampleRate() const;
|
||||
virtual int channels() const;
|
||||
|
||||
int formatVersion() const;
|
||||
int formatID() const;
|
||||
|
||||
/*!
|
||||
* Channel type values: 1 = mono, 2 = stereo, 3 = 3 channels,
|
||||
* 4 = quad, 5 = 4 channels, 6 = 5 channels, 7 = 5.1 channels
|
||||
*/
|
||||
int channelType() const;
|
||||
int bitsPerSample() const;
|
||||
long long sampleCount() const;
|
||||
int blockSizePerChannel() const;
|
||||
|
||||
private:
|
||||
Properties(const Properties &);
|
||||
Properties &operator=(const Properties &);
|
||||
|
||||
void read(const ByteVector &data);
|
||||
|
||||
class PropertiesPrivate;
|
||||
PropertiesPrivate *d;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
17
3rdparty/taglib/fileref.cpp
vendored
@@ -52,6 +52,8 @@
|
||||
#include "s3mfile.h"
|
||||
#include "itfile.h"
|
||||
#include "xmfile.h"
|
||||
#include "dsffile.h"
|
||||
#include "dsdifffile.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
@@ -135,6 +137,10 @@ namespace
|
||||
return new IT::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "XM")
|
||||
return new XM::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "DFF" || ext == "DSDIFF")
|
||||
return new DSDIFF::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "DSF")
|
||||
return new DSF::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -174,6 +180,10 @@ namespace
|
||||
file = new RIFF::WAV::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(APE::File::isSupported(stream))
|
||||
file = new APE::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
//else if(DSF::File::isSupported(stream))
|
||||
//return new DSDIFF::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
//else if(DSDIFF::File::isSupported(stream))
|
||||
//return new DSF::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
|
||||
// isSupported() only does a quick check, so double check the file here.
|
||||
|
||||
@@ -255,6 +265,10 @@ namespace
|
||||
return new IT::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "XM")
|
||||
return new XM::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "DFF" || ext == "DSDIFF")
|
||||
return new DSDIFF::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "DSF")
|
||||
return new DSF::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -387,6 +401,9 @@ StringList FileRef::defaultFileExtensions()
|
||||
l.append("s3m");
|
||||
l.append("it");
|
||||
l.append("xm");
|
||||
l.append("dsf");
|
||||
l.append("dff");
|
||||
l.append("dsdiff"); // alias for "dff"
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
14
3rdparty/taglib/toolkit/tfile.cpp
vendored
@@ -63,6 +63,8 @@
|
||||
#include "itfile.h"
|
||||
#include "xmfile.h"
|
||||
#include "mp4file.h"
|
||||
#include "dsffile.h"
|
||||
#include "dsdifffile.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
@@ -148,6 +150,10 @@ PropertyMap File::properties() const
|
||||
return dynamic_cast<const MP4::File* >(this)->properties();
|
||||
if(dynamic_cast<const ASF::File* >(this))
|
||||
return dynamic_cast<const ASF::File* >(this)->properties();
|
||||
if(dynamic_cast<const DSF::File* >(this))
|
||||
return dynamic_cast<const DSF::File* >(this)->properties();
|
||||
if(dynamic_cast<const DSDIFF::File* >(this))
|
||||
return dynamic_cast<const DSDIFF::File* >(this)->properties();
|
||||
return tag()->properties();
|
||||
}
|
||||
|
||||
@@ -177,6 +183,10 @@ void File::removeUnsupportedProperties(const StringList &properties)
|
||||
dynamic_cast<MP4::File* >(this)->removeUnsupportedProperties(properties);
|
||||
else if(dynamic_cast<ASF::File* >(this))
|
||||
dynamic_cast<ASF::File* >(this)->removeUnsupportedProperties(properties);
|
||||
else if(dynamic_cast<DSF::File* >(this))
|
||||
dynamic_cast<DSF::File* >(this)->removeUnsupportedProperties(properties);
|
||||
else if(dynamic_cast<DSDIFF::File* >(this))
|
||||
dynamic_cast<DSDIFF::File* >(this)->removeUnsupportedProperties(properties);
|
||||
else
|
||||
tag()->removeUnsupportedProperties(properties);
|
||||
}
|
||||
@@ -219,6 +229,10 @@ PropertyMap File::setProperties(const PropertyMap &properties)
|
||||
return dynamic_cast<MP4::File* >(this)->setProperties(properties);
|
||||
else if(dynamic_cast<ASF::File* >(this))
|
||||
return dynamic_cast<ASF::File* >(this)->setProperties(properties);
|
||||
else if(dynamic_cast<DSF::File* >(this))
|
||||
return dynamic_cast<DSF::File* >(this)->setProperties(properties);
|
||||
else if(dynamic_cast<DSDIFF::File* >(this))
|
||||
return dynamic_cast<DSDIFF::File* >(this)->setProperties(properties);
|
||||
else
|
||||
return tag()->setProperties(properties);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,9 @@
|
||||
|
||||
project(strawberry)
|
||||
cmake_minimum_required(VERSION 2.8.11)
|
||||
cmake_policy(SET CMP0054 NEW)
|
||||
if(${CMAKE_VERSION} VERSION_GREATER "3.0")
|
||||
cmake_policy(SET CMP0054 NEW)
|
||||
endif()
|
||||
if(${CMAKE_VERSION} VERSION_GREATER "3.10.3")
|
||||
cmake_policy(SET CMP0072 NEW)
|
||||
endif()
|
||||
@@ -32,6 +34,7 @@ include(cmake/Summary.cmake)
|
||||
include(cmake/OptionalSource.cmake)
|
||||
include(cmake/ParseArguments.cmake)
|
||||
include(cmake/Rpm.cmake)
|
||||
include(cmake/Deb.cmake)
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
set(LINUX 1)
|
||||
@@ -82,18 +85,21 @@ find_package(Protobuf REQUIRED)
|
||||
find_library(PROTOBUF_STATIC_LIBRARY libprotobuf.a libprotobuf)
|
||||
if(LINUX)
|
||||
find_package(ALSA REQUIRED)
|
||||
find_package(DBus REQUIRED)
|
||||
pkg_check_modules(DBUS REQUIRED dbus-1)
|
||||
else(LINUX)
|
||||
find_package(ALSA)
|
||||
find_package(DBus)
|
||||
pkg_check_modules(DBUS dbus-1)
|
||||
endif(LINUX)
|
||||
if(ALSA_FOUND)
|
||||
set(HAVE_ALSA ON)
|
||||
endif()
|
||||
find_package(X11)
|
||||
if (NOT APPLE)
|
||||
find_package(X11)
|
||||
endif()
|
||||
if(X11_FOUND)
|
||||
set(HAVE_X11 ON)
|
||||
endif()
|
||||
find_package(OpenGL REQUIRED)
|
||||
pkg_check_modules(GSTREAMER gstreamer-1.0)
|
||||
pkg_check_modules(GSTREAMER_BASE gstreamer-base-1.0)
|
||||
pkg_check_modules(GSTREAMER_AUDIO gstreamer-audio-1.0)
|
||||
@@ -103,9 +109,11 @@ pkg_check_modules(LIBXINE libxine)
|
||||
pkg_check_modules(LIBVLC libvlc)
|
||||
pkg_check_modules(PHONON phonon4qt5)
|
||||
pkg_check_modules(SQLITE REQUIRED sqlite3>=3.7)
|
||||
find_package(OpenGL REQUIRED)
|
||||
pkg_check_modules(CHROMAPRINT REQUIRED libchromaprint)
|
||||
pkg_check_modules(LIBPULSE libpulse)
|
||||
pkg_check_modules(CHROMAPRINT libchromaprint)
|
||||
#if(CHROMAPRINT_FOUND)
|
||||
# set(HAVE_CHROMAPRINT ON)
|
||||
#endif()
|
||||
pkg_check_modules(LIBGPOD libgpod-1.0>=0.7.92)
|
||||
pkg_check_modules(LIBMTP libmtp>=1.0)
|
||||
pkg_check_modules(IMOBILEDEVICE libimobiledevice-1.0)
|
||||
@@ -129,6 +137,9 @@ endif()
|
||||
if(APPLE)
|
||||
find_package(Qt5 REQUIRED COMPONENTS MacExtras)
|
||||
endif()
|
||||
if(WIN32)
|
||||
find_package(Qt5 REQUIRED COMPONENTS WinExtras)
|
||||
endif()
|
||||
|
||||
set(QT_LIBRARIES Qt5::Core Qt5::Concurrent Qt5::Widgets Qt5::Network Qt5::Sql Qt5::OpenGL Qt5::Xml)
|
||||
|
||||
@@ -141,11 +152,9 @@ endif()
|
||||
if(APPLE)
|
||||
set(QT_LIBRARIES ${QT_LIBRARIES} Qt5::MacExtras)
|
||||
endif()
|
||||
|
||||
# Don't try to use webkit if their include directories couldn't be found.
|
||||
if (NOT QT_QTWEBKIT_INCLUDE_DIR)
|
||||
set (QT_USE_QTWEBKIT 0)
|
||||
endif (NOT QT_QTWEBKIT_INCLUDE_DIR)
|
||||
if(WIN32)
|
||||
set(QT_LIBRARIES ${QT_LIBRARIES} Qt5::WinExtras)
|
||||
endif()
|
||||
|
||||
# TAGLIB
|
||||
pkg_check_modules(TAGLIB taglib)
|
||||
@@ -162,6 +171,10 @@ if (TAGLIB_FOUND AND USE_SYSTEM_TAGLIB)
|
||||
set(CMAKE_REQUIRED_LIBRARIES "${TAGLIB_LIBRARIES}")
|
||||
set(CMAKE_REQUIRED_INCLUDES)
|
||||
set(CMAKE_REQUIRED_LIBRARIES)
|
||||
find_path(HAVE_TAGLIB_DSFFILE_H taglib/dsffile.h)
|
||||
if(HAVE_TAGLIB_DSFFILE_H)
|
||||
set(HAVE_TAGLIB_DSFFILE ON)
|
||||
endif(HAVE_TAGLIB_DSFFILE_H)
|
||||
else()
|
||||
message(STATUS "Using builtin taglib library")
|
||||
set(TAGLIB_INCLUDE_DIRS "${CMAKE_BINARY_DIR}/3rdparty/taglib/headers/taglib/;${CMAKE_BINARY_DIR}/3rdparty/taglib/headers/")
|
||||
@@ -169,6 +182,7 @@ else()
|
||||
set(TAGLIB_LIBRARIES tag)
|
||||
add_subdirectory(3rdparty/utf8-cpp)
|
||||
add_subdirectory(3rdparty/taglib)
|
||||
set(HAVE_TAGLIB_DSFFILE ON)
|
||||
endif()
|
||||
|
||||
# LASTFM
|
||||
@@ -179,9 +193,6 @@ if(LASTFM5_INCLUDE_DIRS AND LASTFM51_INCLUDE_DIRS)
|
||||
set(HAVE_LIBLASTFM1 ON)
|
||||
endif()
|
||||
|
||||
# CHECK INCLUDES
|
||||
CHECK_INCLUDE_FILES(chromaprint.h CHROMAPRINT_H)
|
||||
|
||||
# Use system sha2 if it's available
|
||||
find_path(SHA2_INCLUDE_DIRS sha2.h)
|
||||
find_library(SHA2_LIBRARIES sha2)
|
||||
@@ -233,11 +244,6 @@ endif (USE_SYSTEM_QXT)
|
||||
set(QOCOA_LIBRARIES Qocoa)
|
||||
add_subdirectory(3rdparty/qocoa)
|
||||
|
||||
# Windows
|
||||
if (WIN32)
|
||||
add_subdirectory(3rdparty/qtwin)
|
||||
endif (WIN32)
|
||||
|
||||
if (APPLE)
|
||||
find_library(SPARKLE Sparkle)
|
||||
add_subdirectory(3rdparty/SPMediaKeyTap)
|
||||
@@ -281,34 +287,22 @@ optional_component(PHONON OFF "Engine: Phonon backend"
|
||||
DEPENDS "phonon4qt5" PHONON_FOUND
|
||||
)
|
||||
|
||||
optional_component(AUDIOCD ON "Devices: Audio CD support"
|
||||
DEPENDS "libcdio" CDIO_FOUND
|
||||
)
|
||||
|
||||
optional_component(LIBGPOD ON "Devices: iPod classic support"
|
||||
DEPENDS "libgpod" LIBGPOD_FOUND
|
||||
)
|
||||
|
||||
optional_component(GIO ON "Devices: GIO device backend"
|
||||
DEPENDS "libgio" GIO_FOUND
|
||||
DEPENDS "Unix or Windows" "NOT APPLE"
|
||||
)
|
||||
|
||||
optional_component(IMOBILEDEVICE ON "Devices: iPod Touch, iPhone, iPad support"
|
||||
DEPENDS "libimobiledevice" IMOBILEDEVICE_FOUND
|
||||
DEPENDS "libplist" PLIST_FOUND
|
||||
DEPENDS "libusbmuxd" USBMUXD_FOUND
|
||||
DEPENDS "iPod classic support" HAVE_LIBGPOD
|
||||
)
|
||||
|
||||
optional_component(LIBMTP ON "Devices: MTP support"
|
||||
DEPENDS "libmtp" LIBMTP_FOUND
|
||||
optional_component(LIBPULSE ON "Pulse audio integration"
|
||||
DEPENDS "libpulse" LIBPULSE_FOUND
|
||||
)
|
||||
|
||||
optional_component(LIBLASTFM ON "Last.fm album cover provider"
|
||||
DEPENDS "liblastfm" LASTFM5_LIBRARIES LASTFM5_INCLUDE_DIRS
|
||||
)
|
||||
|
||||
optional_component(CHROMAPRINT ON "Chromaprint support / Tag fetching from Musicbrainz"
|
||||
DEPENDS "chromaprint" CHROMAPRINT_FOUND
|
||||
)
|
||||
|
||||
optional_component(AUDIOCD ON "Devices: Audio CD support"
|
||||
DEPENDS "libcdio" CDIO_FOUND
|
||||
)
|
||||
|
||||
optional_component(DEVICEKIT ON "Devices: DeviceKit backend"
|
||||
DEPENDS "D-Bus support" DBUS_FOUND
|
||||
)
|
||||
@@ -317,8 +311,24 @@ optional_component(UDISKS2 ON "Devices: UDisks2 backend"
|
||||
DEPENDS "D-Bus support" DBUS_FOUND
|
||||
)
|
||||
|
||||
optional_component(LIBPULSE ON "Pulse audio integration"
|
||||
DEPENDS "libpulse" LIBPULSE_FOUND
|
||||
optional_component(GIO ON "Devices: GIO device backend"
|
||||
DEPENDS "libgio" GIO_FOUND
|
||||
DEPENDS "Unix or Windows" "NOT APPLE"
|
||||
)
|
||||
|
||||
optional_component(LIBGPOD ON "Devices: iPod classic support"
|
||||
DEPENDS "libgpod" LIBGPOD_FOUND
|
||||
)
|
||||
|
||||
optional_component(LIBMTP ON "Devices: MTP support"
|
||||
DEPENDS "libmtp" LIBMTP_FOUND
|
||||
)
|
||||
|
||||
optional_component(IMOBILEDEVICE ON "Devices: iPod Touch, iPhone, iPad support"
|
||||
DEPENDS "libimobiledevice" IMOBILEDEVICE_FOUND
|
||||
DEPENDS "libplist" PLIST_FOUND
|
||||
DEPENDS "libusbmuxd" USBMUXD_FOUND
|
||||
DEPENDS "iPod classic support" LIBGPOD_FOUND
|
||||
)
|
||||
|
||||
optional_component(SPARKLE ON "Sparkle integration"
|
||||
|
||||
38
Changelog
@@ -2,6 +2,44 @@ Strawberry Music Player
|
||||
=======================
|
||||
ChangeLog
|
||||
|
||||
Version 0.3.3:
|
||||
|
||||
* Fixed Tidal login
|
||||
|
||||
Version 0.3.2:
|
||||
|
||||
* Fixed search error not shown in Tidal search
|
||||
* Added URL handler for Tidal, now retriving URL's when playing instead of when searching
|
||||
* Fixed bug in pipeline not setting url
|
||||
* Fixed bug setting wrong temporary metadata
|
||||
* Removed device module from windows, since it's not implemented for windows
|
||||
* Added support for both ALSA hw and plughw
|
||||
* Added option to change url stream scheme for Tidal
|
||||
* Added encoding of Tidal token in the source code
|
||||
* Added encoding of Tidal password in the configuration
|
||||
|
||||
Version 0.3.1:
|
||||
|
||||
* Added new lyrics provider with lyrics from AudD and API Seeds
|
||||
* New improved context widget with albums and lyrics
|
||||
* Fixed playing and context widget getting stuck in play mode when there was an error
|
||||
* Changed icons for artists in collection, tidal and cover manager
|
||||
* Removed "search" icon from "Search automatically" checkbox (right click) that looked ugly
|
||||
* Removed some unused widgets from the src/widgets directory
|
||||
* Fixed initial size of window and side panel
|
||||
* Fixed saving window size correctly
|
||||
* Added Tidal support
|
||||
* Disabled Amazon cover provider because of revoked API key
|
||||
* Removed broken xine fader
|
||||
* Made chromeprint optional
|
||||
* Added missing names to about dialog
|
||||
* Made xine enabled only for window debug
|
||||
* Removed dead code
|
||||
* Added DSF and DSDIFF/DFF support
|
||||
* Fixed tagreader crash when saving tags to MP3 files
|
||||
* Added support for reading/writing lyrics to tags
|
||||
* Fixed saving tags (APE) for WavPack files
|
||||
|
||||
Version 0.2.1:
|
||||
|
||||
* Fixed crash with newer Qt
|
||||
|
||||
18
Dockerfile
Normal file
@@ -0,0 +1,18 @@
|
||||
from opensuse:tumbleweed
|
||||
|
||||
run zypper --non-interactive --gpg-auto-import-keys ref
|
||||
run zypper --non-interactive --gpg-auto-import-keys dup -l -y
|
||||
|
||||
run zypper --non-interactive --gpg-auto-import-keys install \
|
||||
lsb-release \
|
||||
git tar make cmake gcc gcc-c++ pkg-config \
|
||||
glibc-devel glib2-devel glib2-tools dbus-1-devel alsa-devel libpulse-devel libnotify-devel \
|
||||
boost-devel protobuf-devel sqlite3-devel taglib-devel \
|
||||
gstreamer-devel gstreamer-plugins-base-devel libxine-devel vlc-devel \
|
||||
libQt5Core-devel libQt5Gui-devel libQt5Widgets-devel libQt5Concurrent-devel libQt5Network-devel libQt5OpenGL-devel libQt5Sql-devel \
|
||||
libqt5-qtx11extras-devel libQt5Gui-private-headers-devel libqt5-qtbase-common-devel liblastfm-qt5-devel \
|
||||
libcdio-devel libgpod-devel libplist-devel libmtp-devel libusbmuxd-devel libchromaprint-devel
|
||||
|
||||
run mkdir -p /usr/src/app
|
||||
workdir /usr/src/app
|
||||
copy . /usr/src/app
|
||||
21
README.md
@@ -1,22 +1,33 @@
|
||||
:strawberry: Strawberry Music Player
|
||||
:strawberry: Strawberry Music Player [](https://travis-ci.org/jonaski/strawberry)
|
||||
=======================
|
||||
|
||||
Strawberry is a audio player and music collection organizer. It is a fork of Clementine created in 2013 with a diffrent goal.
|
||||
It's written in C++ and Qt 5. The name is inspired by the band Strawbs.
|
||||
|
||||
* Website: http://www.strawbs.org/
|
||||
* Github: https://github.com/jonaski/strawberry
|
||||
* Buildbot: http://buildbot.strawbs.net/
|
||||
* Latest builds: http://builds.strawbs.org/
|
||||
|
||||
### :heavy_check_mark: Features:
|
||||
|
||||
* Play and organize music
|
||||
* Supports WAV, FLAC, WavPack, DSF, DSDIFF, Ogg Vorbis, Speex, MPC, TrueAudio, AIFF, MP4, MP3 and ASF
|
||||
* Audio CD playback
|
||||
* Native desktop notifications
|
||||
* Playlists in multiple formats
|
||||
* Advanced output and device options with support for bit perfect playback on Linux
|
||||
* Edit tags on music files
|
||||
* Fetch tags from MusicBrainz
|
||||
* Album cover art from Lastfm, Musicbrainz, Discogs and Amazon
|
||||
* Album cover art from Last.fm, Musicbrainz and Discogs
|
||||
* Song lyrics from AudD and API Seeds
|
||||
* Support for multiple backends
|
||||
* Audio analyzer
|
||||
* Equalizer
|
||||
* Transfer music to iPod, iPhone, MTP or mass-storage USB player
|
||||
* Integrated Tidal support
|
||||
|
||||
It has so far been tested to work on Linux, OpenBSD and Windows (cross compiled using mingw).
|
||||
|
||||
It has so far been tested to work on Linux, OpenBSD, MacOs and Windows.
|
||||
|
||||
### :heavy_exclamation_mark: Requirements
|
||||
|
||||
@@ -28,7 +39,7 @@ To build Strawberry from source you need the following installed on your system
|
||||
* [GCC](https://gcc.gnu.org/) or [clang](https://clang.llvm.org/) compiler
|
||||
* [Protobuf library and compiler](https://developers.google.com/protocol-buffers/)
|
||||
* [Boost development headers](https://www.boost.org/)
|
||||
* [Qt 5 with components Core, Widgets, Network, Sql, Xml, OpenGL, Concurrent, Test, WebKitWidget, X11Extras and DBus](https://www.qt.io/)
|
||||
* [Qt 5 with components Core, Gui, Widgets, Concurrent, Network, Sql, Xml, OpenGL, X11Extras and DBus](https://www.qt.io/)
|
||||
* [SQLite3](https://www.sqlite.org)
|
||||
* [TagLib 1.11.1 or higher](http://taglib.org/)
|
||||
* [Chromaprint library](https://acoustid.org/chromaprint)
|
||||
|
||||
6
cmake/Deb.cmake
Normal file
@@ -0,0 +1,6 @@
|
||||
add_custom_target(deb
|
||||
#COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_SOURCE_DIR}/dist/debian ${CMAKE_BINARY_DIR}/debian
|
||||
COMMAND cp -r -p ${CMAKE_SOURCE_DIR}/dist/debian ${CMAKE_BINARY_DIR}/
|
||||
COMMAND dpkg-buildpackage -b -d -uc -us
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
@@ -1,43 +0,0 @@
|
||||
if(DBUS_INCLUDE_DIR AND DBUS_LIBRARY AND DBUS_ARCH_INCLUDE_DIR)
|
||||
# Already in cache, be silent
|
||||
set(DBUS_FIND_QUIETLY TRUE)
|
||||
endif(DBUS_INCLUDE_DIR AND DBUS_LIBRARY AND DBUS_ARCH_INCLUDE_DIR)
|
||||
|
||||
set(DBUS_LIBRARY)
|
||||
set(DBUS_INCLUDE_DIR)
|
||||
set(DBUS_ARCH_INCLUDE_DIR)
|
||||
|
||||
FIND_PATH(DBUS_INCLUDE_DIR dbus/dbus.h
|
||||
/usr/include
|
||||
/usr/include/dbus-1.0
|
||||
/usr/local/include
|
||||
/usr/local/include/dbus-1.0
|
||||
)
|
||||
|
||||
FIND_PATH(DBUS_ARCH_INCLUDE_DIR dbus/dbus-arch-deps.h
|
||||
/usr/lib/include
|
||||
/usr/lib/dbus-1.0/include
|
||||
/usr/lib64/include
|
||||
/usr/lib64/dbus-1.0/include
|
||||
/usr/local/lib/include
|
||||
/usr/local/lib/dbus-1.0/include
|
||||
/usr/local/lib64/include
|
||||
/usr/local/lib64/dbus-1.0/include
|
||||
)
|
||||
|
||||
FIND_LIBRARY(DBUS_LIBRARY NAMES dbus-1 dbus
|
||||
PATHS
|
||||
/usr/lib
|
||||
/usr/lib64
|
||||
/usr/local/lib
|
||||
/usr/local/lib64
|
||||
)
|
||||
|
||||
if(DBUS_INCLUDE_DIR AND DBUS_LIBRARY AND DBUS_ARCH_INCLUDE_DIR)
|
||||
MESSAGE(STATUS "D-Bus found: includes in ${DBUS_INCLUDE_DIR}, library in ${DBUS_LIBRARY}")
|
||||
set(DBUS_FOUND TRUE)
|
||||
else(DBUS_INCLUDE_DIR AND DBUS_LIBRARY AND DBUS_ARCH_INCLUDE_DIR)
|
||||
MESSAGE(STATUS "D-Bus not found")
|
||||
endif(DBUS_INCLUDE_DIR AND DBUS_LIBRARY AND DBUS_ARCH_INCLUDE_DIR)
|
||||
|
||||
MARK_AS_ADVANCED(DBUS_INCLUDE_DIR DBUS_LIBRARY DBUS_ARCH_INCLUDE_DIR)
|
||||
@@ -1,12 +1,65 @@
|
||||
set(RPMBUILD_DIR ~/rpmbuild CACHE STRING "Rpmbuild directory, for the rpm target")
|
||||
set(MOCK_COMMAND mock CACHE STRING "Command to use for running mock")
|
||||
set(MOCK_CHROOT suse-x86_64 CACHE STRING "Chroot to use when building an rpm with mock")
|
||||
set(RPM_DISTRO suse CACHE STRING "Suffix of the rpm file")
|
||||
set(RPM_ARCH x86_64 CACHE STRING "Architecture of the rpm file")
|
||||
find_program(LSB_RELEASE_EXEC lsb_release)
|
||||
|
||||
add_custom_target(rpm
|
||||
COMMAND ${CMAKE_SOURCE_DIR}/dist/scripts/maketarball.sh
|
||||
COMMAND ${CMAKE_COMMAND} -E copy strawberry-${STRAWBERRY_VERSION_PACKAGE}.tar.xz ${RPMBUILD_DIR}/SOURCES/
|
||||
COMMAND rpmbuild -bs ${CMAKE_SOURCE_DIR}/dist/rpm/strawberry.spec
|
||||
COMMAND rpmbuild -bb ${CMAKE_SOURCE_DIR}/dist/rpm/strawberry.spec
|
||||
)
|
||||
if (LSB_RELEASE_EXEC)
|
||||
execute_process(COMMAND /bin/sh "-c" "${LSB_RELEASE_EXEC} -is | tr '[:upper:]' '[:lower:]' | cut -d' ' -f1"
|
||||
OUTPUT_VARIABLE DIST_NAME
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
execute_process(COMMAND /bin/sh "-c" "${LSB_RELEASE_EXEC} -ds | tr '[:upper:]' '[:lower:]' | sed 's/\"//g' | cut -d' ' -f2"
|
||||
OUTPUT_VARIABLE DIST_RELEASE
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
execute_process(COMMAND /bin/sh "-c" "${LSB_RELEASE_EXEC} -ds | tr '[:upper:]' '[:lower:]' | sed 's/\"//g' | sed 's/\\.//g' | cut -d' ' -f3"
|
||||
OUTPUT_VARIABLE DIST_VERSION
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
if (DIST_NAME)
|
||||
message(STATUS "Distro Name: ${DIST_NAME}")
|
||||
if (DIST_RELEASE)
|
||||
message(STATUS "Distro Release: ${DIST_RELEASE}")
|
||||
endif()
|
||||
if (DIST_VERSION)
|
||||
message(STATUS "Distro Version: ${DIST_VERSION}")
|
||||
endif()
|
||||
set(RPM_ARCH x86_64 CACHE STRING "Architecture of the rpm file")
|
||||
set(RPMBUILD_DIR ~/rpmbuild CACHE STRING "Rpmbuild directory, for the rpm target")
|
||||
if (${DIST_NAME} STREQUAL "opensuse")
|
||||
if (DIST_RELEASE)
|
||||
if (${DIST_RELEASE} STREQUAL "leap")
|
||||
if (DIST_VERSION)
|
||||
set(RPM_DISTRO "lp${DIST_VERSION}" CACHE STRING "Suffix of the rpm file")
|
||||
else()
|
||||
set(RPM_DISTRO ${DIST_RELEASE} CACHE STRING "Suffix of the rpm file")
|
||||
endif()
|
||||
elseif (${DIST_RELEASE} STREQUAL "tumbleweed")
|
||||
set(RPM_DISTRO ${DIST_RELEASE} CACHE STRING "Suffix of the rpm file")
|
||||
else ()
|
||||
set(RPM_DISTRO ${DIST_NAME} CACHE STRING "Suffix of the rpm file")
|
||||
endif()
|
||||
else()
|
||||
set(RPM_DISTRO ${DIST_NAME} CACHE STRING "Suffix of the rpm file")
|
||||
endif()
|
||||
add_custom_target(rpm
|
||||
COMMAND ${CMAKE_SOURCE_DIR}/dist/scripts/maketarball.sh
|
||||
COMMAND ${CMAKE_COMMAND} -E copy strawberry-${STRAWBERRY_VERSION_PACKAGE}.tar.xz ${RPMBUILD_DIR}/SOURCES/
|
||||
COMMAND rpmbuild -bs ${CMAKE_SOURCE_DIR}/dist/opensuse/strawberry.spec
|
||||
COMMAND rpmbuild -bb ${CMAKE_SOURCE_DIR}/dist/opensuse/strawberry.spec
|
||||
)
|
||||
elseif (${DIST_NAME} STREQUAL "fedora")
|
||||
if (DIST_VERSION)
|
||||
set(RPM_DISTRO "${DIST_NAME}${DIST_VERSION}" CACHE STRING "Suffix of the rpm file")
|
||||
else ()
|
||||
set(RPM_DISTRO ${DIST_NAME} CACHE STRING "Suffix of the rpm file")
|
||||
endif()
|
||||
add_custom_target(rpm
|
||||
COMMAND ${CMAKE_SOURCE_DIR}/dist/scripts/maketarball.sh
|
||||
COMMAND ${CMAKE_COMMAND} -E copy strawberry-${STRAWBERRY_VERSION_PACKAGE}.tar.xz ${RPMBUILD_DIR}/SOURCES/
|
||||
COMMAND rpmbuild -bs ${CMAKE_SOURCE_DIR}/dist/fedora/strawberry.spec
|
||||
COMMAND rpmbuild -bb ${CMAKE_SOURCE_DIR}/dist/fedora/strawberry.spec
|
||||
)
|
||||
else()
|
||||
set(RPM_DISTRO ${DIST_NAME} CACHE STRING "Suffix of the rpm file")
|
||||
endif()
|
||||
message(STATUS "RPM Suffix: ${RPM_DISTRO}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
set(STRAWBERRY_VERSION_MAJOR 0)
|
||||
set(STRAWBERRY_VERSION_MINOR 2)
|
||||
set(STRAWBERRY_VERSION_PATCH 1)
|
||||
set(STRAWBERRY_VERSION_MINOR 3)
|
||||
set(STRAWBERRY_VERSION_PATCH 3)
|
||||
#set(STRAWBERRY_VERSION_PRERELEASE rc1)
|
||||
|
||||
set(INCLUDE_GIT_REVISION OFF)
|
||||
|
||||
if (WIN32)
|
||||
set(INCLUDE_GIT_REVISION OFF)
|
||||
endif()
|
||||
|
||||
set(majorminorpatch "${STRAWBERRY_VERSION_MAJOR}.${STRAWBERRY_VERSION_MINOR}.${STRAWBERRY_VERSION_PATCH}")
|
||||
|
||||
set(STRAWBERRY_VERSION_DISPLAY "${majorminorpatch}")
|
||||
@@ -26,10 +22,11 @@ if(STRAWBERRY_VERSION_PRERELEASE)
|
||||
set(STRAWBERRY_VERSION_PACKAGE "${STRAWBERRY_VERSION_PACKAGE}${STRAWBERRY_VERSION_PRERELEASE}")
|
||||
endif(STRAWBERRY_VERSION_PRERELEASE)
|
||||
|
||||
if(INCLUDE_GIT_REVISION)
|
||||
|
||||
if(INCLUDE_GIT_REVISION AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
|
||||
|
||||
find_program(GIT_EXECUTABLE git)
|
||||
if(GIT_EXECUTABLE-NOTFOUND)
|
||||
if(NOT GIT_EXECUTABLE OR GIT_EXECUTABLE-NOTFOUND)
|
||||
message(FATAL_ERROR "Missing GIT executable." )
|
||||
endif()
|
||||
|
||||
@@ -56,6 +53,14 @@ if(INCLUDE_GIT_REVISION)
|
||||
message(FATAL_ERROR "GIT command failed to get revision string '${GIT_REVISION}'")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
if(FORCE_GIT_REVISION)
|
||||
set(GIT_REVISION ${FORCE_GIT_REVISION})
|
||||
endif()
|
||||
|
||||
if(GIT_REVISION)
|
||||
|
||||
string(REGEX REPLACE "^(.+)-([0-9]+)-(g[a-f0-9]+)$" "\\1;\\2;\\3" GIT_PARTS ${GIT_REVISION})
|
||||
|
||||
if(NOT GIT_PARTS)
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>schema/schema.sql</file>
|
||||
<file>schema/schema-1.sql</file>
|
||||
<file>schema/schema-2.sql</file>
|
||||
<file>schema/schema-3.sql</file>
|
||||
<file>schema/device-schema.sql</file>
|
||||
<file>style/mainwindow.css</file>
|
||||
<file>style/statusview.css</file>
|
||||
<file>style/strawberry.css</file>
|
||||
<file>misc/playing_tooltip.txt</file>
|
||||
<file>pictures/strawberry.png</file>
|
||||
<file>pictures/strawbs-transparent.png</file>
|
||||
@@ -72,7 +74,6 @@
|
||||
<file>icons/128x128/go-previous.png</file>
|
||||
<file>icons/128x128/go-up.png</file>
|
||||
<file>icons/128x128/gstreamer.png</file>
|
||||
<file>icons/128x128/guitar.png</file>
|
||||
<file>icons/128x128/headset.png</file>
|
||||
<file>icons/128x128/help-hint.png</file>
|
||||
<file>icons/128x128/intel.png</file>
|
||||
@@ -92,13 +93,10 @@
|
||||
<file>icons/128x128/play2.png</file>
|
||||
<file>icons/128x128/realtek.png</file>
|
||||
<file>icons/128x128/search.png</file>
|
||||
<file>icons/128x128/soundcard2.png</file>
|
||||
<file>icons/128x128/soundcard.png</file>
|
||||
<file>icons/128x128/speaker.png</file>
|
||||
<file>icons/128x128/star-grey.png</file>
|
||||
<file>icons/128x128/star.png</file>
|
||||
<file>icons/128x128/strawberry-panel-grey.png</file>
|
||||
<file>icons/128x128/strawberry-panel.png</file>
|
||||
<file>icons/128x128/strawberry.png</file>
|
||||
<file>icons/128x128/strawberry.svg</file>
|
||||
<file>icons/128x128/tools-wizard.png</file>
|
||||
@@ -113,6 +111,7 @@
|
||||
<file>icons/128x128/xine.png</file>
|
||||
<file>icons/128x128/zoom-in.png</file>
|
||||
<file>icons/128x128/zoom-out.png</file>
|
||||
<file>icons/128x128/tidal.png</file>
|
||||
<file>icons/64x64/albums.png</file>
|
||||
<file>icons/64x64/alsa.png</file>
|
||||
<file>icons/64x64/application-exit.png</file>
|
||||
@@ -160,7 +159,6 @@
|
||||
<file>icons/64x64/go-previous.png</file>
|
||||
<file>icons/64x64/go-up.png</file>
|
||||
<file>icons/64x64/gstreamer.png</file>
|
||||
<file>icons/64x64/guitar.png</file>
|
||||
<file>icons/64x64/headset.png</file>
|
||||
<file>icons/64x64/help-hint.png</file>
|
||||
<file>icons/64x64/intel.png</file>
|
||||
@@ -181,13 +179,10 @@
|
||||
<file>icons/64x64/pulseaudio.png</file>
|
||||
<file>icons/64x64/realtek.png</file>
|
||||
<file>icons/64x64/search.png</file>
|
||||
<file>icons/64x64/soundcard2.png</file>
|
||||
<file>icons/64x64/soundcard.png</file>
|
||||
<file>icons/64x64/speaker.png</file>
|
||||
<file>icons/64x64/star-grey.png</file>
|
||||
<file>icons/64x64/star.png</file>
|
||||
<file>icons/64x64/strawberry-panel-grey.png</file>
|
||||
<file>icons/64x64/strawberry-panel.png</file>
|
||||
<file>icons/64x64/strawberry.png</file>
|
||||
<file>icons/64x64/tools-wizard.png</file>
|
||||
<file>icons/64x64/view-choose.png</file>
|
||||
@@ -201,6 +196,7 @@
|
||||
<file>icons/64x64/xine.png</file>
|
||||
<file>icons/64x64/zoom-in.png</file>
|
||||
<file>icons/64x64/zoom-out.png</file>
|
||||
<file>icons/64x64/tidal.png</file>
|
||||
<file>icons/48x48/albums.png</file>
|
||||
<file>icons/48x48/alsa.png</file>
|
||||
<file>icons/48x48/application-exit.png</file>
|
||||
@@ -248,7 +244,6 @@
|
||||
<file>icons/48x48/go-previous.png</file>
|
||||
<file>icons/48x48/go-up.png</file>
|
||||
<file>icons/48x48/gstreamer.png</file>
|
||||
<file>icons/48x48/guitar.png</file>
|
||||
<file>icons/48x48/headset.png</file>
|
||||
<file>icons/48x48/help-hint.png</file>
|
||||
<file>icons/48x48/intel.png</file>
|
||||
@@ -272,13 +267,10 @@
|
||||
<file>icons/48x48/pulseaudio.png</file>
|
||||
<file>icons/48x48/realtek.png</file>
|
||||
<file>icons/48x48/search.png</file>
|
||||
<file>icons/48x48/soundcard2.png</file>
|
||||
<file>icons/48x48/soundcard.png</file>
|
||||
<file>icons/48x48/speaker.png</file>
|
||||
<file>icons/48x48/star-grey.png</file>
|
||||
<file>icons/48x48/star.png</file>
|
||||
<file>icons/48x48/strawberry-panel-grey.png</file>
|
||||
<file>icons/48x48/strawberry-panel.png</file>
|
||||
<file>icons/48x48/strawberry.png</file>
|
||||
<file>icons/48x48/tools-wizard.png</file>
|
||||
<file>icons/48x48/view-choose.png</file>
|
||||
@@ -292,6 +284,7 @@
|
||||
<file>icons/48x48/xine.png</file>
|
||||
<file>icons/48x48/zoom-in.png</file>
|
||||
<file>icons/48x48/zoom-out.png</file>
|
||||
<file>icons/48x48/tidal.png</file>
|
||||
<file>icons/32x32/albums.png</file>
|
||||
<file>icons/32x32/alsa.png</file>
|
||||
<file>icons/32x32/application-exit.png</file>
|
||||
@@ -339,7 +332,6 @@
|
||||
<file>icons/32x32/go-previous.png</file>
|
||||
<file>icons/32x32/go-up.png</file>
|
||||
<file>icons/32x32/gstreamer.png</file>
|
||||
<file>icons/32x32/guitar.png</file>
|
||||
<file>icons/32x32/headset.png</file>
|
||||
<file>icons/32x32/help-hint.png</file>
|
||||
<file>icons/32x32/intel.png</file>
|
||||
@@ -363,13 +355,10 @@
|
||||
<file>icons/32x32/pulseaudio.png</file>
|
||||
<file>icons/32x32/realtek.png</file>
|
||||
<file>icons/32x32/search.png</file>
|
||||
<file>icons/32x32/soundcard2.png</file>
|
||||
<file>icons/32x32/soundcard.png</file>
|
||||
<file>icons/32x32/speaker.png</file>
|
||||
<file>icons/32x32/star-grey.png</file>
|
||||
<file>icons/32x32/star.png</file>
|
||||
<file>icons/32x32/strawberry-panel-grey.png</file>
|
||||
<file>icons/32x32/strawberry-panel.png</file>
|
||||
<file>icons/32x32/strawberry.png</file>
|
||||
<file>icons/32x32/strawberry.svg</file>
|
||||
<file>icons/32x32/tools-wizard.png</file>
|
||||
@@ -384,6 +373,7 @@
|
||||
<file>icons/32x32/xine.png</file>
|
||||
<file>icons/32x32/zoom-in.png</file>
|
||||
<file>icons/32x32/zoom-out.png</file>
|
||||
<file>icons/32x32/tidal.png</file>
|
||||
<file>icons/22x22/albums.png</file>
|
||||
<file>icons/22x22/alsa.png</file>
|
||||
<file>icons/22x22/application-exit.png</file>
|
||||
@@ -431,7 +421,6 @@
|
||||
<file>icons/22x22/go-previous.png</file>
|
||||
<file>icons/22x22/go-up.png</file>
|
||||
<file>icons/22x22/gstreamer.png</file>
|
||||
<file>icons/22x22/guitar.png</file>
|
||||
<file>icons/22x22/headset.png</file>
|
||||
<file>icons/22x22/help-hint.png</file>
|
||||
<file>icons/22x22/intel.png</file>
|
||||
@@ -455,13 +444,10 @@
|
||||
<file>icons/22x22/pulseaudio.png</file>
|
||||
<file>icons/22x22/realtek.png</file>
|
||||
<file>icons/22x22/search.png</file>
|
||||
<file>icons/22x22/soundcard2.png</file>
|
||||
<file>icons/22x22/soundcard.png</file>
|
||||
<file>icons/22x22/speaker.png</file>
|
||||
<file>icons/22x22/star-grey.png</file>
|
||||
<file>icons/22x22/star.png</file>
|
||||
<file>icons/22x22/strawberry-panel-grey.png</file>
|
||||
<file>icons/22x22/strawberry-panel.png</file>
|
||||
<file>icons/22x22/strawberry.png</file>
|
||||
<file>icons/22x22/strawberry.svg</file>
|
||||
<file>icons/22x22/tools-wizard.png</file>
|
||||
@@ -476,5 +462,7 @@
|
||||
<file>icons/22x22/xine.png</file>
|
||||
<file>icons/22x22/zoom-in.png</file>
|
||||
<file>icons/22x22/zoom-out.png</file>
|
||||
<file>icons/22x22/tidal.png</file>
|
||||
<file>fonts/HumongousofEternitySt.ttf</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
BIN
data/fonts/HumongousofEternitySt.ttf
Normal file
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 22 KiB |
BIN
data/icons/128x128/tidal.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
BIN
data/icons/22x22/tidal.png
Normal file
|
After Width: | Height: | Size: 933 B |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
BIN
data/icons/32x32/tidal.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 4.5 KiB |
BIN
data/icons/48x48/tidal.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 7.1 KiB |
BIN
data/icons/64x64/tidal.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 125 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 363 KiB |
|
Before Width: | Height: | Size: 628 KiB |
BIN
data/icons/full/tidal.png
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
@@ -11,8 +11,6 @@ CREATE TABLE device_%deviceid_subdirectories (
|
||||
|
||||
CREATE TABLE device_%deviceid_songs (
|
||||
|
||||
/* Metadata from taglib */
|
||||
|
||||
title TEXT NOT NULL,
|
||||
album TEXT NOT NULL,
|
||||
artist TEXT NOT NULL,
|
||||
@@ -27,6 +25,7 @@ CREATE TABLE device_%deviceid_songs (
|
||||
performer TEXT NOT NULL,
|
||||
grouping TEXT NOT NULL,
|
||||
comment TEXT NOT NULL,
|
||||
lyrics TEXT NOT NULL,
|
||||
|
||||
beginning INTEGER NOT NULL DEFAULT 0,
|
||||
length INTEGER NOT NULL DEFAULT 0,
|
||||
@@ -35,8 +34,7 @@ CREATE TABLE device_%deviceid_songs (
|
||||
samplerate INTEGER NOT NULL DEFAULT 0,
|
||||
bitdepth INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
/* Information about the file on disk */
|
||||
|
||||
source INTEGER NOT NULL DEFAULT 0,
|
||||
directory_id INTEGER NOT NULL,
|
||||
filename TEXT NOT NULL,
|
||||
filetype INTEGER NOT NULL DEFAULT 0,
|
||||
@@ -45,8 +43,6 @@ CREATE TABLE device_%deviceid_songs (
|
||||
ctime INTEGER NOT NULL,
|
||||
unavailable INTEGER DEFAULT 0,
|
||||
|
||||
/* Other */
|
||||
|
||||
playcount INTEGER NOT NULL DEFAULT 0,
|
||||
skipcount INTEGER NOT NULL DEFAULT 0,
|
||||
lastplayed INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
3
data/schema/schema-1.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE playlist_items ADD COLUMN internet_service TEXT;
|
||||
|
||||
UPDATE schema_version SET version=1;
|
||||
5
data/schema/schema-2.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
ALTER TABLE songs ADD COLUMN lyrics TEXT;
|
||||
|
||||
ALTER TABLE playlist_items ADD COLUMN lyrics TEXT;
|
||||
|
||||
UPDATE schema_version SET version=2;
|
||||
65
data/schema/schema-3.sql
Normal file
@@ -0,0 +1,65 @@
|
||||
ALTER TABLE songs ADD COLUMN source INTEGER NOT NULL DEFAULT 0;
|
||||
|
||||
UPDATE songs SET source = 2 WHERE source = 0;
|
||||
|
||||
DROP TABLE playlist_items;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS playlist_items (
|
||||
|
||||
playlist INTEGER NOT NULL,
|
||||
type INTEGER NOT NULL DEFAULT 0,
|
||||
collection_id INTEGER,
|
||||
url TEXT,
|
||||
|
||||
title TEXT NOT NULL,
|
||||
album TEXT NOT NULL,
|
||||
artist TEXT NOT NULL,
|
||||
albumartist TEXT NOT NULL,
|
||||
track INTEGER NOT NULL DEFAULT -1,
|
||||
disc INTEGER NOT NULL DEFAULT -1,
|
||||
year INTEGER NOT NULL DEFAULT -1,
|
||||
originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
genre TEXT NOT NULL,
|
||||
compilation INTEGER NOT NULL DEFAULT -1,
|
||||
composer TEXT NOT NULL,
|
||||
performer TEXT NOT NULL,
|
||||
grouping TEXT NOT NULL,
|
||||
comment TEXT NOT NULL,
|
||||
lyrics TEXT NOT NULL,
|
||||
|
||||
beginning INTEGER NOT NULL DEFAULT 0,
|
||||
length INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
bitrate INTEGER NOT NULL DEFAULT 0,
|
||||
samplerate INTEGER NOT NULL DEFAULT 0,
|
||||
bitdepth INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
source INTEGER NOT NULL DEFAULT 0,
|
||||
directory_id INTEGER,
|
||||
filename TEXT,
|
||||
filetype INTEGER NOT NULL DEFAULT 0,
|
||||
filesize INTEGER,
|
||||
mtime INTEGER,
|
||||
ctime INTEGER,
|
||||
unavailable INTEGER DEFAULT 0,
|
||||
|
||||
playcount INTEGER NOT NULL DEFAULT 0,
|
||||
skipcount INTEGER NOT NULL DEFAULT 0,
|
||||
lastplayed INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
compilation_detected INTEGER DEFAULT 0,
|
||||
compilation_on INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_off INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_effective INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
art_automatic TEXT,
|
||||
art_manual TEXT,
|
||||
|
||||
effective_albumartist TEXT,
|
||||
effective_originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
cue_path TEXT
|
||||
|
||||
);
|
||||
|
||||
UPDATE schema_version SET version=3;
|
||||
@@ -1,23 +1,23 @@
|
||||
CREATE TABLE schema_version (
|
||||
CREATE TABLE IF NOT EXISTS schema_version (
|
||||
version INTEGER NOT NULL
|
||||
);
|
||||
|
||||
INSERT INTO schema_version (version) VALUES (0);
|
||||
DELETE FROM schema_version;
|
||||
|
||||
CREATE TABLE directories (
|
||||
INSERT INTO schema_version (version) VALUES (3);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS directories (
|
||||
path TEXT NOT NULL,
|
||||
subdirs INTEGER NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE subdirectories (
|
||||
CREATE TABLE IF NOT EXISTS subdirectories (
|
||||
directory_id INTEGER NOT NULL,
|
||||
path TEXT NOT NULL,
|
||||
mtime INTEGER NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE songs (
|
||||
|
||||
/* Metadata from taglib */
|
||||
CREATE TABLE IF NOT EXISTS songs (
|
||||
|
||||
title TEXT NOT NULL,
|
||||
album TEXT NOT NULL,
|
||||
@@ -33,6 +33,7 @@ CREATE TABLE songs (
|
||||
performer TEXT NOT NULL,
|
||||
grouping TEXT NOT NULL,
|
||||
comment TEXT NOT NULL,
|
||||
lyrics TEXT NOT NULL,
|
||||
|
||||
beginning INTEGER NOT NULL DEFAULT 0,
|
||||
length INTEGER NOT NULL DEFAULT 0,
|
||||
@@ -41,8 +42,7 @@ CREATE TABLE songs (
|
||||
samplerate INTEGER NOT NULL DEFAULT 0,
|
||||
bitdepth INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
/* Information about the file on disk */
|
||||
|
||||
source INTEGER NOT NULL DEFAULT 0,
|
||||
directory_id INTEGER NOT NULL,
|
||||
filename TEXT NOT NULL,
|
||||
filetype INTEGER NOT NULL DEFAULT 0,
|
||||
@@ -51,8 +51,6 @@ CREATE TABLE songs (
|
||||
ctime INTEGER NOT NULL,
|
||||
unavailable INTEGER DEFAULT 0,
|
||||
|
||||
/* Other */
|
||||
|
||||
playcount INTEGER NOT NULL DEFAULT 0,
|
||||
skipcount INTEGER NOT NULL DEFAULT 0,
|
||||
lastplayed INTEGER NOT NULL DEFAULT 0,
|
||||
@@ -67,12 +65,12 @@ CREATE TABLE songs (
|
||||
|
||||
effective_albumartist TEXT,
|
||||
effective_originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
|
||||
cue_path TEXT
|
||||
|
||||
);
|
||||
|
||||
CREATE TABLE playlists (
|
||||
CREATE TABLE IF NOT EXISTS playlists (
|
||||
|
||||
name TEXT NOT NULL,
|
||||
last_played INTEGER NOT NULL DEFAULT -1,
|
||||
@@ -83,15 +81,13 @@ CREATE TABLE playlists (
|
||||
|
||||
);
|
||||
|
||||
CREATE TABLE playlist_items (
|
||||
CREATE TABLE IF NOT EXISTS playlist_items (
|
||||
|
||||
playlist INTEGER NOT NULL,
|
||||
type TEXT NOT NULL,
|
||||
type INTEGER NOT NULL DEFAULT 0,
|
||||
collection_id INTEGER,
|
||||
url TEXT,
|
||||
|
||||
/* Metadata from taglib */
|
||||
|
||||
title TEXT NOT NULL,
|
||||
album TEXT NOT NULL,
|
||||
artist TEXT NOT NULL,
|
||||
@@ -106,6 +102,7 @@ CREATE TABLE playlist_items (
|
||||
performer TEXT NOT NULL,
|
||||
grouping TEXT NOT NULL,
|
||||
comment TEXT NOT NULL,
|
||||
lyrics TEXT NOT NULL,
|
||||
|
||||
beginning INTEGER NOT NULL DEFAULT 0,
|
||||
length INTEGER NOT NULL DEFAULT 0,
|
||||
@@ -114,8 +111,7 @@ CREATE TABLE playlist_items (
|
||||
samplerate INTEGER NOT NULL DEFAULT 0,
|
||||
bitdepth INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
/* Information about the file on disk */
|
||||
|
||||
source INTEGER NOT NULL DEFAULT 0,
|
||||
directory_id INTEGER,
|
||||
filename TEXT,
|
||||
filetype INTEGER NOT NULL DEFAULT 0,
|
||||
@@ -124,8 +120,6 @@ CREATE TABLE playlist_items (
|
||||
ctime INTEGER,
|
||||
unavailable INTEGER DEFAULT 0,
|
||||
|
||||
/* Other */
|
||||
|
||||
playcount INTEGER NOT NULL DEFAULT 0,
|
||||
skipcount INTEGER NOT NULL DEFAULT 0,
|
||||
lastplayed INTEGER NOT NULL DEFAULT 0,
|
||||
@@ -145,7 +139,7 @@ CREATE TABLE playlist_items (
|
||||
|
||||
);
|
||||
|
||||
CREATE TABLE devices (
|
||||
CREATE TABLE IF NOT EXISTS devices (
|
||||
unique_id TEXT NOT NULL,
|
||||
friendly_name TEXT,
|
||||
size INTEGER,
|
||||
@@ -155,17 +149,17 @@ CREATE TABLE devices (
|
||||
transcode_format NOT NULL DEFAULT 5
|
||||
);
|
||||
|
||||
CREATE INDEX idx_filename ON songs (filename);
|
||||
CREATE INDEX IF NOT EXISTS idx_filename ON songs (filename);
|
||||
|
||||
CREATE INDEX idx_comp_artist ON songs (compilation_effective, artist);
|
||||
CREATE INDEX IF NOT EXISTS idx_comp_artist ON songs (compilation_effective, artist);
|
||||
|
||||
CREATE INDEX idx_album ON songs (album);
|
||||
CREATE INDEX IF NOT EXISTS idx_album ON songs (album);
|
||||
|
||||
CREATE INDEX idx_title ON songs (title);
|
||||
CREATE INDEX IF NOT EXISTS idx_title ON songs (title);
|
||||
|
||||
CREATE VIEW duplicated_songs as select artist dup_artist, album dup_album, title dup_title from songs as inner_songs where artist != '' and album != '' and title != '' and unavailable = 0 group by artist, album , title having count(*) > 1;
|
||||
CREATE VIEW IF NOT EXISTS duplicated_songs as select artist dup_artist, album dup_album, title dup_title from songs as inner_songs where artist != '' and album != '' and title != '' and unavailable = 0 group by artist, album , title having count(*) > 1;
|
||||
|
||||
CREATE VIRTUAL TABLE songs_fts USING fts3(
|
||||
CREATE VIRTUAL TABLE IF NOT EXISTS songs_fts USING fts3(
|
||||
|
||||
ftstitle,
|
||||
ftsalbum,
|
||||
@@ -180,7 +174,7 @@ CREATE VIRTUAL TABLE songs_fts USING fts3(
|
||||
|
||||
);
|
||||
|
||||
CREATE VIRTUAL TABLE playlist_items_fts_ USING fts3(
|
||||
CREATE VIRTUAL TABLE IF NOT EXISTS playlist_items_fts_ USING fts3(
|
||||
|
||||
ftstitle,
|
||||
ftsalbum,
|
||||
@@ -195,7 +189,7 @@ CREATE VIRTUAL TABLE playlist_items_fts_ USING fts3(
|
||||
|
||||
);
|
||||
|
||||
CREATE VIRTUAL TABLE %allsongstables_fts USING fts3(
|
||||
CREATE VIRTUAL TABLE IF NOT EXISTS %allsongstables_fts USING fts3(
|
||||
|
||||
ftstitle,
|
||||
ftsalbum,
|
||||
@@ -211,7 +205,7 @@ CREATE VIRTUAL TABLE %allsongstables_fts USING fts3(
|
||||
);
|
||||
|
||||
|
||||
INSERT INTO songs_fts (ROWID, ftstitle, ftsalbum, ftsartist, ftsalbumartist, ftscomposer, ftsperformer, ftsgrouping, ftsgenre, ftscomment)
|
||||
INSERT INTO songs_fts (ROWID, ftstitle, ftsalbum, ftsartist, ftsalbumartist, ftscomposer, ftsperformer, ftsgrouping, ftsgenre, ftscomment)
|
||||
SELECT ROWID, title, album, artist, albumartist, composer, performer, grouping, genre, comment FROM songs;
|
||||
|
||||
INSERT INTO %allsongstables_fts (ROWID, ftstitle, ftsalbum, ftsartist, ftsalbumartist, ftscomposer, ftsperformer, ftsgrouping, ftsgenre, ftscomment)
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
StatusView {
|
||||
background: white;
|
||||
background-color: white;
|
||||
}
|
||||
QVBoxLayout {
|
||||
background: white;
|
||||
background-color: white;
|
||||
}
|
||||
QScrollArea {
|
||||
background: qpalette(base);
|
||||
}
|
||||
@@ -52,3 +52,20 @@ darwin {
|
||||
darwin QMenu {
|
||||
font-size: 13pt;
|
||||
}
|
||||
|
||||
#scrollarea_play {
|
||||
background-color: white;
|
||||
font: 11pt;
|
||||
}
|
||||
|
||||
#scrollarea_stop {
|
||||
background-color: white;
|
||||
font: 11pt;
|
||||
}
|
||||
|
||||
#scrollAreaWidgetContents_stop {
|
||||
background-color: white;
|
||||
}
|
||||
#scrollAreaWidgetContents_play {
|
||||
background-color: white;
|
||||
}
|
||||
14
dist/CMakeLists.txt
vendored
@@ -1,9 +1,17 @@
|
||||
set(ENV{LC_ALL} "en_US.utf8")
|
||||
execute_process(COMMAND date "+%a %b %d %Y" OUTPUT_VARIABLE RPM_DATE OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
execute_process(COMMAND env LC_ALL="en_US.utf8" date "+%a %b %d %Y" OUTPUT_VARIABLE RPM_DATE OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
execute_process(COMMAND env LC_ALL=C date "+%a, %-d %b %Y %H:%M:%S %z" OUTPUT_VARIABLE DEB_DATE OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/rpm/strawberry.spec.in ${CMAKE_CURRENT_SOURCE_DIR}/rpm/strawberry.spec @ONLY)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/maketarball.sh.in ${CMAKE_CURRENT_SOURCE_DIR}/scripts/maketarball.sh @ONLY)
|
||||
if (RPM_DISTRO)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/opensuse/strawberry.spec.in ${CMAKE_CURRENT_SOURCE_DIR}/opensuse/strawberry.spec @ONLY)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fedora/strawberry.spec.in ${CMAKE_CURRENT_SOURCE_DIR}/fedora/strawberry.spec @ONLY)
|
||||
endif()
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/debian/changelog.in ${CMAKE_CURRENT_SOURCE_DIR}/debian/changelog)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/macos/Info.plist.in ${CMAKE_CURRENT_SOURCE_DIR}/macos/Info.plist)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry.nsi.in ${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry.nsi @ONLY)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-64.nsi.in ${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-64.nsi @ONLY)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-debug.nsi.in ${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-debug.nsi @ONLY)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-debug-64.nsi.in ${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-debug-64.nsi @ONLY)
|
||||
|
||||
if (UNIX AND NOT APPLE)
|
||||
install(FILES ../data/icons/48x48/strawberry.png DESTINATION share/icons/hicolor/48x48/apps/)
|
||||
|
||||
5
dist/debian/changelog.in
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
strawberry (${STRAWBERRY_VERSION_DISPLAY}) unstable; urgency=low
|
||||
|
||||
* Version ${STRAWBERRY_VERSION_DISPLAY}
|
||||
|
||||
-- Jonas Kvinge <jonas@jkvinge.net> ${DEB_DATE}
|
||||
1
dist/debian/compat
vendored
Normal file
@@ -0,0 +1 @@
|
||||
9
|
||||
70
dist/debian/control
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
Source: strawberry
|
||||
Section: sound
|
||||
Priority: optional
|
||||
Maintainer: "Jonas Kvinge" <jonas@jkvinge.net>
|
||||
Build-Depends: debhelper (>= 7),
|
||||
make,
|
||||
cmake,
|
||||
gcc,
|
||||
protobuf-compiler,
|
||||
libglib2.0-dev,
|
||||
libdbus-1-dev,
|
||||
libprotobuf-dev,
|
||||
libboost-dev,
|
||||
libsqlite3-dev,
|
||||
libasound2-dev,
|
||||
libpulse-dev,
|
||||
libtag1-dev,
|
||||
libqt5-dev,
|
||||
qtbase5-dev,
|
||||
qtbase5-dev-tools,
|
||||
qtbase5-private-dev,
|
||||
qt5-dev-tools,
|
||||
libqt5opengl5-dev,
|
||||
libqt5x11extras5-dev,
|
||||
libgstreamer1.0-dev,
|
||||
libgstreamer-plugins-base1.0-dev,
|
||||
libxine2-dev,
|
||||
libvlc-dev,
|
||||
libphonon4qt5-dev,
|
||||
libcdio-dev,
|
||||
libgpod-dev,
|
||||
libimobiledevice-dev,
|
||||
libmtp-dev,
|
||||
libplist-dev,
|
||||
libusbmuxd-dev,
|
||||
libchromaprint-dev,
|
||||
liblastfm5-dev
|
||||
Standards-Version: 3.9.8
|
||||
|
||||
Package: strawberry
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends},
|
||||
${misc:Depends},
|
||||
libsqlite3-0,
|
||||
gstreamer1.0-plugins-base,
|
||||
gstreamer1.0-plugins-good,
|
||||
gstreamer1.0-alsa,
|
||||
gstreamer1.0-pulseaudio
|
||||
Homepage: http://www.strawbs.org/
|
||||
Description: Audio player and music collection organizer
|
||||
Strawberry is a audio player especially aimed at audiophiles.
|
||||
.
|
||||
Features:
|
||||
- Play and organize music
|
||||
- Supports WAV, FLAC, WavPack, DSF, DSDIFF, Ogg Vorbis, Speex, MPC, TrueAudio, AIFF, MP4, MP3 and ASF
|
||||
- Audio CD playback
|
||||
- Native desktop notifications
|
||||
- Playlists in multiple formats
|
||||
- Advanced output and device options with support for bit perfect playback on Linux
|
||||
- Edit tags on music files
|
||||
- Fetch tags from MusicBrainz
|
||||
- Album cover art from Lastfm, Musicbrainz and Discogs
|
||||
- Song lyrics from AudD and API Seeds
|
||||
- Support for multiple backends
|
||||
- Audio analyzer
|
||||
- Equalizer
|
||||
- Transfer music to iPod, iPhone, MTP or mass-storage USB player
|
||||
- Integrated Tidal support
|
||||
.
|
||||
It is a fork of Clementine. The name is inspired by the band Strawbs.
|
||||
61
dist/debian/rules
vendored
Executable file
@@ -0,0 +1,61 @@
|
||||
#!/usr/bin/make -f
|
||||
# -*- makefile -*-
|
||||
|
||||
MY_MAKEFLAGS=
|
||||
ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
|
||||
NUMJOBS=$(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
|
||||
MY_MAKEFLAGS=-j$(NUMJOBS)
|
||||
endif
|
||||
|
||||
configure: configure-stamp
|
||||
configure-stamp:
|
||||
dh_testdir
|
||||
cmake .. \
|
||||
-DCMAKE_INSTALL_PREFIX=$(CURDIR)/debian/strawberry/usr
|
||||
touch configure-stamp
|
||||
|
||||
build: build-stamp
|
||||
build-stamp: configure-stamp
|
||||
dh_testdir
|
||||
make $(MY_MAKEFLAGS)
|
||||
touch $@
|
||||
|
||||
clean:
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
rm -f build-stamp configure-stamp
|
||||
|
||||
-make clean
|
||||
-rm Makefile src/Makefile
|
||||
|
||||
dh_clean
|
||||
|
||||
install: build
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_prep
|
||||
dh_installdirs
|
||||
|
||||
make install
|
||||
|
||||
binary-indep: install
|
||||
|
||||
binary-arch: install
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_installchangelogs
|
||||
dh_installmenu
|
||||
dh_installdocs
|
||||
dh_gconf
|
||||
dh_link
|
||||
dh_strip
|
||||
dh_compress
|
||||
dh_fixperms
|
||||
dh_installdeb
|
||||
dh_shlibdeps
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
|
||||
binary: binary-indep binary-arch
|
||||
.PHONY: build clean binary-indep binary-arch binary install configure
|
||||
118
dist/fedora/strawberry.spec.in
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
Name: strawberry
|
||||
Version: @STRAWBERRY_VERSION_RPM_V@
|
||||
Release: @STRAWBERRY_VERSION_RPM_R@.@RPM_DISTRO@
|
||||
Summary: A audio player and music collection organiser
|
||||
|
||||
Group: Applications/Multimedia
|
||||
License: GPL-3.0+
|
||||
URL: http://www.strawbs.org/
|
||||
Source0: %{name}-@STRAWBERRY_VERSION_PACKAGE@.tar.xz
|
||||
|
||||
BuildRequires: boost-devel
|
||||
BuildRequires: cmake
|
||||
BuildRequires: desktop-file-utils
|
||||
BuildRequires: gcc-c++
|
||||
BuildRequires: hicolor-icon-theme
|
||||
BuildRequires: liblastfm-qt5-devel
|
||||
BuildRequires: make
|
||||
BuildRequires: git
|
||||
BuildRequires: pkgconfig
|
||||
BuildRequires: pkgconfig(glib-2.0)
|
||||
BuildRequires: pkgconfig(gio-2.0)
|
||||
BuildRequires: pkgconfig(gio-unix-2.0)
|
||||
BuildRequires: pkgconfig(gthread-2.0)
|
||||
BuildRequires: pkgconfig(dbus-1)
|
||||
BuildRequires: pkgconfig(alsa)
|
||||
BuildRequires: pkgconfig(protobuf)
|
||||
BuildRequires: pkgconfig(sqlite3) >= 3.7
|
||||
BuildRequires: pkgconfig(taglib) >= 1.11
|
||||
BuildRequires: pkgconfig(Qt5Core)
|
||||
BuildRequires: pkgconfig(Qt5Gui)
|
||||
BuildRequires: pkgconfig(Qt5Widgets)
|
||||
BuildRequires: pkgconfig(Qt5Concurrent)
|
||||
BuildRequires: pkgconfig(Qt5Sql)
|
||||
BuildRequires: pkgconfig(Qt5Network)
|
||||
BuildRequires: pkgconfig(Qt5Xml)
|
||||
BuildRequires: pkgconfig(Qt5X11Extras)
|
||||
BuildRequires: pkgconfig(Qt5DBus)
|
||||
BuildRequires: pkgconfig(Qt5OpenGL)
|
||||
BuildRequires: pkgconfig(gstreamer-1.0)
|
||||
BuildRequires: pkgconfig(gstreamer-app-1.0)
|
||||
BuildRequires: pkgconfig(gstreamer-audio-1.0)
|
||||
BuildRequires: pkgconfig(gstreamer-base-1.0)
|
||||
BuildRequires: pkgconfig(gstreamer-tag-1.0)
|
||||
BuildRequires: pkgconfig(libpulse)
|
||||
BuildRequires: pkgconfig(libcdio)
|
||||
BuildRequires: pkgconfig(libchromaprint)
|
||||
BuildRequires: pkgconfig(libgpod-1.0)
|
||||
BuildRequires: pkgconfig(libmtp)
|
||||
BuildRequires: pkgconfig(libnotify)
|
||||
BuildRequires: pkgconfig(libudf)
|
||||
|
||||
%description
|
||||
Strawberry is a audio player and music collection organizer.
|
||||
It is a fork of Clementine. The name is inspired by the band Strawbs.
|
||||
|
||||
Features:
|
||||
* Play and organize music
|
||||
* Supports WAV, FLAC, WavPack, DSF, DSDIFF, Ogg Vorbis, Speex, MPC, TrueAudio, AIFF, MP4, MP3 and ASF
|
||||
* Audio CD playback
|
||||
* Native desktop notifications
|
||||
* Playlists in multiple formats
|
||||
* Advanced output and device options with support for bit perfect playback on Linux
|
||||
* Edit tags on music files
|
||||
* Fetch tags from MusicBrainz
|
||||
* Album cover art from Last.fm, Musicbrainz and Discogs
|
||||
* Song lyrics from AudD and API Seeds
|
||||
* Support for multiple backends
|
||||
* Audio analyzer
|
||||
* Equalizer
|
||||
* Transfer music to iPod, iPhone, MTP or mass-storage USB player
|
||||
* Integrated Tidal support
|
||||
|
||||
%prep
|
||||
%setup -qn %{name}-@STRAWBERRY_VERSION_PACKAGE@
|
||||
|
||||
%build
|
||||
|
||||
%if 0%{?fedora} > 27
|
||||
# workaround FTBFS
|
||||
export CXXFLAGS="%{optflags} -fpermissive"
|
||||
%endif
|
||||
|
||||
mkdir %{_target_platform}
|
||||
pushd %{_target_platform}
|
||||
|
||||
%{cmake} \
|
||||
-DBUILD_WERROR:BOOL=OFF \
|
||||
-DCMAKE_BUILD_TYPE:STRING=Release \
|
||||
..
|
||||
popd
|
||||
|
||||
%make_build -C %{_target_platform}
|
||||
|
||||
%install
|
||||
make install DESTDIR=%{buildroot} -C %{_target_platform}
|
||||
rm -rf %{buildroot}%{_datadir}/man
|
||||
|
||||
%check
|
||||
desktop-file-validate %{buildroot}%{_datadir}/applications/strawberry.desktop
|
||||
pushd %{_target_platform}
|
||||
popd
|
||||
|
||||
%clean
|
||||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%doc
|
||||
%{_bindir}/strawberry
|
||||
%{_bindir}/strawberry-tagreader
|
||||
%{_datadir}/applications/strawberry.desktop
|
||||
%{_datadir}/icons/hicolor/48x48/apps/strawberry.png
|
||||
%{_datadir}/icons/hicolor/64x64/apps/strawberry.png
|
||||
%{_datadir}/icons/hicolor/128x128/apps/strawberry.png
|
||||
%{_datadir}/icons/hicolor/scalable/apps/strawberry.svg
|
||||
|
||||
%changelog
|
||||
* @RPM_DATE@ Jonas Kvinge <jonas@strawbs.net> - @STRAWBERRY_VERSION_RPM_V@
|
||||
- Version @STRAWBERRY_VERSION_PACKAGE@
|
||||
@@ -9,7 +9,11 @@ URL: http://www.strawbs.org/
|
||||
Source0: %{name}-@STRAWBERRY_VERSION_PACKAGE@.tar.xz
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
|
||||
%if 0%{?suse_version} > 1325
|
||||
BuildRequires: libboost_headers-devel
|
||||
%else
|
||||
BuildRequires: boost-devel
|
||||
%endif
|
||||
BuildRequires: cmake
|
||||
BuildRequires: desktop-file-utils
|
||||
BuildRequires: gcc-c++
|
||||
@@ -27,32 +31,30 @@ BuildRequires: pkgconfig(gthread-2.0)
|
||||
BuildRequires: pkgconfig(dbus-1)
|
||||
BuildRequires: pkgconfig(alsa)
|
||||
BuildRequires: pkgconfig(protobuf)
|
||||
BuildRequires: pkgconfig(Qt5Concurrent)
|
||||
BuildRequires: pkgconfig(sqlite3) >= 3.7
|
||||
BuildRequires: pkgconfig(taglib) >= 1.11
|
||||
BuildRequires: pkgconfig(Qt5Core)
|
||||
BuildRequires: pkgconfig(Qt5Gui)
|
||||
BuildRequires: pkgconfig(Qt5Network)
|
||||
BuildRequires: pkgconfig(Qt5OpenGL)
|
||||
BuildRequires: pkgconfig(Qt5Sql)
|
||||
BuildRequires: pkgconfig(Qt5Test)
|
||||
BuildRequires: pkgconfig(Qt5WebKit)
|
||||
BuildRequires: pkgconfig(Qt5WebKitWidgets)
|
||||
BuildRequires: pkgconfig(Qt5Widgets)
|
||||
BuildRequires: pkgconfig(Qt5Concurrent)
|
||||
BuildRequires: pkgconfig(Qt5Sql)
|
||||
BuildRequires: pkgconfig(Qt5Network)
|
||||
BuildRequires: pkgconfig(Qt5Xml)
|
||||
BuildRequires: pkgconfig(Qt5X11Extras)
|
||||
BuildRequires: pkgconfig(Qt5DBus)
|
||||
BuildRequires: pkgconfig(Qt5OpenGL)
|
||||
BuildRequires: pkgconfig(gstreamer-1.0)
|
||||
BuildRequires: pkgconfig(gstreamer-app-1.0)
|
||||
BuildRequires: pkgconfig(gstreamer-audio-1.0)
|
||||
BuildRequires: pkgconfig(gstreamer-base-1.0)
|
||||
BuildRequires: pkgconfig(gstreamer-tag-1.0)
|
||||
BuildRequires: pkgconfig(libpulse)
|
||||
BuildRequires: pkgconfig(libcdio)
|
||||
BuildRequires: pkgconfig(libchromaprint)
|
||||
BuildRequires: pkgconfig(libgpod-1.0)
|
||||
BuildRequires: pkgconfig(libmtp)
|
||||
BuildRequires: pkgconfig(libnotify)
|
||||
BuildRequires: pkgconfig(libpulse)
|
||||
BuildRequires: pkgconfig(libudf)
|
||||
BuildRequires: pkgconfig(libxml-2.0)
|
||||
BuildRequires: pkgconfig(sqlite3) >= 3.7
|
||||
BuildRequires: pkgconfig(taglib) >= 1.11
|
||||
BuildRequires: pkgconfig(libxine)
|
||||
BuildRequires: pkgconfig(libvlc)
|
||||
|
||||
@@ -62,13 +64,20 @@ It is a fork of Clementine. The name is inspired by the band Strawbs.
|
||||
|
||||
Features:
|
||||
* Play and organize music
|
||||
* Supports WAV, FLAC, WavPack, DSF, DSDIFF, Ogg Vorbis, Speex, MPC, TrueAudio, AIFF, MP4, MP3 and ASF
|
||||
* Audio CD playback
|
||||
* Native desktop notifications
|
||||
* Playlists in multiple formats
|
||||
* Advanced output and device options with support for bit perfect playback on Linux
|
||||
* Edit tags on music files
|
||||
* Fetch tags from MusicBrainz
|
||||
* Album cover art from Lastfm, Musicbrainz, Discogs and Amazon
|
||||
* Transfer music to iPod, iPhone, MTP or mass-storage USB player
|
||||
* Album cover art from Last.fm, Musicbrainz and Discogs
|
||||
* Song lyrics from AudD and API Seeds
|
||||
* Support for multiple backends
|
||||
* Audio analyzer
|
||||
* Equalizer
|
||||
* Transfer music to iPod, iPhone, MTP or mass-storage USB player
|
||||
* Integrated Tidal support
|
||||
|
||||
%prep
|
||||
%setup -q -n %{name}-@STRAWBERRY_VERSION_PACKAGE@
|
||||
@@ -101,3 +110,4 @@ make clean
|
||||
%changelog
|
||||
* @RPM_DATE@ Jonas Kvinge <jonas@strawbs.net> - @STRAWBERRY_VERSION_RPM_V@
|
||||
- Version @STRAWBERRY_VERSION_PACKAGE@
|
||||
|
||||
18
dist/scripts/maketarball.sh.in
vendored
@@ -16,12 +16,14 @@ echo "Creating $name-$version.tar.xz..."
|
||||
rm -f "$name-$version.tar.xz"
|
||||
tar -cJf $name-$version.tar.xz \
|
||||
--transform "s,^$rootnoslash,$name-$version," $exclude_vcs \
|
||||
--exclude "*.tar" \
|
||||
--exclude "*.tar.*" \
|
||||
--exclude "*.bz" \
|
||||
--exclude "*.bz2" \
|
||||
--exclude "*.xz" \
|
||||
--exclude ".directory" \
|
||||
--exclude "$root/CMakeLists.txt.user" \
|
||||
--exclude "$root/build" \
|
||||
--exclude="*.tar" \
|
||||
--exclude="*.tar.*" \
|
||||
--exclude="*.bz" \
|
||||
--exclude="*.bz2" \
|
||||
--exclude="*.xz" \
|
||||
--exclude=".directory" \
|
||||
--exclude="*.spec" \
|
||||
--exclude="*.nsi" \
|
||||
--exclude="$root/CMakeLists.txt.user" \
|
||||
--exclude="$root/build" \
|
||||
"$root"
|
||||
|
||||
445
dist/windows/strawberry-64.nsi.in
vendored
Normal file
@@ -0,0 +1,445 @@
|
||||
!define PRODUCT_NAME "Strawberry"
|
||||
!define PRODUCT_PUBLISHER "Strawberry"
|
||||
!define PRODUCT_VERSION_MAJOR @STRAWBERRY_VERSION_MAJOR@
|
||||
!define PRODUCT_VERSION_MINOR @STRAWBERRY_VERSION_MINOR@
|
||||
!define PRODUCT_VERSION_PATCH @STRAWBERRY_VERSION_PATCH@
|
||||
!define PRODUCT_DISPLAY_VERSION "@STRAWBERRY_VERSION_PACKAGE@"
|
||||
!define PRODUCT_DISPLAY_VERSION_SHORT "@STRAWBERRY_VERSION_PACKAGE@"
|
||||
!define PRODUCT_WEB_SITE "http://www.strawbs.org/"
|
||||
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
|
||||
!define PRODUCT_UNINST_ROOT_KEY "HKLM"
|
||||
!define PRODUCT_INSTALL_DIR "$PROGRAMFILES\Strawberry Music Player"
|
||||
|
||||
; Set Application Capabilities info
|
||||
!define CAPABILITIES_NAME "Strawberry Music Player"
|
||||
!define CAPABILITIES_LOCAL_NAME "Strawberry"
|
||||
!define CAPABILITIES_PROGID "Strawberry Music Player"
|
||||
!define CAPABILITIES_PATH "Software\Clients\Media\Strawberry"
|
||||
!define CAPABILITIES_DESCRIPTION "Strawberry Music Player"
|
||||
!define CAPABILITIES_ICON "$INSTDIR\strawberry.ico"
|
||||
!define CAPABILITIES_REINSTALL "Command to reinstall"
|
||||
!define CAPABILITIES_HIDE_ICONS "Command to hide icons"
|
||||
!define CAPABILITIES_SHOW_ICONS "Command to show icons"
|
||||
|
||||
SetCompressor /SOLID lzma
|
||||
!addplugindir nsisplugins
|
||||
!include "MUI2.nsh"
|
||||
!include "FileAssociation.nsh"
|
||||
!include "Capabilities.nsh"
|
||||
|
||||
!define MUI_ICON "strawberry.ico"
|
||||
|
||||
!define MUI_COMPONENTSPAGE_SMALLDESC
|
||||
;!define MUI_FINISHPAGE_RUN
|
||||
;!define MUI_FINISHPAGE_RUN_TEXT "Run Strawberry"
|
||||
;!define MUI_FINISHPAGE_RUN_FUNCTION "RunStrawberry"
|
||||
|
||||
; Installer pages
|
||||
!insertmacro MUI_PAGE_WELCOME
|
||||
!insertmacro MUI_PAGE_DIRECTORY
|
||||
!insertmacro MUI_PAGE_INSTFILES
|
||||
!insertmacro MUI_PAGE_FINISH
|
||||
|
||||
; Uninstaller pages
|
||||
!insertmacro MUI_UNPAGE_CONFIRM
|
||||
!insertmacro MUI_UNPAGE_INSTFILES
|
||||
!insertmacro MUI_UNPAGE_FINISH
|
||||
|
||||
!insertmacro MUI_LANGUAGE "English" ;first language is the default language
|
||||
|
||||
Name "${PRODUCT_NAME}"
|
||||
OutFile "${PRODUCT_NAME}Setup-${PRODUCT_DISPLAY_VERSION}-Release-x64.exe"
|
||||
InstallDir "${PRODUCT_INSTALL_DIR}"
|
||||
|
||||
; Get the path where Strawberry was installed previously and set it as default path
|
||||
InstallDirRegKey ${PRODUCT_UNINST_ROOT_KEY} ${PRODUCT_UNINST_KEY} "UninstallString"
|
||||
|
||||
ShowInstDetails show
|
||||
ShowUnInstDetails show
|
||||
RequestExecutionLevel admin
|
||||
;RequestExecutionLevel user
|
||||
|
||||
; Check for previous installation, and call the uninstaller if any
|
||||
Function CheckPreviousInstall
|
||||
|
||||
ReadRegStr $R0 ${PRODUCT_UNINST_ROOT_KEY} ${PRODUCT_UNINST_KEY} "UninstallString"
|
||||
StrCmp $R0 "" done
|
||||
|
||||
MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION \
|
||||
"${PRODUCT_NAME} is already installed. $\n$\nClick `OK` to remove the \
|
||||
previous version or `Cancel` to cancel this upgrade." \
|
||||
IDOK uninst
|
||||
Abort
|
||||
; Run the uninstaller
|
||||
uninst:
|
||||
ClearErrors
|
||||
ExecWait '$R0' ; Do not copy the uninstaller to a temp file
|
||||
|
||||
done:
|
||||
|
||||
FunctionEnd
|
||||
|
||||
Function .onInit
|
||||
|
||||
!insertmacro MUI_LANGDLL_DISPLAY
|
||||
|
||||
Call CheckPreviousInstall
|
||||
|
||||
FunctionEnd
|
||||
|
||||
;Function RunStrawberry
|
||||
;ShellExecAsUser::ShellExecAsUser "" "$INSTDIR/strawberry.exe" ""
|
||||
;FunctionEnd
|
||||
|
||||
Section "Delete old files" oldfiles
|
||||
SectionEnd
|
||||
|
||||
Section "Strawberry" Strawberry
|
||||
SetOutPath "$INSTDIR"
|
||||
|
||||
File "strawberry.exe"
|
||||
File "strawberry-tagreader.exe"
|
||||
File "strawberry.ico"
|
||||
|
||||
File "libbz2.dll"
|
||||
File "libcdio-16.dll"
|
||||
File "libchromaprint.dll"
|
||||
File "libcrypto-1_1-x64.dll"
|
||||
File "libfaad-2.dll"
|
||||
File "libffi-6.dll"
|
||||
File "libFLAC-8.dll"
|
||||
File "libfreetype-6.dll"
|
||||
File "libgcc_s_seh-1.dll"
|
||||
File "libgio-2.0-0.dll"
|
||||
File "libglib-2.0-0.dll"
|
||||
File "libgmodule-2.0-0.dll"
|
||||
File "libgobject-2.0-0.dll"
|
||||
File "libgstapp-1.0-0.dll"
|
||||
File "libgstaudio-1.0-0.dll"
|
||||
File "libgstbase-1.0-0.dll"
|
||||
File "libgstfft-1.0-0.dll"
|
||||
File "libgstpbutils-1.0-0.dll"
|
||||
File "libgstreamer-1.0-0.dll"
|
||||
File "libgstriff-1.0-0.dll"
|
||||
File "libgstrtp-1.0-0.dll"
|
||||
File "libgstrtsp-1.0-0.dll"
|
||||
File "libgstsdp-1.0-0.dll"
|
||||
File "libgsttag-1.0-0.dll"
|
||||
File "libgstvideo-1.0-0.dll"
|
||||
File "libgstnet-1.0-0.dll"
|
||||
File "libharfbuzz-0.dll"
|
||||
File "libiconv-2.dll"
|
||||
File "libintl-8.dll"
|
||||
File "libjpeg-9.dll"
|
||||
File "liblastfm5.dll"
|
||||
File "libmp3lame-0.dll"
|
||||
File "libogg-0.dll"
|
||||
File "libopus-0.dll"
|
||||
File "libpcre-1.dll"
|
||||
File "libpcre2-16-0.dll"
|
||||
File "libpng16-16.dll"
|
||||
File "libprotobuf-15.dll"
|
||||
File "libspeex-1.dll"
|
||||
File "libsqlite3-0.dll"
|
||||
File "libssl-1_1-x64.dll"
|
||||
File "libstdc++-6.dll"
|
||||
File "libtag.dll"
|
||||
File "libvorbis-0.dll"
|
||||
File "libvorbisenc-2.dll"
|
||||
File "libwavpack-1.dll"
|
||||
File "libwinpthread-1.dll"
|
||||
File "Qt5Concurrent.dll"
|
||||
File "Qt5Core.dll"
|
||||
File "Qt5Gui.dll"
|
||||
File "Qt5Network.dll"
|
||||
File "Qt5Sql.dll"
|
||||
File "Qt5Widgets.dll"
|
||||
File "Qt5Xml.dll"
|
||||
File "Qt5WinExtras.dll"
|
||||
File "zlib1.dll"
|
||||
;File "libmpcdec-5.dll"
|
||||
;File "libtheora-0.dll"
|
||||
File "libfftw3-3.dll"
|
||||
File "libxml2-2.dll"
|
||||
File "libsoup-2.4-1.dll"
|
||||
File "liblzma-5.dll"
|
||||
|
||||
; Register Strawberry with Default Programs
|
||||
Var /GLOBAL AppIcon
|
||||
Var /GLOBAL AppExe
|
||||
StrCpy $AppExe "$INSTDIR\strawberry.exe"
|
||||
StrCpy $AppIcon "$INSTDIR\strawberry.ico"
|
||||
|
||||
${RegisterCapabilities}
|
||||
|
||||
${RegisterMediaType} ".mp3" $AppExe $AppIcon "MP3 Audio File"
|
||||
${RegisterMediaType} ".flac" $AppExe $AppIcon "FLAC Audio File"
|
||||
${RegisterMediaType} ".ogg" $AppExe $AppIcon "OGG Audio File"
|
||||
${RegisterMediaType} ".spx" $AppExe $AppIcon "OGG Speex Audio File"
|
||||
${RegisterMediaType} ".m4a" $AppExe $AppIcon "MP4 Audio File"
|
||||
${RegisterMediaType} ".aac" $AppExe $AppIcon "AAC Audio File"
|
||||
${RegisterMediaType} ".wma" $AppExe $AppIcon "WMA Audio File"
|
||||
${RegisterMediaType} ".wav" $AppExe $AppIcon "WAV Audio File"
|
||||
|
||||
${RegisterMediaType} ".pls" $AppExe $AppIcon "PLS Audio File"
|
||||
${RegisterMediaType} ".m3u" $AppExe $AppIcon "M3U Audio File"
|
||||
${RegisterMediaType} ".xspf" $AppExe $AppIcon "XSPF Audio File"
|
||||
${RegisterMediaType} ".asx" $AppExe $AppIcon "Windows Media Audio/Video playlist"
|
||||
|
||||
${RegisterMimeType} "audio/mp3" "mp3" "{cd3afa76-b84f-48f0-9393-7edc34128127}"
|
||||
${RegisterMimeType} "audio/mp4" "m4a" "{cd3afa7c-b84f-48f0-9393-7edc34128127}"
|
||||
${RegisterMimeType} "audio/x-ms-wma" "wma" "{cd3afa84-b84f-48f0-9393-7edc34128127}"
|
||||
${RegisterMimeType} "audio/wav" "wav" "{cd3afa7b-b84f-48f0-9393-7edc34128127}"
|
||||
|
||||
${RegisterMimeType} "audio/mpegurl" "m3u" "{cd3afa78-b84f-48f0-9393-7edc34128127}"
|
||||
${RegisterMimeType} "application/x-wmplayer" "asx" "{cd3afa96-b84f-48f0-9393-7edc34128127}"
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "Qt Platforms" platforms
|
||||
SetOutPath "$INSTDIR\platforms"
|
||||
File "/oname=qwindows.dll" "platforms\qwindows.dll"
|
||||
SectionEnd
|
||||
|
||||
Section "Qt SQL Drivers" sqldrivers
|
||||
SetOutPath "$INSTDIR\sqldrivers"
|
||||
File "/oname=qsqlite.dll" "sqldrivers\qsqlite.dll"
|
||||
SectionEnd
|
||||
|
||||
Section "Qt image format plugins" imageformats
|
||||
SetOutPath "$INSTDIR\imageformats"
|
||||
File "/oname=qgif.dll" "imageformats\qgif.dll"
|
||||
File "/oname=qico.dll" "imageformats\qico.dll"
|
||||
File "/oname=qjpeg.dll" "imageformats\qjpeg.dll"
|
||||
SectionEnd
|
||||
|
||||
Section "Gstreamer plugins" gstreamer-plugins
|
||||
SetOutPath "$INSTDIR\gstreamer-plugins"
|
||||
|
||||
File "/oname=libgstapetag.dll" "gstreamer-plugins\libgstapetag.dll"
|
||||
File "/oname=libgstapp.dll" "gstreamer-plugins\libgstapp.dll"
|
||||
File "/oname=libgstasf.dll" "gstreamer-plugins\libgstasf.dll"
|
||||
File "/oname=libgstaiff.dll" "gstreamer-plugins\libgstaiff.dll"
|
||||
File "/oname=libgstaudioconvert.dll" "gstreamer-plugins\libgstaudioconvert.dll"
|
||||
File "/oname=libgstaudiofx.dll" "gstreamer-plugins\libgstaudiofx.dll"
|
||||
File "/oname=libgstaudioparsers.dll" "gstreamer-plugins\libgstaudioparsers.dll"
|
||||
File "/oname=libgstaudioresample.dll" "gstreamer-plugins\libgstaudioresample.dll"
|
||||
File "/oname=libgstaudiotestsrc.dll" "gstreamer-plugins\libgstaudiotestsrc.dll"
|
||||
File "/oname=libgstautodetect.dll" "gstreamer-plugins\libgstautodetect.dll"
|
||||
File "/oname=libgstcoreelements.dll" "gstreamer-plugins\libgstcoreelements.dll"
|
||||
File "/oname=libgstdirectsound.dll" "gstreamer-plugins\libgstdirectsound.dll"
|
||||
File "/oname=libgstequalizer.dll" "gstreamer-plugins\libgstequalizer.dll"
|
||||
File "/oname=libgstfaad.dll" "gstreamer-plugins\libgstfaad.dll"
|
||||
File "/oname=libgstflac.dll" "gstreamer-plugins\libgstflac.dll"
|
||||
File "/oname=libgstgio.dll" "gstreamer-plugins\libgstgio.dll"
|
||||
File "/oname=libgsticydemux.dll" "gstreamer-plugins\libgsticydemux.dll"
|
||||
File "/oname=libgstid3demux.dll" "gstreamer-plugins\libgstid3demux.dll"
|
||||
File "/oname=libgstisomp4.dll" "gstreamer-plugins\libgstisomp4.dll"
|
||||
File "/oname=libgstlame.dll" "gstreamer-plugins\libgstlame.dll"
|
||||
File "/oname=libgstogg.dll" "gstreamer-plugins\libgstogg.dll"
|
||||
File "/oname=libgstopusparse.dll" "gstreamer-plugins\libgstopusparse.dll"
|
||||
File "/oname=libgstplayback.dll" "gstreamer-plugins\libgstplayback.dll"
|
||||
File "/oname=libgstreplaygain.dll" "gstreamer-plugins\libgstreplaygain.dll"
|
||||
File "/oname=libgstspectrum.dll" "gstreamer-plugins\libgstspectrum.dll"
|
||||
File "/oname=libgstspeex.dll" "gstreamer-plugins\libgstspeex.dll"
|
||||
File "/oname=libgsttaglib.dll" "gstreamer-plugins\libgsttaglib.dll"
|
||||
File "/oname=libgsttypefindfunctions.dll" "gstreamer-plugins\libgsttypefindfunctions.dll"
|
||||
File "/oname=libgstvolume.dll" "gstreamer-plugins\libgstvolume.dll"
|
||||
File "/oname=libgstvorbis.dll" "gstreamer-plugins\libgstvorbis.dll"
|
||||
File "/oname=libgstwavpack.dll" "gstreamer-plugins\libgstwavpack.dll"
|
||||
File "/oname=libgstwavparse.dll" "gstreamer-plugins\libgstwavparse.dll"
|
||||
File "/oname=libgstcdio.dll" "gstreamer-plugins\libgstcdio.dll"
|
||||
File "/oname=libgsttcp.dll" "gstreamer-plugins\libgsttcp.dll"
|
||||
File "/oname=libgstudp.dll" "gstreamer-plugins\libgstudp.dll"
|
||||
File "/oname=libgstsoup.dll" "gstreamer-plugins\libgstsoup.dll"
|
||||
File "/oname=libgstlibav.dll" "gstreamer-plugins\libgstlibav.dll"
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "Start menu items" startmenu
|
||||
; Create Start Menu folders and shortcuts.
|
||||
SetShellVarContext all
|
||||
|
||||
CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}"
|
||||
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk" "$INSTDIR\strawberry.exe"
|
||||
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "Uninstaller"
|
||||
; Create uninstaller
|
||||
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
||||
|
||||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "${PRODUCT_NAME}"
|
||||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\Uninstall.exe"
|
||||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\strawberry.ico"
|
||||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_DISPLAY_VERSION}"
|
||||
WriteRegDWORD ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "VersionMajor" "${PRODUCT_VERSION_MAJOR}"
|
||||
WriteRegDWORD ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "VersionMinor" "${PRODUCT_VERSION_MINOR}"
|
||||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
|
||||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "Uninstall"
|
||||
; Kill strawberry.exe if it's running
|
||||
; This calling convention is retarded...
|
||||
;StrCpy $0 "strawberry.exe"
|
||||
;KillProc::FindProcesses
|
||||
;StrCmp $1 "-1" wooops
|
||||
|
||||
;StrCmp $0 "0" completed
|
||||
|
||||
;DetailPrint "Killing running strawberry.exe..."
|
||||
|
||||
;StrCpy $0 "strawberry.exe"
|
||||
;KillProc::KillProcesses
|
||||
;StrCmp $1 "-1" wooops
|
||||
|
||||
;Sleep 2000
|
||||
;Goto completed
|
||||
|
||||
;wooops:
|
||||
;DetailPrint "-> Error: Something went wrong while killing running strawberry.exe"
|
||||
;Abort
|
||||
|
||||
;completed:
|
||||
|
||||
; Delete all the files
|
||||
|
||||
Delete "$INSTDIR\strawberry.ico"
|
||||
Delete "$INSTDIR\strawberry.exe"
|
||||
Delete "$INSTDIR\strawberry-tagreader.exe"
|
||||
|
||||
Delete "$INSTDIR\libbz2.dll"
|
||||
Delete "$INSTDIR\libcdio-16.dll"
|
||||
Delete "$INSTDIR\libchromaprint.dll"
|
||||
Delete "$INSTDIR\libcrypto-1_1.dll"
|
||||
Delete "$INSTDIR\libfaad-2.dll"
|
||||
Delete "$INSTDIR\libffi-6.dll"
|
||||
Delete "$INSTDIR\libFLAC-8.dll"
|
||||
Delete "$INSTDIR\libfreetype-6.dll"
|
||||
Delete "$INSTDIR\libgcc_s_sjlj-1.dll"
|
||||
Delete "$INSTDIR\libgio-2.0-0.dll"
|
||||
Delete "$INSTDIR\libglib-2.0-0.dll"
|
||||
Delete "$INSTDIR\libgmodule-2.0-0.dll"
|
||||
Delete "$INSTDIR\libgobject-2.0-0.dll"
|
||||
Delete "$INSTDIR\libgstapp-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstaudio-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstbase-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstfft-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstpbutils-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstreamer-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstriff-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstrtp-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstrtsp-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstsdp-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgsttag-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstvideo-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstnet-1.0-0.dll"
|
||||
Delete "$INSTDIR\libharfbuzz-0.dll"
|
||||
Delete "$INSTDIR\libiconv-2.dll"
|
||||
Delete "$INSTDIR\libintl-8.dll"
|
||||
Delete "$INSTDIR\libjpeg-9.dll"
|
||||
Delete "$INSTDIR\liblastfm5.dll"
|
||||
Delete "$INSTDIR\libmp3lame-0.dll"
|
||||
Delete "$INSTDIR\libogg-0.dll"
|
||||
Delete "$INSTDIR\libopus-0.dll"
|
||||
Delete "$INSTDIR\libpcre-1.dll"
|
||||
Delete "$INSTDIR\libpcre2-16-0.dll"
|
||||
Delete "$INSTDIR\libpng16-16.dll"
|
||||
Delete "$INSTDIR\libprotobuf-15.dll"
|
||||
Delete "$INSTDIR\libspeex-1.dll"
|
||||
Delete "$INSTDIR\libsqlite3-0.dll"
|
||||
Delete "$INSTDIR\libssl-1_1.dll"
|
||||
Delete "$INSTDIR\libstdc++-6.dll"
|
||||
Delete "$INSTDIR\libtag.dll"
|
||||
Delete "$INSTDIR\libvorbis-0.dll"
|
||||
Delete "$INSTDIR\libvorbisenc-2.dll"
|
||||
Delete "$INSTDIR\libwavpack-1.dll"
|
||||
Delete "$INSTDIR\libwinpthread-1.dll"
|
||||
Delete "$INSTDIR\Qt5Concurrent.dll"
|
||||
Delete "$INSTDIR\Qt5Core.dll"
|
||||
Delete "$INSTDIR\Qt5Gui.dll"
|
||||
Delete "$INSTDIR\Qt5Network.dll"
|
||||
Delete "$INSTDIR\Qt5Sql.dll"
|
||||
Delete "$INSTDIR\Qt5Widgets.dll"
|
||||
Delete "$INSTDIR\Qt5Xml.dll"
|
||||
Delete "$INSTDIR\Qt5WinExtras.dll"
|
||||
Delete "$INSTDIR\zlib1.dll"
|
||||
;Delete "$INSTDIR\libmpcdec-5.dll"
|
||||
;Delete "$INSTDIR\libtheora-0.dll"
|
||||
Delete "$INSTDIR\libfftw3-3.dll"
|
||||
Delete "$INSTDIR\libxml2-2.dll"
|
||||
Delete "$INSTDIR\libsoup-2.4-1.dll"
|
||||
Delete "$INSTDIR\liblzma-5.dll"
|
||||
|
||||
Delete "$INSTDIR\platforms\qwindows.dll"
|
||||
Delete "$INSTDIR\sqldrivers\qsqlite.dll"
|
||||
|
||||
Delete "$INSTDIR\imageformats\qgif.dll"
|
||||
Delete "$INSTDIR\imageformats\qico.dll"
|
||||
Delete "$INSTDIR\imageformats\qjpeg.dll"
|
||||
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstapetag.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstapp.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstasf.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstaiff.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstaudioconvert.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstaudiofx.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstaudioparsers.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstaudioresample.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstaudiotestsrc.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstautodetect.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstcoreelements.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstdirectsound.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstequalizer.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstfaad.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstflac.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstgio.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgsticydemux.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstid3demux.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstisomp4.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstlame.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstogg.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstopusparse.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstplayback.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstreplaygain.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstspectrum.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstspeex.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgsttaglib.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgsttypefindfunctions.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstvolume.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstvorbis.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstwavpack.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstwavparse.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstcdio.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgsttcp.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstudp.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstsoup.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstlibav.dll"
|
||||
|
||||
Delete "$INSTDIR\Uninstall.exe"
|
||||
|
||||
; Remove the installation folders.
|
||||
RMDir "$INSTDIR\platforms"
|
||||
RMDir "$INSTDIR\sqldrivers"
|
||||
RMDir "$INSTDIR\imageformats"
|
||||
RMDir "$INSTDIR\gstreamer-plugins"
|
||||
RMDir "$INSTDIR\xine-plugins"
|
||||
RMDir "$INSTDIR"
|
||||
|
||||
; Remove the Shortcuts
|
||||
SetShellVarContext all
|
||||
|
||||
Delete "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk"
|
||||
Delete "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk"
|
||||
RMDir /r "$SMPROGRAMS\${PRODUCT_NAME}"
|
||||
|
||||
; Remove the entry from 'installed programs list'
|
||||
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
|
||||
|
||||
; Unregister from Default Programs
|
||||
${UnRegisterCapabilities}
|
||||
|
||||
SectionEnd
|
||||
505
dist/windows/strawberry-debug-64.nsi.in
vendored
Normal file
@@ -0,0 +1,505 @@
|
||||
!define PRODUCT_NAME "Strawberry"
|
||||
!define PRODUCT_PUBLISHER "Strawberry"
|
||||
!define PRODUCT_VERSION_MAJOR @STRAWBERRY_VERSION_MAJOR@
|
||||
!define PRODUCT_VERSION_MINOR @STRAWBERRY_VERSION_MINOR@
|
||||
!define PRODUCT_VERSION_PATCH @STRAWBERRY_VERSION_PATCH@
|
||||
!define PRODUCT_DISPLAY_VERSION "@STRAWBERRY_VERSION_PACKAGE@"
|
||||
!define PRODUCT_DISPLAY_VERSION_SHORT "@STRAWBERRY_VERSION_PACKAGE@"
|
||||
!define PRODUCT_WEB_SITE "http://www.strawbs.org/"
|
||||
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
|
||||
!define PRODUCT_UNINST_ROOT_KEY "HKLM"
|
||||
!define PRODUCT_INSTALL_DIR "$PROGRAMFILES\Strawberry Music Player"
|
||||
|
||||
; Set Application Capabilities info
|
||||
!define CAPABILITIES_NAME "Strawberry Music Player"
|
||||
!define CAPABILITIES_LOCAL_NAME "Strawberry"
|
||||
!define CAPABILITIES_PROGID "Strawberry Music Player"
|
||||
!define CAPABILITIES_PATH "Software\Clients\Media\Strawberry"
|
||||
!define CAPABILITIES_DESCRIPTION "Strawberry Music Player"
|
||||
!define CAPABILITIES_ICON "$INSTDIR\strawberry.ico"
|
||||
!define CAPABILITIES_REINSTALL "Command to reinstall"
|
||||
!define CAPABILITIES_HIDE_ICONS "Command to hide icons"
|
||||
!define CAPABILITIES_SHOW_ICONS "Command to show icons"
|
||||
|
||||
SetCompressor /SOLID lzma
|
||||
!addplugindir nsisplugins
|
||||
!include "MUI2.nsh"
|
||||
!include "FileAssociation.nsh"
|
||||
!include "Capabilities.nsh"
|
||||
|
||||
!define MUI_ICON "strawberry.ico"
|
||||
|
||||
!define MUI_COMPONENTSPAGE_SMALLDESC
|
||||
;!define MUI_FINISHPAGE_RUN
|
||||
;!define MUI_FINISHPAGE_RUN_TEXT "Run Strawberry"
|
||||
;!define MUI_FINISHPAGE_RUN_FUNCTION "RunStrawberry"
|
||||
|
||||
; Installer pages
|
||||
!insertmacro MUI_PAGE_WELCOME
|
||||
!insertmacro MUI_PAGE_DIRECTORY
|
||||
!insertmacro MUI_PAGE_INSTFILES
|
||||
!insertmacro MUI_PAGE_FINISH
|
||||
|
||||
; Uninstaller pages
|
||||
!insertmacro MUI_UNPAGE_CONFIRM
|
||||
!insertmacro MUI_UNPAGE_INSTFILES
|
||||
!insertmacro MUI_UNPAGE_FINISH
|
||||
|
||||
!insertmacro MUI_LANGUAGE "English" ;first language is the default language
|
||||
|
||||
Name "${PRODUCT_NAME}"
|
||||
OutFile "${PRODUCT_NAME}Setup-${PRODUCT_DISPLAY_VERSION}-Debug-x64.exe"
|
||||
InstallDir "${PRODUCT_INSTALL_DIR}"
|
||||
|
||||
; Get the path where Strawberry was installed previously and set it as default path
|
||||
InstallDirRegKey ${PRODUCT_UNINST_ROOT_KEY} ${PRODUCT_UNINST_KEY} "UninstallString"
|
||||
|
||||
ShowInstDetails show
|
||||
ShowUnInstDetails show
|
||||
RequestExecutionLevel admin
|
||||
;RequestExecutionLevel user
|
||||
|
||||
; Check for previous installation, and call the uninstaller if any
|
||||
Function CheckPreviousInstall
|
||||
|
||||
ReadRegStr $R0 ${PRODUCT_UNINST_ROOT_KEY} ${PRODUCT_UNINST_KEY} "UninstallString"
|
||||
StrCmp $R0 "" done
|
||||
|
||||
MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION \
|
||||
"${PRODUCT_NAME} is already installed. $\n$\nClick `OK` to remove the \
|
||||
previous version or `Cancel` to cancel this upgrade." \
|
||||
IDOK uninst
|
||||
Abort
|
||||
; Run the uninstaller
|
||||
uninst:
|
||||
ClearErrors
|
||||
ExecWait '$R0' ; Do not copy the uninstaller to a temp file
|
||||
|
||||
done:
|
||||
|
||||
FunctionEnd
|
||||
|
||||
Function .onInit
|
||||
|
||||
!insertmacro MUI_LANGDLL_DISPLAY
|
||||
|
||||
Call CheckPreviousInstall
|
||||
|
||||
FunctionEnd
|
||||
|
||||
;Function RunStrawberry
|
||||
;ShellExecAsUser::ShellExecAsUser "" "$INSTDIR/strawberry.exe" ""
|
||||
;FunctionEnd
|
||||
|
||||
Section "Delete old files" oldfiles
|
||||
SectionEnd
|
||||
|
||||
Section "Strawberry" Strawberry
|
||||
SetOutPath "$INSTDIR"
|
||||
|
||||
File "strawberry.exe"
|
||||
File "strawberry-tagreader.exe"
|
||||
File "strawberry.ico"
|
||||
|
||||
File "libbz2.dll"
|
||||
File "libcdio-16.dll"
|
||||
File "libchromaprint.dll"
|
||||
File "libcrypto-1_1-x64.dll"
|
||||
File "libfaad-2.dll"
|
||||
File "libffi-6.dll"
|
||||
File "libFLAC-8.dll"
|
||||
File "libfreetype-6.dll"
|
||||
File "libgcc_s_seh-1.dll"
|
||||
File "libgio-2.0-0.dll"
|
||||
File "libglib-2.0-0.dll"
|
||||
File "libgmodule-2.0-0.dll"
|
||||
File "libgobject-2.0-0.dll"
|
||||
File "libgstapp-1.0-0.dll"
|
||||
File "libgstaudio-1.0-0.dll"
|
||||
File "libgstbase-1.0-0.dll"
|
||||
File "libgstfft-1.0-0.dll"
|
||||
File "libgstpbutils-1.0-0.dll"
|
||||
File "libgstreamer-1.0-0.dll"
|
||||
File "libgstriff-1.0-0.dll"
|
||||
File "libgstrtp-1.0-0.dll"
|
||||
File "libgstrtsp-1.0-0.dll"
|
||||
File "libgstsdp-1.0-0.dll"
|
||||
File "libgsttag-1.0-0.dll"
|
||||
File "libgstvideo-1.0-0.dll"
|
||||
File "libgstnet-1.0-0.dll"
|
||||
File "libharfbuzz-0.dll"
|
||||
File "libiconv-2.dll"
|
||||
File "libintl-8.dll"
|
||||
File "libjpeg-9.dll"
|
||||
File "liblastfm5.dll"
|
||||
File "libmp3lame-0.dll"
|
||||
File "libogg-0.dll"
|
||||
File "libopus-0.dll"
|
||||
File "libpcre-1.dll"
|
||||
File "libpcre2-16-0.dll"
|
||||
File "libpng16-16.dll"
|
||||
File "libprotobuf-15.dll"
|
||||
File "libspeex-1.dll"
|
||||
File "libsqlite3-0.dll"
|
||||
File "libssl-1_1-x64.dll"
|
||||
File "libstdc++-6.dll"
|
||||
File "libtag.dll"
|
||||
File "libvorbis-0.dll"
|
||||
File "libvorbisenc-2.dll"
|
||||
File "libwavpack-1.dll"
|
||||
File "libwinpthread-1.dll"
|
||||
File "Qt5Concurrent.dll"
|
||||
File "Qt5Core.dll"
|
||||
File "Qt5Gui.dll"
|
||||
File "Qt5Network.dll"
|
||||
File "Qt5Sql.dll"
|
||||
File "Qt5Widgets.dll"
|
||||
File "Qt5Xml.dll"
|
||||
File "Qt5WinExtras.dll"
|
||||
File "zlib1.dll"
|
||||
File "libxine-2.dll"
|
||||
File "libmpcdec-5.dll"
|
||||
File "libtheora-0.dll"
|
||||
File "libfftw3-3.dll"
|
||||
File "libxml2-2.dll"
|
||||
File "libsoup-2.4-1.dll"
|
||||
File "liblzma-5.dll"
|
||||
|
||||
; Register Strawberry with Default Programs
|
||||
Var /GLOBAL AppIcon
|
||||
Var /GLOBAL AppExe
|
||||
StrCpy $AppExe "$INSTDIR\strawberry.exe"
|
||||
StrCpy $AppIcon "$INSTDIR\strawberry.ico"
|
||||
|
||||
${RegisterCapabilities}
|
||||
|
||||
${RegisterMediaType} ".mp3" $AppExe $AppIcon "MP3 Audio File"
|
||||
${RegisterMediaType} ".flac" $AppExe $AppIcon "FLAC Audio File"
|
||||
${RegisterMediaType} ".ogg" $AppExe $AppIcon "OGG Audio File"
|
||||
${RegisterMediaType} ".spx" $AppExe $AppIcon "OGG Speex Audio File"
|
||||
${RegisterMediaType} ".m4a" $AppExe $AppIcon "MP4 Audio File"
|
||||
${RegisterMediaType} ".aac" $AppExe $AppIcon "AAC Audio File"
|
||||
${RegisterMediaType} ".wma" $AppExe $AppIcon "WMA Audio File"
|
||||
${RegisterMediaType} ".wav" $AppExe $AppIcon "WAV Audio File"
|
||||
|
||||
${RegisterMediaType} ".pls" $AppExe $AppIcon "PLS Audio File"
|
||||
${RegisterMediaType} ".m3u" $AppExe $AppIcon "M3U Audio File"
|
||||
${RegisterMediaType} ".xspf" $AppExe $AppIcon "XSPF Audio File"
|
||||
${RegisterMediaType} ".asx" $AppExe $AppIcon "Windows Media Audio/Video playlist"
|
||||
|
||||
${RegisterMimeType} "audio/mp3" "mp3" "{cd3afa76-b84f-48f0-9393-7edc34128127}"
|
||||
${RegisterMimeType} "audio/mp4" "m4a" "{cd3afa7c-b84f-48f0-9393-7edc34128127}"
|
||||
${RegisterMimeType} "audio/x-ms-wma" "wma" "{cd3afa84-b84f-48f0-9393-7edc34128127}"
|
||||
${RegisterMimeType} "audio/wav" "wav" "{cd3afa7b-b84f-48f0-9393-7edc34128127}"
|
||||
|
||||
${RegisterMimeType} "audio/mpegurl" "m3u" "{cd3afa78-b84f-48f0-9393-7edc34128127}"
|
||||
${RegisterMimeType} "application/x-wmplayer" "asx" "{cd3afa96-b84f-48f0-9393-7edc34128127}"
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "Qt Platforms" platforms
|
||||
SetOutPath "$INSTDIR\platforms"
|
||||
File "/oname=qwindows.dll" "platforms\qwindows.dll"
|
||||
SectionEnd
|
||||
|
||||
Section "Qt SQL Drivers" sqldrivers
|
||||
SetOutPath "$INSTDIR\sqldrivers"
|
||||
File "/oname=qsqlite.dll" "sqldrivers\qsqlite.dll"
|
||||
SectionEnd
|
||||
|
||||
Section "Qt image format plugins" imageformats
|
||||
SetOutPath "$INSTDIR\imageformats"
|
||||
File "/oname=qgif.dll" "imageformats\qgif.dll"
|
||||
File "/oname=qico.dll" "imageformats\qico.dll"
|
||||
File "/oname=qjpeg.dll" "imageformats\qjpeg.dll"
|
||||
SectionEnd
|
||||
|
||||
Section "Gstreamer plugins" gstreamer-plugins
|
||||
SetOutPath "$INSTDIR\gstreamer-plugins"
|
||||
|
||||
File "/oname=libgstapetag.dll" "gstreamer-plugins\libgstapetag.dll"
|
||||
File "/oname=libgstapp.dll" "gstreamer-plugins\libgstapp.dll"
|
||||
File "/oname=libgstasf.dll" "gstreamer-plugins\libgstasf.dll"
|
||||
File "/oname=libgstaiff.dll" "gstreamer-plugins\libgstaiff.dll"
|
||||
File "/oname=libgstaudioconvert.dll" "gstreamer-plugins\libgstaudioconvert.dll"
|
||||
File "/oname=libgstaudiofx.dll" "gstreamer-plugins\libgstaudiofx.dll"
|
||||
File "/oname=libgstaudioparsers.dll" "gstreamer-plugins\libgstaudioparsers.dll"
|
||||
File "/oname=libgstaudioresample.dll" "gstreamer-plugins\libgstaudioresample.dll"
|
||||
File "/oname=libgstaudiotestsrc.dll" "gstreamer-plugins\libgstaudiotestsrc.dll"
|
||||
File "/oname=libgstautodetect.dll" "gstreamer-plugins\libgstautodetect.dll"
|
||||
File "/oname=libgstcoreelements.dll" "gstreamer-plugins\libgstcoreelements.dll"
|
||||
File "/oname=libgstdirectsound.dll" "gstreamer-plugins\libgstdirectsound.dll"
|
||||
File "/oname=libgstequalizer.dll" "gstreamer-plugins\libgstequalizer.dll"
|
||||
File "/oname=libgstfaad.dll" "gstreamer-plugins\libgstfaad.dll"
|
||||
File "/oname=libgstflac.dll" "gstreamer-plugins\libgstflac.dll"
|
||||
File "/oname=libgstgio.dll" "gstreamer-plugins\libgstgio.dll"
|
||||
File "/oname=libgsticydemux.dll" "gstreamer-plugins\libgsticydemux.dll"
|
||||
File "/oname=libgstid3demux.dll" "gstreamer-plugins\libgstid3demux.dll"
|
||||
File "/oname=libgstisomp4.dll" "gstreamer-plugins\libgstisomp4.dll"
|
||||
File "/oname=libgstlame.dll" "gstreamer-plugins\libgstlame.dll"
|
||||
File "/oname=libgstogg.dll" "gstreamer-plugins\libgstogg.dll"
|
||||
File "/oname=libgstopusparse.dll" "gstreamer-plugins\libgstopusparse.dll"
|
||||
File "/oname=libgstplayback.dll" "gstreamer-plugins\libgstplayback.dll"
|
||||
File "/oname=libgstreplaygain.dll" "gstreamer-plugins\libgstreplaygain.dll"
|
||||
File "/oname=libgstspectrum.dll" "gstreamer-plugins\libgstspectrum.dll"
|
||||
File "/oname=libgstspeex.dll" "gstreamer-plugins\libgstspeex.dll"
|
||||
File "/oname=libgsttaglib.dll" "gstreamer-plugins\libgsttaglib.dll"
|
||||
File "/oname=libgsttypefindfunctions.dll" "gstreamer-plugins\libgsttypefindfunctions.dll"
|
||||
File "/oname=libgstvolume.dll" "gstreamer-plugins\libgstvolume.dll"
|
||||
File "/oname=libgstvorbis.dll" "gstreamer-plugins\libgstvorbis.dll"
|
||||
File "/oname=libgstwavpack.dll" "gstreamer-plugins\libgstwavpack.dll"
|
||||
File "/oname=libgstwavparse.dll" "gstreamer-plugins\libgstwavparse.dll"
|
||||
File "/oname=libgstcdio.dll" "gstreamer-plugins\libgstcdio.dll"
|
||||
File "/oname=libgsttcp.dll" "gstreamer-plugins\libgsttcp.dll"
|
||||
File "/oname=libgstudp.dll" "gstreamer-plugins\libgstudp.dll"
|
||||
File "/oname=libgstsoup.dll" "gstreamer-plugins\libgstsoup.dll"
|
||||
File "/oname=libgstlibav.dll" "gstreamer-plugins\libgstlibav.dll"
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "Xine plugins" xine-plugins
|
||||
SetOutPath "$INSTDIR\xine-plugins"
|
||||
File "/oname=xineplug_ao_out_directx2.dll" "xine-plugins\xineplug_ao_out_directx2.dll"
|
||||
File "/oname=xineplug_ao_out_directx.dll" "xine-plugins\xineplug_ao_out_directx.dll"
|
||||
File "/oname=xineplug_decode_dts.dll" "xine-plugins\xineplug_decode_dts.dll"
|
||||
File "/oname=xineplug_decode_dvaudio.dll" "xine-plugins\xineplug_decode_dvaudio.dll"
|
||||
File "/oname=xineplug_decode_faad.dll" "xine-plugins\xineplug_decode_faad.dll"
|
||||
File "/oname=xineplug_decode_gsm610.dll" "xine-plugins\xineplug_decode_gsm610.dll"
|
||||
File "/oname=xineplug_decode_lpcm.dll" "xine-plugins\xineplug_decode_lpcm.dll"
|
||||
File "/oname=xineplug_decode_mad.dll" "xine-plugins\xineplug_decode_mad.dll"
|
||||
File "/oname=xineplug_decode_mpc.dll" "xine-plugins\xineplug_decode_mpc.dll"
|
||||
File "/oname=xineplug_decode_mpeg2.dll" "xine-plugins\xineplug_decode_mpeg2.dll"
|
||||
File "/oname=xineplug_dmx_asf.dll" "xine-plugins\xineplug_dmx_asf.dll"
|
||||
File "/oname=xineplug_dmx_audio.dll" "xine-plugins\xineplug_dmx_audio.dll"
|
||||
File "/oname=xineplug_dmx_playlist.dll" "xine-plugins\xineplug_dmx_playlist.dll"
|
||||
File "/oname=xineplug_dmx_slave.dll" "xine-plugins\xineplug_dmx_slave.dll"
|
||||
File "/oname=xineplug_flac.dll" "xine-plugins\xineplug_flac.dll"
|
||||
File "/oname=xineplug_wavpack.dll" "xine-plugins\xineplug_wavpack.dll"
|
||||
File "/oname=xineplug_xiph.dll" "xine-plugins\xineplug_xiph.dll"
|
||||
File "/oname=xineplug_inp_cdda.dll" "xine-plugins\xineplug_inp_cdda.dll"
|
||||
|
||||
File "/oname=xineplug_post_audio_filters.dll" "xine-plugins\xineplug_post_audio_filters.dll"
|
||||
File "/oname=xineplug_post_goom.dll" "xine-plugins\xineplug_post_goom.dll"
|
||||
File "/oname=xineplug_post_mosaico.dll" "xine-plugins\xineplug_post_mosaico.dll"
|
||||
File "/oname=xineplug_post_planar.dll" "xine-plugins\xineplug_post_planar.dll"
|
||||
File "/oname=xineplug_post_switch.dll" "xine-plugins\xineplug_post_switch.dll"
|
||||
File "/oname=xineplug_post_tvtime.dll" "xine-plugins\xineplug_post_tvtime.dll"
|
||||
File "/oname=xineplug_post_visualizations.dll" "xine-plugins\xineplug_post_visualizations.dll"
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "Start menu items" startmenu
|
||||
; Create Start Menu folders and shortcuts.
|
||||
SetShellVarContext all
|
||||
|
||||
CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}"
|
||||
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk" "$INSTDIR\strawberry.exe"
|
||||
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "Uninstaller"
|
||||
; Create uninstaller
|
||||
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
||||
|
||||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "${PRODUCT_NAME}"
|
||||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\Uninstall.exe"
|
||||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\strawberry.ico"
|
||||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_DISPLAY_VERSION}"
|
||||
WriteRegDWORD ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "VersionMajor" "${PRODUCT_VERSION_MAJOR}"
|
||||
WriteRegDWORD ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "VersionMinor" "${PRODUCT_VERSION_MINOR}"
|
||||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
|
||||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "Uninstall"
|
||||
; Kill strawberry.exe if it's running
|
||||
; This calling convention is retarded...
|
||||
;StrCpy $0 "strawberry.exe"
|
||||
;KillProc::FindProcesses
|
||||
;StrCmp $1 "-1" wooops
|
||||
|
||||
;StrCmp $0 "0" completed
|
||||
|
||||
;DetailPrint "Killing running strawberry.exe..."
|
||||
|
||||
;StrCpy $0 "strawberry.exe"
|
||||
;KillProc::KillProcesses
|
||||
;StrCmp $1 "-1" wooops
|
||||
|
||||
;Sleep 2000
|
||||
;Goto completed
|
||||
|
||||
;wooops:
|
||||
;DetailPrint "-> Error: Something went wrong while killing running strawberry.exe"
|
||||
;Abort
|
||||
|
||||
;completed:
|
||||
|
||||
; Delete all the files
|
||||
|
||||
Delete "$INSTDIR\strawberry.ico"
|
||||
Delete "$INSTDIR\strawberry.exe"
|
||||
Delete "$INSTDIR\strawberry-tagreader.exe"
|
||||
|
||||
Delete "$INSTDIR\libbz2.dll"
|
||||
Delete "$INSTDIR\libcdio-16.dll"
|
||||
Delete "$INSTDIR\libchromaprint.dll"
|
||||
Delete "$INSTDIR\libcrypto-1_1.dll"
|
||||
Delete "$INSTDIR\libfaad-2.dll"
|
||||
Delete "$INSTDIR\libffi-6.dll"
|
||||
Delete "$INSTDIR\libFLAC-8.dll"
|
||||
Delete "$INSTDIR\libfreetype-6.dll"
|
||||
Delete "$INSTDIR\libgcc_s_sjlj-1.dll"
|
||||
Delete "$INSTDIR\libgio-2.0-0.dll"
|
||||
Delete "$INSTDIR\libglib-2.0-0.dll"
|
||||
Delete "$INSTDIR\libgmodule-2.0-0.dll"
|
||||
Delete "$INSTDIR\libgobject-2.0-0.dll"
|
||||
Delete "$INSTDIR\libgstapp-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstaudio-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstbase-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstfft-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstpbutils-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstreamer-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstriff-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstrtp-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstrtsp-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstsdp-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgsttag-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstvideo-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstnet-1.0-0.dll"
|
||||
Delete "$INSTDIR\libharfbuzz-0.dll"
|
||||
Delete "$INSTDIR\libiconv-2.dll"
|
||||
Delete "$INSTDIR\libintl-8.dll"
|
||||
Delete "$INSTDIR\libjpeg-9.dll"
|
||||
Delete "$INSTDIR\liblastfm5.dll"
|
||||
Delete "$INSTDIR\libmp3lame-0.dll"
|
||||
Delete "$INSTDIR\libogg-0.dll"
|
||||
Delete "$INSTDIR\libopus-0.dll"
|
||||
Delete "$INSTDIR\libpcre-1.dll"
|
||||
Delete "$INSTDIR\libpcre2-16-0.dll"
|
||||
Delete "$INSTDIR\libpng16-16.dll"
|
||||
Delete "$INSTDIR\libprotobuf-15.dll"
|
||||
Delete "$INSTDIR\libspeex-1.dll"
|
||||
Delete "$INSTDIR\libsqlite3-0.dll"
|
||||
Delete "$INSTDIR\libssl-1_1.dll"
|
||||
Delete "$INSTDIR\libstdc++-6.dll"
|
||||
Delete "$INSTDIR\libtag.dll"
|
||||
Delete "$INSTDIR\libvorbis-0.dll"
|
||||
Delete "$INSTDIR\libvorbisenc-2.dll"
|
||||
Delete "$INSTDIR\libwavpack-1.dll"
|
||||
Delete "$INSTDIR\libwinpthread-1.dll"
|
||||
Delete "$INSTDIR\Qt5Concurrent.dll"
|
||||
Delete "$INSTDIR\Qt5Core.dll"
|
||||
Delete "$INSTDIR\Qt5Gui.dll"
|
||||
Delete "$INSTDIR\Qt5Network.dll"
|
||||
Delete "$INSTDIR\Qt5Sql.dll"
|
||||
Delete "$INSTDIR\Qt5Widgets.dll"
|
||||
Delete "$INSTDIR\Qt5Xml.dll"
|
||||
Delete "$INSTDIR\Qt5WinExtras.dll"
|
||||
Delete "$INSTDIR\zlib1.dll"
|
||||
Delete "$INSTDIR\libxine-2.dll"
|
||||
Delete "$INSTDIR\libmpcdec-5.dll"
|
||||
Delete "$INSTDIR\libtheora-0.dll"
|
||||
Delete "$INSTDIR\libfftw3-3.dll"
|
||||
Delete "$INSTDIR\libxml2-2.dll"
|
||||
Delete "$INSTDIR\libsoup-2.4-1.dll"
|
||||
Delete "$INSTDIR\liblzma-5.dll"
|
||||
|
||||
Delete "$INSTDIR\platforms\qwindows.dll"
|
||||
Delete "$INSTDIR\sqldrivers\qsqlite.dll"
|
||||
|
||||
Delete "$INSTDIR\imageformats\qgif.dll"
|
||||
Delete "$INSTDIR\imageformats\qico.dll"
|
||||
Delete "$INSTDIR\imageformats\qjpeg.dll"
|
||||
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstapetag.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstapp.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstasf.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstaiff.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstaudioconvert.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstaudiofx.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstaudioparsers.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstaudioresample.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstaudiotestsrc.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstautodetect.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstcoreelements.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstdirectsound.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstequalizer.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstfaad.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstflac.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstgio.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgsticydemux.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstid3demux.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstisomp4.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstlame.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstogg.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstopusparse.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstplayback.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstreplaygain.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstspectrum.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstspeex.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgsttaglib.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgsttypefindfunctions.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstvolume.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstvorbis.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstwavpack.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstwavparse.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstcdio.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgsttcp.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstudp.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstsoup.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstlibav.dll"
|
||||
|
||||
Delete "$INSTDIR\xine-plugins\xineplug_ao_out_directx2.dll"
|
||||
Delete "$INSTDIR\xine-plugins\xineplug_ao_out_directx.dll"
|
||||
Delete "$INSTDIR\xine-plugins\xineplug_decode_dts.dll"
|
||||
Delete "$INSTDIR\xine-plugins\xineplug_decode_dvaudio.dll"
|
||||
Delete "$INSTDIR\xine-plugins\xineplug_decode_faad.dll"
|
||||
Delete "$INSTDIR\xine-plugins\xineplug_decode_gsm610.dll"
|
||||
Delete "$INSTDIR\xine-plugins\xineplug_decode_lpcm.dll"
|
||||
Delete "$INSTDIR\xine-plugins\xineplug_decode_mad.dll"
|
||||
Delete "$INSTDIR\xine-plugins\xineplug_decode_mpc.dll"
|
||||
Delete "$INSTDIR\xine-plugins\xineplug_decode_mpeg2.dll"
|
||||
Delete "$INSTDIR\xine-plugins\xineplug_dmx_asf.dll"
|
||||
Delete "$INSTDIR\xine-plugins\xineplug_dmx_audio.dll"
|
||||
Delete "$INSTDIR\xine-plugins\xineplug_dmx_playlist.dll"
|
||||
Delete "$INSTDIR\xine-plugins\xineplug_dmx_slave.dll"
|
||||
Delete "$INSTDIR\xine-plugins\xineplug_flac.dll"
|
||||
Delete "$INSTDIR\xine-plugins\xineplug_wavpack.dll"
|
||||
Delete "$INSTDIR\xine-plugins\xineplug_xiph.dll"
|
||||
Delete "$INSTDIR\xine-plugins\xineplug_inp_cdda.dll"
|
||||
|
||||
Delete "$INSTDIR\xine-plugins\xineplug_post_audio_filters.dll"
|
||||
Delete "$INSTDIR\xine-plugins\xineplug_post_goom.dll"
|
||||
Delete "$INSTDIR\xine-plugins\xineplug_post_mosaico.dll"
|
||||
Delete "$INSTDIR\xine-plugins\xineplug_post_planar.dll"
|
||||
Delete "$INSTDIR\xine-plugins\xineplug_post_switch.dll"
|
||||
Delete "$INSTDIR\xine-plugins\xineplug_post_tvtime.dll"
|
||||
Delete "$INSTDIR\xine-plugins\xineplug_post_visualizations.dll"
|
||||
|
||||
Delete "$INSTDIR\Uninstall.exe"
|
||||
|
||||
; Remove the installation folders.
|
||||
RMDir "$INSTDIR\platforms"
|
||||
RMDir "$INSTDIR\sqldrivers"
|
||||
RMDir "$INSTDIR\imageformats"
|
||||
RMDir "$INSTDIR\gstreamer-plugins"
|
||||
RMDir "$INSTDIR\xine-plugins"
|
||||
RMDir "$INSTDIR"
|
||||
|
||||
; Remove the Shortcuts
|
||||
SetShellVarContext all
|
||||
|
||||
Delete "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk"
|
||||
Delete "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk"
|
||||
RMDir /r "$SMPROGRAMS\${PRODUCT_NAME}"
|
||||
|
||||
; Remove the entry from 'installed programs list'
|
||||
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
|
||||
|
||||
; Unregister from Default Programs
|
||||
${UnRegisterCapabilities}
|
||||
|
||||
SectionEnd
|
||||
@@ -1,10 +1,10 @@
|
||||
!define PRODUCT_NAME "Strawberry"
|
||||
!define PRODUCT_PUBLISHER "Strawberry"
|
||||
!define PRODUCT_VERSION_MAJOR 0
|
||||
!define PRODUCT_VERSION_MINOR 2
|
||||
!define PRODUCT_VERSION_PATCH 1
|
||||
!define PRODUCT_DISPLAY_VERSION "0.2.1"
|
||||
!define PRODUCT_DISPLAY_VERSION_SHORT "0.2.1"
|
||||
!define PRODUCT_VERSION_MAJOR @STRAWBERRY_VERSION_MAJOR@
|
||||
!define PRODUCT_VERSION_MINOR @STRAWBERRY_VERSION_MINOR@
|
||||
!define PRODUCT_VERSION_PATCH @STRAWBERRY_VERSION_PATCH@
|
||||
!define PRODUCT_DISPLAY_VERSION "@STRAWBERRY_VERSION_PACKAGE@"
|
||||
!define PRODUCT_DISPLAY_VERSION_SHORT "@STRAWBERRY_VERSION_PACKAGE@"
|
||||
!define PRODUCT_WEB_SITE "http://www.strawbs.org/"
|
||||
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
|
||||
!define PRODUCT_UNINST_ROOT_KEY "HKLM"
|
||||
@@ -48,7 +48,7 @@ SetCompressor /SOLID lzma
|
||||
!insertmacro MUI_LANGUAGE "English" ;first language is the default language
|
||||
|
||||
Name "${PRODUCT_NAME}"
|
||||
OutFile "${PRODUCT_NAME}Setup-0.2.1.exe"
|
||||
OutFile "${PRODUCT_NAME}Setup-${PRODUCT_DISPLAY_VERSION}-Debug.exe"
|
||||
InstallDir "${PRODUCT_INSTALL_DIR}"
|
||||
|
||||
; Get the path where Strawberry was installed previously and set it as default path
|
||||
@@ -87,50 +87,6 @@ Function .onInit
|
||||
|
||||
FunctionEnd
|
||||
|
||||
;!define LVM_GETITEMCOUNT 0x1004
|
||||
!define LVM_GETITEMTEXT 0x102D
|
||||
|
||||
Function DumpLog
|
||||
Exch $5
|
||||
Push $0
|
||||
Push $1
|
||||
Push $2
|
||||
Push $3
|
||||
Push $4
|
||||
Push $6
|
||||
|
||||
FindWindow $0 "#32770" "" $HWNDPARENT
|
||||
GetDlgItem $0 $0 1016
|
||||
StrCmp $0 0 exit
|
||||
FileOpen $5 $5 "w"
|
||||
StrCmp $5 "" exit
|
||||
SendMessage $0 ${LVM_GETITEMCOUNT} 0 0 $6
|
||||
System::Alloc ${NSIS_MAX_STRLEN}
|
||||
Pop $3
|
||||
StrCpy $2 0
|
||||
System::Call "*(i, i, i, i, i, i, i, i, i) i \
|
||||
(0, 0, 0, 0, 0, r3, ${NSIS_MAX_STRLEN}) .r1"
|
||||
loop: StrCmp $2 $6 done
|
||||
System::Call "User32::SendMessageA(i, i, i, i) i \
|
||||
($0, ${LVM_GETITEMTEXT}, $2, r1)"
|
||||
System::Call "*$3(&t${NSIS_MAX_STRLEN} .r4)"
|
||||
FileWrite $5 "$4$\r$\n"
|
||||
IntOp $2 $2 + 1
|
||||
Goto loop
|
||||
done:
|
||||
FileClose $5
|
||||
System::Free $1
|
||||
System::Free $3
|
||||
exit:
|
||||
Pop $6
|
||||
Pop $4
|
||||
Pop $3
|
||||
Pop $2
|
||||
Pop $1
|
||||
Pop $0
|
||||
Exch $5
|
||||
FunctionEnd
|
||||
|
||||
;Function RunStrawberry
|
||||
;ShellExecAsUser::ShellExecAsUser "" "$INSTDIR/strawberry.exe" ""
|
||||
;FunctionEnd
|
||||
@@ -170,6 +126,7 @@ Section "Strawberry" Strawberry
|
||||
File "libgstsdp-1.0-0.dll"
|
||||
File "libgsttag-1.0-0.dll"
|
||||
File "libgstvideo-1.0-0.dll"
|
||||
File "libgstnet-1.0-0.dll"
|
||||
File "libharfbuzz-0.dll"
|
||||
File "libiconv-2.dll"
|
||||
File "libintl-8.dll"
|
||||
@@ -198,11 +155,15 @@ Section "Strawberry" Strawberry
|
||||
File "Qt5Sql.dll"
|
||||
File "Qt5Widgets.dll"
|
||||
File "Qt5Xml.dll"
|
||||
File "Qt5WinExtras.dll"
|
||||
File "zlib1.dll"
|
||||
File "libxine-2.dll"
|
||||
File "libmpcdec-5.dll"
|
||||
File "libtheora-0.dll"
|
||||
File "libfftw3-3.dll"
|
||||
File "libxml2-2.dll"
|
||||
File "libsoup-2.4-1.dll"
|
||||
File "liblzma-5.dll"
|
||||
|
||||
; Register Strawberry with Default Programs
|
||||
Var /GLOBAL AppIcon
|
||||
@@ -233,31 +194,17 @@ Section "Strawberry" Strawberry
|
||||
|
||||
${RegisterMimeType} "audio/mpegurl" "m3u" "{cd3afa78-b84f-48f0-9393-7edc34128127}"
|
||||
${RegisterMimeType} "application/x-wmplayer" "asx" "{cd3afa96-b84f-48f0-9393-7edc34128127}"
|
||||
|
||||
StrCpy $0 "$EXEDIR\install.log"
|
||||
Push $0
|
||||
Call DumpLog
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "Qt Platforms" platforms
|
||||
SetOutPath "$INSTDIR\platforms"
|
||||
File "/oname=qwindows.dll" "platforms\qwindows.dll"
|
||||
|
||||
StrCpy $0 "$EXEDIR\install.log"
|
||||
Push $0
|
||||
Call DumpLog
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "Qt SQL Drivers" sqldrivers
|
||||
SetOutPath "$INSTDIR\sqldrivers"
|
||||
File "/oname=qsqlite.dll" "sqldrivers\qsqlite.dll"
|
||||
|
||||
StrCpy $0 "$EXEDIR\install.log"
|
||||
Push $0
|
||||
Call DumpLog
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "Qt image format plugins" imageformats
|
||||
@@ -265,11 +212,6 @@ Section "Qt image format plugins" imageformats
|
||||
File "/oname=qgif.dll" "imageformats\qgif.dll"
|
||||
File "/oname=qico.dll" "imageformats\qico.dll"
|
||||
File "/oname=qjpeg.dll" "imageformats\qjpeg.dll"
|
||||
|
||||
StrCpy $0 "$EXEDIR\install.log"
|
||||
Push $0
|
||||
Call DumpLog
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "Gstreamer plugins" gstreamer-plugins
|
||||
@@ -308,10 +250,10 @@ Section "Gstreamer plugins" gstreamer-plugins
|
||||
File "/oname=libgstwavpack.dll" "gstreamer-plugins\libgstwavpack.dll"
|
||||
File "/oname=libgstwavparse.dll" "gstreamer-plugins\libgstwavparse.dll"
|
||||
File "/oname=libgstcdio.dll" "gstreamer-plugins\libgstcdio.dll"
|
||||
|
||||
StrCpy $0 "$EXEDIR\install.log"
|
||||
Push $0
|
||||
Call DumpLog
|
||||
File "/oname=libgsttcp.dll" "gstreamer-plugins\libgsttcp.dll"
|
||||
File "/oname=libgstudp.dll" "gstreamer-plugins\libgstudp.dll"
|
||||
File "/oname=libgstsoup.dll" "gstreamer-plugins\libgstsoup.dll"
|
||||
File "/oname=libgstlibav.dll" "gstreamer-plugins\libgstlibav.dll"
|
||||
|
||||
SectionEnd
|
||||
|
||||
@@ -344,10 +286,6 @@ Section "Xine plugins" xine-plugins
|
||||
File "/oname=xineplug_post_tvtime.dll" "xine-plugins\xineplug_post_tvtime.dll"
|
||||
File "/oname=xineplug_post_visualizations.dll" "xine-plugins\xineplug_post_visualizations.dll"
|
||||
|
||||
StrCpy $0 "$EXEDIR\install.log"
|
||||
Push $0
|
||||
Call DumpLog
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "Start menu items" startmenu
|
||||
@@ -357,10 +295,6 @@ Section "Start menu items" startmenu
|
||||
CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}"
|
||||
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk" "$INSTDIR\strawberry.exe"
|
||||
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
|
||||
|
||||
StrCpy $0 "$EXEDIR\install.log"
|
||||
Push $0
|
||||
Call DumpLog
|
||||
|
||||
SectionEnd
|
||||
|
||||
@@ -377,10 +311,6 @@ Section "Uninstaller"
|
||||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
|
||||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
|
||||
|
||||
StrCpy $0 "$EXEDIR\install.log"
|
||||
Push $0
|
||||
Call DumpLog
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "Uninstall"
|
||||
@@ -409,8 +339,6 @@ Section "Uninstall"
|
||||
|
||||
; Delete all the files
|
||||
|
||||
;Delete "$EXEDIR\install.log"
|
||||
|
||||
Delete "$INSTDIR\strawberry.ico"
|
||||
Delete "$INSTDIR\strawberry.exe"
|
||||
Delete "$INSTDIR\strawberry-tagreader.exe"
|
||||
@@ -440,6 +368,7 @@ Section "Uninstall"
|
||||
Delete "$INSTDIR\libgstsdp-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgsttag-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstvideo-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstnet-1.0-0.dll"
|
||||
Delete "$INSTDIR\libharfbuzz-0.dll"
|
||||
Delete "$INSTDIR\libiconv-2.dll"
|
||||
Delete "$INSTDIR\libintl-8.dll"
|
||||
@@ -468,11 +397,15 @@ Section "Uninstall"
|
||||
Delete "$INSTDIR\Qt5Sql.dll"
|
||||
Delete "$INSTDIR\Qt5Widgets.dll"
|
||||
Delete "$INSTDIR\Qt5Xml.dll"
|
||||
Delete "$INSTDIR\Qt5WinExtras.dll"
|
||||
Delete "$INSTDIR\zlib1.dll"
|
||||
Delete "$INSTDIR\libxine-2.dll"
|
||||
Delete "$INSTDIR\libmpcdec-5.dll"
|
||||
Delete "$INSTDIR\libtheora-0.dll"
|
||||
Delete "$INSTDIR\libfftw3-3.dll"
|
||||
Delete "$INSTDIR\libxml2-2.dll"
|
||||
Delete "$INSTDIR\libsoup-2.4-1.dll"
|
||||
Delete "$INSTDIR\liblzma-5.dll"
|
||||
|
||||
Delete "$INSTDIR\platforms\qwindows.dll"
|
||||
Delete "$INSTDIR\sqldrivers\qsqlite.dll"
|
||||
@@ -514,6 +447,10 @@ Section "Uninstall"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstwavpack.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstwavparse.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstcdio.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgsttcp.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstudp.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstsoup.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstlibav.dll"
|
||||
|
||||
Delete "$INSTDIR\xine-plugins\xineplug_ao_out_directx2.dll"
|
||||
Delete "$INSTDIR\xine-plugins\xineplug_ao_out_directx.dll"
|
||||
445
dist/windows/strawberry.nsi.in
vendored
Normal file
@@ -0,0 +1,445 @@
|
||||
!define PRODUCT_NAME "Strawberry"
|
||||
!define PRODUCT_PUBLISHER "Strawberry"
|
||||
!define PRODUCT_VERSION_MAJOR @STRAWBERRY_VERSION_MAJOR@
|
||||
!define PRODUCT_VERSION_MINOR @STRAWBERRY_VERSION_MINOR@
|
||||
!define PRODUCT_VERSION_PATCH @STRAWBERRY_VERSION_PATCH@
|
||||
!define PRODUCT_DISPLAY_VERSION "@STRAWBERRY_VERSION_PACKAGE@"
|
||||
!define PRODUCT_DISPLAY_VERSION_SHORT "@STRAWBERRY_VERSION_PACKAGE@"
|
||||
!define PRODUCT_WEB_SITE "http://www.strawbs.org/"
|
||||
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
|
||||
!define PRODUCT_UNINST_ROOT_KEY "HKLM"
|
||||
!define PRODUCT_INSTALL_DIR "$PROGRAMFILES\Strawberry Music Player"
|
||||
|
||||
; Set Application Capabilities info
|
||||
!define CAPABILITIES_NAME "Strawberry Music Player"
|
||||
!define CAPABILITIES_LOCAL_NAME "Strawberry"
|
||||
!define CAPABILITIES_PROGID "Strawberry Music Player"
|
||||
!define CAPABILITIES_PATH "Software\Clients\Media\Strawberry"
|
||||
!define CAPABILITIES_DESCRIPTION "Strawberry Music Player"
|
||||
!define CAPABILITIES_ICON "$INSTDIR\strawberry.ico"
|
||||
!define CAPABILITIES_REINSTALL "Command to reinstall"
|
||||
!define CAPABILITIES_HIDE_ICONS "Command to hide icons"
|
||||
!define CAPABILITIES_SHOW_ICONS "Command to show icons"
|
||||
|
||||
SetCompressor /SOLID lzma
|
||||
!addplugindir nsisplugins
|
||||
!include "MUI2.nsh"
|
||||
!include "FileAssociation.nsh"
|
||||
!include "Capabilities.nsh"
|
||||
|
||||
!define MUI_ICON "strawberry.ico"
|
||||
|
||||
!define MUI_COMPONENTSPAGE_SMALLDESC
|
||||
;!define MUI_FINISHPAGE_RUN
|
||||
;!define MUI_FINISHPAGE_RUN_TEXT "Run Strawberry"
|
||||
;!define MUI_FINISHPAGE_RUN_FUNCTION "RunStrawberry"
|
||||
|
||||
; Installer pages
|
||||
!insertmacro MUI_PAGE_WELCOME
|
||||
!insertmacro MUI_PAGE_DIRECTORY
|
||||
!insertmacro MUI_PAGE_INSTFILES
|
||||
!insertmacro MUI_PAGE_FINISH
|
||||
|
||||
; Uninstaller pages
|
||||
!insertmacro MUI_UNPAGE_CONFIRM
|
||||
!insertmacro MUI_UNPAGE_INSTFILES
|
||||
!insertmacro MUI_UNPAGE_FINISH
|
||||
|
||||
!insertmacro MUI_LANGUAGE "English" ;first language is the default language
|
||||
|
||||
Name "${PRODUCT_NAME}"
|
||||
OutFile "${PRODUCT_NAME}Setup-${PRODUCT_DISPLAY_VERSION}-Release.exe"
|
||||
InstallDir "${PRODUCT_INSTALL_DIR}"
|
||||
|
||||
; Get the path where Strawberry was installed previously and set it as default path
|
||||
InstallDirRegKey ${PRODUCT_UNINST_ROOT_KEY} ${PRODUCT_UNINST_KEY} "UninstallString"
|
||||
|
||||
ShowInstDetails show
|
||||
ShowUnInstDetails show
|
||||
RequestExecutionLevel admin
|
||||
;RequestExecutionLevel user
|
||||
|
||||
; Check for previous installation, and call the uninstaller if any
|
||||
Function CheckPreviousInstall
|
||||
|
||||
ReadRegStr $R0 ${PRODUCT_UNINST_ROOT_KEY} ${PRODUCT_UNINST_KEY} "UninstallString"
|
||||
StrCmp $R0 "" done
|
||||
|
||||
MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION \
|
||||
"${PRODUCT_NAME} is already installed. $\n$\nClick `OK` to remove the \
|
||||
previous version or `Cancel` to cancel this upgrade." \
|
||||
IDOK uninst
|
||||
Abort
|
||||
; Run the uninstaller
|
||||
uninst:
|
||||
ClearErrors
|
||||
ExecWait '$R0' ; Do not copy the uninstaller to a temp file
|
||||
|
||||
done:
|
||||
|
||||
FunctionEnd
|
||||
|
||||
Function .onInit
|
||||
|
||||
!insertmacro MUI_LANGDLL_DISPLAY
|
||||
|
||||
Call CheckPreviousInstall
|
||||
|
||||
FunctionEnd
|
||||
|
||||
;Function RunStrawberry
|
||||
;ShellExecAsUser::ShellExecAsUser "" "$INSTDIR/strawberry.exe" ""
|
||||
;FunctionEnd
|
||||
|
||||
Section "Delete old files" oldfiles
|
||||
SectionEnd
|
||||
|
||||
Section "Strawberry" Strawberry
|
||||
SetOutPath "$INSTDIR"
|
||||
|
||||
File "strawberry.exe"
|
||||
File "strawberry-tagreader.exe"
|
||||
File "strawberry.ico"
|
||||
|
||||
File "libbz2.dll"
|
||||
File "libcdio-16.dll"
|
||||
File "libchromaprint.dll"
|
||||
File "libcrypto-1_1.dll"
|
||||
File "libfaad-2.dll"
|
||||
File "libffi-6.dll"
|
||||
File "libFLAC-8.dll"
|
||||
File "libfreetype-6.dll"
|
||||
File "libgcc_s_sjlj-1.dll"
|
||||
File "libgio-2.0-0.dll"
|
||||
File "libglib-2.0-0.dll"
|
||||
File "libgmodule-2.0-0.dll"
|
||||
File "libgobject-2.0-0.dll"
|
||||
File "libgstapp-1.0-0.dll"
|
||||
File "libgstaudio-1.0-0.dll"
|
||||
File "libgstbase-1.0-0.dll"
|
||||
File "libgstfft-1.0-0.dll"
|
||||
File "libgstpbutils-1.0-0.dll"
|
||||
File "libgstreamer-1.0-0.dll"
|
||||
File "libgstriff-1.0-0.dll"
|
||||
File "libgstrtp-1.0-0.dll"
|
||||
File "libgstrtsp-1.0-0.dll"
|
||||
File "libgstsdp-1.0-0.dll"
|
||||
File "libgsttag-1.0-0.dll"
|
||||
File "libgstvideo-1.0-0.dll"
|
||||
File "libgstnet-1.0-0.dll"
|
||||
File "libharfbuzz-0.dll"
|
||||
File "libiconv-2.dll"
|
||||
File "libintl-8.dll"
|
||||
File "libjpeg-9.dll"
|
||||
File "liblastfm5.dll"
|
||||
File "libmp3lame-0.dll"
|
||||
File "libogg-0.dll"
|
||||
File "libopus-0.dll"
|
||||
File "libpcre-1.dll"
|
||||
File "libpcre2-16-0.dll"
|
||||
File "libpng16-16.dll"
|
||||
File "libprotobuf-15.dll"
|
||||
File "libspeex-1.dll"
|
||||
File "libsqlite3-0.dll"
|
||||
File "libssl-1_1.dll"
|
||||
File "libstdc++-6.dll"
|
||||
File "libtag.dll"
|
||||
File "libvorbis-0.dll"
|
||||
File "libvorbisenc-2.dll"
|
||||
File "libwavpack-1.dll"
|
||||
File "libwinpthread-1.dll"
|
||||
File "Qt5Concurrent.dll"
|
||||
File "Qt5Core.dll"
|
||||
File "Qt5Gui.dll"
|
||||
File "Qt5Network.dll"
|
||||
File "Qt5Sql.dll"
|
||||
File "Qt5Widgets.dll"
|
||||
File "Qt5Xml.dll"
|
||||
File "Qt5WinExtras.dll"
|
||||
File "zlib1.dll"
|
||||
;File "libmpcdec-5.dll"
|
||||
;File "libtheora-0.dll"
|
||||
File "libfftw3-3.dll"
|
||||
File "libxml2-2.dll"
|
||||
File "libsoup-2.4-1.dll"
|
||||
File "liblzma-5.dll"
|
||||
|
||||
; Register Strawberry with Default Programs
|
||||
Var /GLOBAL AppIcon
|
||||
Var /GLOBAL AppExe
|
||||
StrCpy $AppExe "$INSTDIR\strawberry.exe"
|
||||
StrCpy $AppIcon "$INSTDIR\strawberry.ico"
|
||||
|
||||
${RegisterCapabilities}
|
||||
|
||||
${RegisterMediaType} ".mp3" $AppExe $AppIcon "MP3 Audio File"
|
||||
${RegisterMediaType} ".flac" $AppExe $AppIcon "FLAC Audio File"
|
||||
${RegisterMediaType} ".ogg" $AppExe $AppIcon "OGG Audio File"
|
||||
${RegisterMediaType} ".spx" $AppExe $AppIcon "OGG Speex Audio File"
|
||||
${RegisterMediaType} ".m4a" $AppExe $AppIcon "MP4 Audio File"
|
||||
${RegisterMediaType} ".aac" $AppExe $AppIcon "AAC Audio File"
|
||||
${RegisterMediaType} ".wma" $AppExe $AppIcon "WMA Audio File"
|
||||
${RegisterMediaType} ".wav" $AppExe $AppIcon "WAV Audio File"
|
||||
|
||||
${RegisterMediaType} ".pls" $AppExe $AppIcon "PLS Audio File"
|
||||
${RegisterMediaType} ".m3u" $AppExe $AppIcon "M3U Audio File"
|
||||
${RegisterMediaType} ".xspf" $AppExe $AppIcon "XSPF Audio File"
|
||||
${RegisterMediaType} ".asx" $AppExe $AppIcon "Windows Media Audio/Video playlist"
|
||||
|
||||
${RegisterMimeType} "audio/mp3" "mp3" "{cd3afa76-b84f-48f0-9393-7edc34128127}"
|
||||
${RegisterMimeType} "audio/mp4" "m4a" "{cd3afa7c-b84f-48f0-9393-7edc34128127}"
|
||||
${RegisterMimeType} "audio/x-ms-wma" "wma" "{cd3afa84-b84f-48f0-9393-7edc34128127}"
|
||||
${RegisterMimeType} "audio/wav" "wav" "{cd3afa7b-b84f-48f0-9393-7edc34128127}"
|
||||
|
||||
${RegisterMimeType} "audio/mpegurl" "m3u" "{cd3afa78-b84f-48f0-9393-7edc34128127}"
|
||||
${RegisterMimeType} "application/x-wmplayer" "asx" "{cd3afa96-b84f-48f0-9393-7edc34128127}"
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "Qt Platforms" platforms
|
||||
SetOutPath "$INSTDIR\platforms"
|
||||
File "/oname=qwindows.dll" "platforms\qwindows.dll"
|
||||
SectionEnd
|
||||
|
||||
Section "Qt SQL Drivers" sqldrivers
|
||||
SetOutPath "$INSTDIR\sqldrivers"
|
||||
File "/oname=qsqlite.dll" "sqldrivers\qsqlite.dll"
|
||||
SectionEnd
|
||||
|
||||
Section "Qt image format plugins" imageformats
|
||||
SetOutPath "$INSTDIR\imageformats"
|
||||
File "/oname=qgif.dll" "imageformats\qgif.dll"
|
||||
File "/oname=qico.dll" "imageformats\qico.dll"
|
||||
File "/oname=qjpeg.dll" "imageformats\qjpeg.dll"
|
||||
SectionEnd
|
||||
|
||||
Section "Gstreamer plugins" gstreamer-plugins
|
||||
SetOutPath "$INSTDIR\gstreamer-plugins"
|
||||
|
||||
File "/oname=libgstapetag.dll" "gstreamer-plugins\libgstapetag.dll"
|
||||
File "/oname=libgstapp.dll" "gstreamer-plugins\libgstapp.dll"
|
||||
File "/oname=libgstasf.dll" "gstreamer-plugins\libgstasf.dll"
|
||||
File "/oname=libgstaiff.dll" "gstreamer-plugins\libgstaiff.dll"
|
||||
File "/oname=libgstaudioconvert.dll" "gstreamer-plugins\libgstaudioconvert.dll"
|
||||
File "/oname=libgstaudiofx.dll" "gstreamer-plugins\libgstaudiofx.dll"
|
||||
File "/oname=libgstaudioparsers.dll" "gstreamer-plugins\libgstaudioparsers.dll"
|
||||
File "/oname=libgstaudioresample.dll" "gstreamer-plugins\libgstaudioresample.dll"
|
||||
File "/oname=libgstaudiotestsrc.dll" "gstreamer-plugins\libgstaudiotestsrc.dll"
|
||||
File "/oname=libgstautodetect.dll" "gstreamer-plugins\libgstautodetect.dll"
|
||||
File "/oname=libgstcoreelements.dll" "gstreamer-plugins\libgstcoreelements.dll"
|
||||
File "/oname=libgstdirectsound.dll" "gstreamer-plugins\libgstdirectsound.dll"
|
||||
File "/oname=libgstequalizer.dll" "gstreamer-plugins\libgstequalizer.dll"
|
||||
File "/oname=libgstfaad.dll" "gstreamer-plugins\libgstfaad.dll"
|
||||
File "/oname=libgstflac.dll" "gstreamer-plugins\libgstflac.dll"
|
||||
File "/oname=libgstgio.dll" "gstreamer-plugins\libgstgio.dll"
|
||||
File "/oname=libgsticydemux.dll" "gstreamer-plugins\libgsticydemux.dll"
|
||||
File "/oname=libgstid3demux.dll" "gstreamer-plugins\libgstid3demux.dll"
|
||||
File "/oname=libgstisomp4.dll" "gstreamer-plugins\libgstisomp4.dll"
|
||||
File "/oname=libgstlame.dll" "gstreamer-plugins\libgstlame.dll"
|
||||
File "/oname=libgstogg.dll" "gstreamer-plugins\libgstogg.dll"
|
||||
File "/oname=libgstopusparse.dll" "gstreamer-plugins\libgstopusparse.dll"
|
||||
File "/oname=libgstplayback.dll" "gstreamer-plugins\libgstplayback.dll"
|
||||
File "/oname=libgstreplaygain.dll" "gstreamer-plugins\libgstreplaygain.dll"
|
||||
File "/oname=libgstspectrum.dll" "gstreamer-plugins\libgstspectrum.dll"
|
||||
File "/oname=libgstspeex.dll" "gstreamer-plugins\libgstspeex.dll"
|
||||
File "/oname=libgsttaglib.dll" "gstreamer-plugins\libgsttaglib.dll"
|
||||
File "/oname=libgsttypefindfunctions.dll" "gstreamer-plugins\libgsttypefindfunctions.dll"
|
||||
File "/oname=libgstvolume.dll" "gstreamer-plugins\libgstvolume.dll"
|
||||
File "/oname=libgstvorbis.dll" "gstreamer-plugins\libgstvorbis.dll"
|
||||
File "/oname=libgstwavpack.dll" "gstreamer-plugins\libgstwavpack.dll"
|
||||
File "/oname=libgstwavparse.dll" "gstreamer-plugins\libgstwavparse.dll"
|
||||
File "/oname=libgstcdio.dll" "gstreamer-plugins\libgstcdio.dll"
|
||||
File "/oname=libgsttcp.dll" "gstreamer-plugins\libgsttcp.dll"
|
||||
File "/oname=libgstudp.dll" "gstreamer-plugins\libgstudp.dll"
|
||||
File "/oname=libgstsoup.dll" "gstreamer-plugins\libgstsoup.dll"
|
||||
File "/oname=libgstlibav.dll" "gstreamer-plugins\libgstlibav.dll"
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "Start menu items" startmenu
|
||||
; Create Start Menu folders and shortcuts.
|
||||
SetShellVarContext all
|
||||
|
||||
CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}"
|
||||
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk" "$INSTDIR\strawberry.exe"
|
||||
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "Uninstaller"
|
||||
; Create uninstaller
|
||||
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
||||
|
||||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "${PRODUCT_NAME}"
|
||||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\Uninstall.exe"
|
||||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\strawberry.ico"
|
||||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_DISPLAY_VERSION}"
|
||||
WriteRegDWORD ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "VersionMajor" "${PRODUCT_VERSION_MAJOR}"
|
||||
WriteRegDWORD ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "VersionMinor" "${PRODUCT_VERSION_MINOR}"
|
||||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
|
||||
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "Uninstall"
|
||||
; Kill strawberry.exe if it's running
|
||||
; This calling convention is retarded...
|
||||
;StrCpy $0 "strawberry.exe"
|
||||
;KillProc::FindProcesses
|
||||
;StrCmp $1 "-1" wooops
|
||||
|
||||
;StrCmp $0 "0" completed
|
||||
|
||||
;DetailPrint "Killing running strawberry.exe..."
|
||||
|
||||
;StrCpy $0 "strawberry.exe"
|
||||
;KillProc::KillProcesses
|
||||
;StrCmp $1 "-1" wooops
|
||||
|
||||
;Sleep 2000
|
||||
;Goto completed
|
||||
|
||||
;wooops:
|
||||
;DetailPrint "-> Error: Something went wrong while killing running strawberry.exe"
|
||||
;Abort
|
||||
|
||||
;completed:
|
||||
|
||||
; Delete all the files
|
||||
|
||||
Delete "$INSTDIR\strawberry.ico"
|
||||
Delete "$INSTDIR\strawberry.exe"
|
||||
Delete "$INSTDIR\strawberry-tagreader.exe"
|
||||
|
||||
Delete "$INSTDIR\libbz2.dll"
|
||||
Delete "$INSTDIR\libcdio-16.dll"
|
||||
Delete "$INSTDIR\libchromaprint.dll"
|
||||
Delete "$INSTDIR\libcrypto-1_1.dll"
|
||||
Delete "$INSTDIR\libfaad-2.dll"
|
||||
Delete "$INSTDIR\libffi-6.dll"
|
||||
Delete "$INSTDIR\libFLAC-8.dll"
|
||||
Delete "$INSTDIR\libfreetype-6.dll"
|
||||
Delete "$INSTDIR\libgcc_s_sjlj-1.dll"
|
||||
Delete "$INSTDIR\libgio-2.0-0.dll"
|
||||
Delete "$INSTDIR\libglib-2.0-0.dll"
|
||||
Delete "$INSTDIR\libgmodule-2.0-0.dll"
|
||||
Delete "$INSTDIR\libgobject-2.0-0.dll"
|
||||
Delete "$INSTDIR\libgstapp-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstaudio-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstbase-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstfft-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstpbutils-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstreamer-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstriff-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstrtp-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstrtsp-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstsdp-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgsttag-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstvideo-1.0-0.dll"
|
||||
Delete "$INSTDIR\libgstnet-1.0-0.dll"
|
||||
Delete "$INSTDIR\libharfbuzz-0.dll"
|
||||
Delete "$INSTDIR\libiconv-2.dll"
|
||||
Delete "$INSTDIR\libintl-8.dll"
|
||||
Delete "$INSTDIR\libjpeg-9.dll"
|
||||
Delete "$INSTDIR\liblastfm5.dll"
|
||||
Delete "$INSTDIR\libmp3lame-0.dll"
|
||||
Delete "$INSTDIR\libogg-0.dll"
|
||||
Delete "$INSTDIR\libopus-0.dll"
|
||||
Delete "$INSTDIR\libpcre-1.dll"
|
||||
Delete "$INSTDIR\libpcre2-16-0.dll"
|
||||
Delete "$INSTDIR\libpng16-16.dll"
|
||||
Delete "$INSTDIR\libprotobuf-15.dll"
|
||||
Delete "$INSTDIR\libspeex-1.dll"
|
||||
Delete "$INSTDIR\libsqlite3-0.dll"
|
||||
Delete "$INSTDIR\libssl-1_1.dll"
|
||||
Delete "$INSTDIR\libstdc++-6.dll"
|
||||
Delete "$INSTDIR\libtag.dll"
|
||||
Delete "$INSTDIR\libvorbis-0.dll"
|
||||
Delete "$INSTDIR\libvorbisenc-2.dll"
|
||||
Delete "$INSTDIR\libwavpack-1.dll"
|
||||
Delete "$INSTDIR\libwinpthread-1.dll"
|
||||
Delete "$INSTDIR\Qt5Concurrent.dll"
|
||||
Delete "$INSTDIR\Qt5Core.dll"
|
||||
Delete "$INSTDIR\Qt5Gui.dll"
|
||||
Delete "$INSTDIR\Qt5Network.dll"
|
||||
Delete "$INSTDIR\Qt5Sql.dll"
|
||||
Delete "$INSTDIR\Qt5Widgets.dll"
|
||||
Delete "$INSTDIR\Qt5Xml.dll"
|
||||
Delete "$INSTDIR\Qt5WinExtras.dll"
|
||||
Delete "$INSTDIR\zlib1.dll"
|
||||
;Delete "$INSTDIR\libmpcdec-5.dll"
|
||||
;Delete "$INSTDIR\libtheora-0.dll"
|
||||
Delete "$INSTDIR\libfftw3-3.dll"
|
||||
Delete "$INSTDIR\libxml2-2.dll"
|
||||
Delete "$INSTDIR\libsoup-2.4-1.dll"
|
||||
Delete "$INSTDIR\liblzma-5.dll"
|
||||
|
||||
Delete "$INSTDIR\platforms\qwindows.dll"
|
||||
Delete "$INSTDIR\sqldrivers\qsqlite.dll"
|
||||
|
||||
Delete "$INSTDIR\imageformats\qgif.dll"
|
||||
Delete "$INSTDIR\imageformats\qico.dll"
|
||||
Delete "$INSTDIR\imageformats\qjpeg.dll"
|
||||
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstapetag.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstapp.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstasf.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstaiff.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstaudioconvert.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstaudiofx.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstaudioparsers.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstaudioresample.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstaudiotestsrc.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstautodetect.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstcoreelements.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstdirectsound.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstequalizer.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstfaad.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstflac.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstgio.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgsticydemux.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstid3demux.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstisomp4.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstlame.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstogg.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstopusparse.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstplayback.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstreplaygain.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstspectrum.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstspeex.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgsttaglib.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgsttypefindfunctions.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstvolume.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstvorbis.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstwavpack.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstwavparse.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstcdio.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgsttcp.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstudp.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstsoup.dll"
|
||||
Delete "$INSTDIR\gstreamer-plugins\libgstlibav.dll"
|
||||
|
||||
Delete "$INSTDIR\Uninstall.exe"
|
||||
|
||||
; Remove the installation folders.
|
||||
RMDir "$INSTDIR\platforms"
|
||||
RMDir "$INSTDIR\sqldrivers"
|
||||
RMDir "$INSTDIR\imageformats"
|
||||
RMDir "$INSTDIR\gstreamer-plugins"
|
||||
RMDir "$INSTDIR\xine-plugins"
|
||||
RMDir "$INSTDIR"
|
||||
|
||||
; Remove the Shortcuts
|
||||
SetShellVarContext all
|
||||
|
||||
Delete "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk"
|
||||
Delete "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk"
|
||||
RMDir /r "$SMPROGRAMS\${PRODUCT_NAME}"
|
||||
|
||||
; Remove the entry from 'installed programs list'
|
||||
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
|
||||
|
||||
; Unregister from Default Programs
|
||||
${UnRegisterCapabilities}
|
||||
|
||||
SectionEnd
|
||||
3
dist/windows/windres.rc.in
vendored
@@ -11,7 +11,6 @@ BEGIN
|
||||
VALUE "FileDescription", "Strawberry Music Player"
|
||||
VALUE "FileVersion", "${STRAWBERRY_VERSION_DISPLAY}"
|
||||
VALUE "InternalName", "strawberry"
|
||||
VALUE "LegalCopyright", "David Sansome / Jonas Kvinge"
|
||||
VALUE "OriginalFilename", "strawberry.exe"
|
||||
VALUE "ProductName", "Strawberry"
|
||||
VALUE "ProductVersion", "${STRAWBERRY_VERSION_DISPLAY}"
|
||||
@@ -20,6 +19,6 @@ BEGIN
|
||||
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x809, 1252
|
||||
VALUE "Translation", 0x0809, 1252
|
||||
END
|
||||
END
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/* This file is part of Strawberry.
|
||||
Copyright 2013, David Sansome <me@davidsansome.com>
|
||||
Copyright 2018, Jonas Kvinge <jonas@jkvinge.net>
|
||||
|
||||
Strawberry is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -34,12 +35,13 @@
|
||||
#include <taglib/tstring.h>
|
||||
#include <taglib/tstringlist.h>
|
||||
#include <taglib/audioproperties.h>
|
||||
#include <taglib/trueaudiofile.h>
|
||||
#include <taglib/attachedpictureframe.h>
|
||||
#include <taglib/textidentificationframe.h>
|
||||
#include <taglib/unsynchronizedlyricsframe.h>
|
||||
#include <taglib/xiphcomment.h>
|
||||
#include <taglib/commentsframe.h>
|
||||
#include <taglib/tag.h>
|
||||
#include <taglib/apetag.h>
|
||||
#include <taglib/id3v2tag.h>
|
||||
#include "taglib/id3v2frame.h"
|
||||
#include <taglib/flacfile.h>
|
||||
@@ -63,6 +65,11 @@
|
||||
#include <taglib/mpcfile.h>
|
||||
#include <taglib/mpegfile.h>
|
||||
#include <taglib/opusfile.h>
|
||||
#include <taglib/trueaudiofile.h>
|
||||
#ifdef HAVE_TAGLIB_DSFFILE
|
||||
# include <taglib/dsffile.h>
|
||||
# include <taglib/dsdifffile.h>
|
||||
#endif
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QFile>
|
||||
@@ -89,8 +96,6 @@
|
||||
# define TAGLIB_HAS_FLAC_PICTURELIST
|
||||
#endif
|
||||
|
||||
#define NumberToASFAttribute(x) TagLib::ASF::Attribute(QStringToTaglibString(QString::number(x)))
|
||||
|
||||
class FileRefFactory {
|
||||
public:
|
||||
virtual ~FileRefFactory() {}
|
||||
@@ -135,7 +140,7 @@ TagReader::TagReader()
|
||||
kEmbeddedCover("(embedded)") {}
|
||||
|
||||
void TagReader::ReadFile(const QString &filename, pb::tagreader::SongMetadata *song) const {
|
||||
|
||||
|
||||
const QByteArray url(QUrl::fromLocalFile(filename).toEncoded());
|
||||
const QFileInfo info(filename);
|
||||
|
||||
@@ -149,19 +154,18 @@ void TagReader::ReadFile(const QString &filename, pb::tagreader::SongMetadata *s
|
||||
|
||||
std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));
|
||||
if (fileref->isNull()) {
|
||||
qLog(Info) << "TagLib hasn't been able to read " << filename << " file";
|
||||
qLog(Info) << "TagLib hasn't been able to read" << filename << "file";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
song->set_filetype(GuessFileType(fileref.get()));
|
||||
|
||||
if (fileref->audioProperties()) {
|
||||
song->set_bitrate(fileref->audioProperties()->bitrate());
|
||||
song->set_samplerate(fileref->audioProperties()->sampleRate());
|
||||
song->set_length_nanosec(fileref->audioProperties()->length() * kNsecPerSec);
|
||||
}
|
||||
|
||||
// Get the filetype if we can
|
||||
song->set_filetype(GuessFileType(fileref.get()));
|
||||
|
||||
TagLib::Tag *tag = fileref->tag();
|
||||
if (tag) {
|
||||
Decode(tag->title(), nullptr, song->mutable_title());
|
||||
@@ -175,20 +179,39 @@ void TagReader::ReadFile(const QString &filename, pb::tagreader::SongMetadata *s
|
||||
|
||||
QString disc;
|
||||
QString compilation;
|
||||
QString lyrics;
|
||||
|
||||
// Handle all the files which have VorbisComments (Ogg, OPUS, ...) in the same way;
|
||||
// apart, so we keep specific behavior for some formats by adding another
|
||||
// "else if" block below.
|
||||
// apart, so we keep specific behavior for some formats by adding another "else if" block below.
|
||||
if (TagLib::Ogg::XiphComment *tag = dynamic_cast<TagLib::Ogg::XiphComment*>(fileref->file()->tag())) {
|
||||
|
||||
ParseOggTag(tag->fieldListMap(), nullptr, &disc, &compilation, song);
|
||||
#if TAGLIB_MAJOR_VERSION >= 1 && TAGLIB_MINOR_VERSION >= 11
|
||||
if (!tag->pictureList().isEmpty()) song->set_art_automatic(kEmbeddedCover);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (TagLib::MPEG::File *file = dynamic_cast<TagLib::MPEG::File*>(fileref->file())) {
|
||||
|
||||
if (TagLib::FLAC::File *file = dynamic_cast<TagLib::FLAC::File *>(fileref->file())) {
|
||||
|
||||
song->set_bitdepth(file->audioProperties()->bitsPerSample());
|
||||
|
||||
if ( file->xiphComment() ) {
|
||||
ParseOggTag(file->xiphComment()->fieldListMap(), nullptr, &disc, &compilation, song);
|
||||
#ifdef TAGLIB_HAS_FLAC_PICTURELIST
|
||||
if (!file->pictureList().isEmpty()) {
|
||||
song->set_art_automatic(kEmbeddedCover);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (tag) Decode(tag->comment(), nullptr, song->mutable_comment());
|
||||
}
|
||||
|
||||
else if (TagLib::WavPack::File *file = dynamic_cast<TagLib::WavPack::File *>(fileref->file())) {
|
||||
song->set_bitdepth(file->audioProperties()->bitsPerSample());
|
||||
//if (tag) Decode(tag->comment(), nullptr, song->mutable_comment());
|
||||
}
|
||||
|
||||
else if (TagLib::MPEG::File *file = dynamic_cast<TagLib::MPEG::File*>(fileref->file())) {
|
||||
|
||||
if (file->ID3v2Tag()) {
|
||||
const TagLib::ID3v2::FrameListMap &map = file->ID3v2Tag()->frameListMap();
|
||||
|
||||
@@ -242,22 +265,9 @@ void TagReader::ReadFile(const QString &filename, pb::tagreader::SongMetadata *s
|
||||
|
||||
}
|
||||
}
|
||||
else if (TagLib::FLAC::File *file = dynamic_cast<TagLib::FLAC::File *>(fileref->file())) {
|
||||
|
||||
song->set_bitdepth(file->audioProperties()->bitsPerSample());
|
||||
|
||||
if ( file->xiphComment() ) {
|
||||
ParseOggTag(file->xiphComment()->fieldListMap(), nullptr, &disc, &compilation, song);
|
||||
#ifdef TAGLIB_HAS_FLAC_PICTURELIST
|
||||
if (!file->pictureList().isEmpty()) {
|
||||
song->set_art_automatic(kEmbeddedCover);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
Decode(tag->comment(), nullptr, song->mutable_comment());
|
||||
}
|
||||
else if (TagLib::MP4::File *file = dynamic_cast<TagLib::MP4::File*>(fileref->file())) {
|
||||
|
||||
|
||||
song->set_bitdepth(file->audioProperties()->bitsPerSample());
|
||||
|
||||
if (file->tag()) {
|
||||
@@ -292,41 +302,33 @@ void TagReader::ReadFile(const QString &filename, pb::tagreader::SongMetadata *s
|
||||
|
||||
if (items.contains(kMP4_OriginalYear_ID)) {
|
||||
song->set_originalyear(
|
||||
TStringToQString(
|
||||
items[kMP4_OriginalYear_ID].toStringList().toString('\n'))
|
||||
.left(4)
|
||||
.toInt());
|
||||
TStringToQString(items[kMP4_OriginalYear_ID].toStringList().toString('\n')).left(4).toInt());
|
||||
}
|
||||
|
||||
Decode(mp4_tag->comment(), nullptr, song->mutable_comment());
|
||||
}
|
||||
}
|
||||
#ifdef TAGLIB_WITH_ASF
|
||||
|
||||
else if (TagLib::ASF::File *file = dynamic_cast<TagLib::ASF::File*>(fileref->file())) {
|
||||
|
||||
|
||||
song->set_bitdepth(file->audioProperties()->bitsPerSample());
|
||||
|
||||
|
||||
const TagLib::ASF::AttributeListMap &attributes_map = file->tag()->attributeListMap();
|
||||
|
||||
if (attributes_map.contains(kASF_OriginalDate_ID)) {
|
||||
const TagLib::ASF::AttributeList &attributes =
|
||||
attributes_map[kASF_OriginalDate_ID];
|
||||
const TagLib::ASF::AttributeList &attributes = attributes_map[kASF_OriginalDate_ID];
|
||||
if (!attributes.isEmpty()) {
|
||||
song->set_originalyear(
|
||||
TStringToQString(attributes.front().toString()).left(4).toInt());
|
||||
song->set_originalyear(TStringToQString(attributes.front().toString()).left(4).toInt());
|
||||
}
|
||||
}
|
||||
else if (attributes_map.contains(kASF_OriginalYear_ID)) {
|
||||
const TagLib::ASF::AttributeList &attributes =
|
||||
attributes_map[kASF_OriginalYear_ID];
|
||||
const TagLib::ASF::AttributeList &attributes = attributes_map[kASF_OriginalYear_ID];
|
||||
if (!attributes.isEmpty()) {
|
||||
song->set_originalyear(
|
||||
TStringToQString(attributes.front().toString()).left(4).toInt());
|
||||
song->set_originalyear(TStringToQString(attributes.front().toString()).left(4).toInt());
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
else if (tag) {
|
||||
Decode(tag->comment(), nullptr, song->mutable_comment());
|
||||
}
|
||||
@@ -352,7 +354,7 @@ void TagReader::ReadFile(const QString &filename, pb::tagreader::SongMetadata *s
|
||||
song->set_compilation(compilation.toInt() == 1);
|
||||
}
|
||||
|
||||
|
||||
if (!lyrics.isEmpty()) song->set_lyrics(lyrics.toStdString());
|
||||
|
||||
// Set integer fields to -1 if they're not valid
|
||||
#define SetDefault(field) if (song->field() <= 0) { song->set_##field(-1); }
|
||||
@@ -364,11 +366,12 @@ void TagReader::ReadFile(const QString &filename, pb::tagreader::SongMetadata *s
|
||||
SetDefault(bitdepth);
|
||||
SetDefault(lastplayed);
|
||||
#undef SetDefault
|
||||
|
||||
}
|
||||
|
||||
|
||||
void TagReader::Decode(const TagLib::String &tag, const QTextCodec *codec, std::string *output) {
|
||||
|
||||
|
||||
QString tmp;
|
||||
|
||||
if (codec && tag.isLatin1()) { // Never override UTF-8.
|
||||
@@ -380,6 +383,7 @@ void TagReader::Decode(const TagLib::String &tag, const QTextCodec *codec, std::
|
||||
}
|
||||
|
||||
output->assign(DataCommaSizeFromQString(tmp));
|
||||
|
||||
}
|
||||
|
||||
void TagReader::Decode(const QString &tag, const QTextCodec *codec, std::string *output) {
|
||||
@@ -391,6 +395,7 @@ void TagReader::Decode(const QString &tag, const QTextCodec *codec, std::string
|
||||
const QString decoded(codec->toUnicode(tag.toUtf8()));
|
||||
output->assign(DataCommaSizeFromQString(decoded));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void TagReader::ParseFMPSFrame(const QString &name, const QString &value, pb::tagreader::SongMetadata *song) const {
|
||||
@@ -445,6 +450,11 @@ void TagReader::ParseOggTag(const TagLib::Ogg::FieldListMap &map, const QTextCod
|
||||
|
||||
if (!map["FMPS_PLAYCOUNT"].isEmpty() && song->playcount() <= 0) song->set_playcount(TStringToQString( map["FMPS_PLAYCOUNT"].front() ).trimmed().toFloat());
|
||||
|
||||
if (!map["LYRICS"].isEmpty())
|
||||
Decode(map["LYRICS"].front(), codec, song->mutable_lyrics());
|
||||
else if (!map["UNSYNCEDLYRICS"].isEmpty())
|
||||
Decode(map["UNSYNCEDLYRICS"].front(), codec, song->mutable_lyrics());
|
||||
|
||||
}
|
||||
|
||||
void TagReader::SetVorbisComments(TagLib::Ogg::XiphComment *vorbis_comments, const pb::tagreader::SongMetadata &song) const {
|
||||
@@ -460,43 +470,41 @@ void TagReader::SetVorbisComments(TagLib::Ogg::XiphComment *vorbis_comments, con
|
||||
vorbis_comments->addField("ALBUMARTIST", StdStringToTaglibString(song.albumartist()), true);
|
||||
vorbis_comments->removeField("ALBUM ARTIST");
|
||||
|
||||
vorbis_comments->addField("LYRICS", StdStringToTaglibString(song.lyrics()), true);
|
||||
vorbis_comments->removeField("UNSYNCEDLYRICS");
|
||||
|
||||
}
|
||||
|
||||
pb::tagreader::SongMetadata_Type TagReader::GuessFileType(TagLib::FileRef *fileref) const {
|
||||
pb::tagreader::SongMetadata_FileType TagReader::GuessFileType(TagLib::FileRef *fileref) const {
|
||||
|
||||
if (dynamic_cast<TagLib::RIFF::WAV::File*>(fileref->file())) return pb::tagreader::SongMetadata_Type_WAV;
|
||||
if (dynamic_cast<TagLib::FLAC::File*>(fileref->file())) return pb::tagreader::SongMetadata_Type_FLAC;
|
||||
if (dynamic_cast<TagLib::WavPack::File*>(fileref->file())) return pb::tagreader::SongMetadata_Type_WAVPACK;
|
||||
if (dynamic_cast<TagLib::Ogg::FLAC::File*>(fileref->file())) return pb::tagreader::SongMetadata_Type_OGGFLAC;
|
||||
if (dynamic_cast<TagLib::Ogg::Vorbis::File*>(fileref->file())) return pb::tagreader::SongMetadata_Type_OGGVORBIS;
|
||||
if (dynamic_cast<TagLib::Ogg::Opus::File*>(fileref->file())) return pb::tagreader::SongMetadata_Type_OGGOPUS;
|
||||
if (dynamic_cast<TagLib::Ogg::Speex::File*>(fileref->file())) return pb::tagreader::SongMetadata_Type_OGGSPEEX;
|
||||
if (dynamic_cast<TagLib::MPEG::File*>(fileref->file())) return pb::tagreader::SongMetadata_Type_MPEG;
|
||||
#ifdef TAGLIB_WITH_MP4
|
||||
if (dynamic_cast<TagLib::MP4::File*>(fileref->file())) return pb::tagreader::SongMetadata_Type_MP4;
|
||||
if (dynamic_cast<TagLib::RIFF::WAV::File*>(fileref->file())) return pb::tagreader::SongMetadata_FileType_WAV;
|
||||
if (dynamic_cast<TagLib::FLAC::File*>(fileref->file())) return pb::tagreader::SongMetadata_FileType_FLAC;
|
||||
if (dynamic_cast<TagLib::WavPack::File*>(fileref->file())) return pb::tagreader::SongMetadata_FileType_WAVPACK;
|
||||
if (dynamic_cast<TagLib::Ogg::FLAC::File*>(fileref->file())) return pb::tagreader::SongMetadata_FileType_OGGFLAC;
|
||||
if (dynamic_cast<TagLib::Ogg::Vorbis::File*>(fileref->file())) return pb::tagreader::SongMetadata_FileType_OGGVORBIS;
|
||||
if (dynamic_cast<TagLib::Ogg::Opus::File*>(fileref->file())) return pb::tagreader::SongMetadata_FileType_OGGOPUS;
|
||||
if (dynamic_cast<TagLib::Ogg::Speex::File*>(fileref->file())) return pb::tagreader::SongMetadata_FileType_OGGSPEEX;
|
||||
if (dynamic_cast<TagLib::MPEG::File*>(fileref->file())) return pb::tagreader::SongMetadata_FileType_MPEG;
|
||||
if (dynamic_cast<TagLib::MP4::File*>(fileref->file())) return pb::tagreader::SongMetadata_FileType_MP4;
|
||||
if (dynamic_cast<TagLib::ASF::File*>(fileref->file())) return pb::tagreader::SongMetadata_FileType_ASF;
|
||||
if (dynamic_cast<TagLib::RIFF::AIFF::File*>(fileref->file())) return pb::tagreader::SongMetadata_FileType_AIFF;
|
||||
if (dynamic_cast<TagLib::MPC::File*>(fileref->file())) return pb::tagreader::SongMetadata_FileType_MPC;
|
||||
if (dynamic_cast<TagLib::TrueAudio::File*>(fileref->file())) return pb::tagreader::SongMetadata_FileType_TRUEAUDIO;
|
||||
#ifdef HAVE_TAGLIB_DSFFILE
|
||||
if (dynamic_cast<TagLib::DSF::File*>(fileref->file())) return pb::tagreader::SongMetadata_FileType_DSF;
|
||||
if (dynamic_cast<TagLib::DSDIFF::File*>(fileref->file())) return pb::tagreader::SongMetadata_FileType_DSDIFF;
|
||||
#endif
|
||||
#ifdef TAGLIB_WITH_ASF
|
||||
if (dynamic_cast<TagLib::ASF::File*>(fileref->file())) return pb::tagreader::SongMetadata_Type_ASF;
|
||||
#endif
|
||||
if (dynamic_cast<TagLib::RIFF::AIFF::File*>(fileref->file())) return pb::tagreader::SongMetadata_Type_AIFF;
|
||||
if (dynamic_cast<TagLib::MPC::File*>(fileref->file())) return pb::tagreader::SongMetadata_Type_MPC;
|
||||
if (dynamic_cast<TagLib::TrueAudio::File*>(fileref->file())) return pb::tagreader::SongMetadata_Type_TRUEAUDIO;
|
||||
|
||||
return pb::tagreader::SongMetadata_Type_UNKNOWN;
|
||||
return pb::tagreader::SongMetadata_FileType_UNKNOWN;
|
||||
|
||||
}
|
||||
|
||||
bool TagReader::SaveFile(const QString &filename, const pb::tagreader::SongMetadata &song) const {
|
||||
|
||||
if (filename.isNull()) return false;
|
||||
|
||||
if (filename.isNull() || filename.isEmpty()) return false;
|
||||
qLog(Debug) << "Saving tags to" << filename;
|
||||
|
||||
std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));
|
||||
|
||||
if (!fileref || fileref->isNull()) // The file probably doesn't exist
|
||||
return false;
|
||||
std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));;
|
||||
if (!fileref || fileref->isNull()) return false;
|
||||
|
||||
fileref->tag()->setTitle(StdStringToTaglibString(song.title()));
|
||||
fileref->tag()->setArtist(StdStringToTaglibString(song.artist()));
|
||||
@@ -506,8 +514,24 @@ bool TagReader::SaveFile(const QString &filename, const pb::tagreader::SongMetad
|
||||
fileref->tag()->setYear(song.year());
|
||||
fileref->tag()->setTrack(song.track());
|
||||
|
||||
if (TagLib::MPEG::File *file = dynamic_cast<TagLib::MPEG::File*>(fileref->file())) {
|
||||
if (TagLib::FLAC::File *file = dynamic_cast<TagLib::FLAC::File*>(fileref->file())) {
|
||||
TagLib::Ogg::XiphComment *tag = file->xiphComment();
|
||||
SetVorbisComments(tag, song);
|
||||
}
|
||||
else if (TagLib::WavPack::File *file = dynamic_cast<TagLib::WavPack::File*>(fileref->file())) {
|
||||
TagLib::APE::Tag *tag = file->APETag(true);
|
||||
if (!tag) return false;
|
||||
tag->setArtist(StdStringToTaglibString(song.artist()));
|
||||
tag->setAlbum(StdStringToTaglibString(song.album()));
|
||||
tag->setTitle(StdStringToTaglibString(song.title()));
|
||||
tag->setGenre(StdStringToTaglibString(song.genre()));
|
||||
tag->setComment(StdStringToTaglibString(song.comment()));
|
||||
tag->setYear(song.year());
|
||||
tag->setTrack(song.track());
|
||||
}
|
||||
else if (TagLib::MPEG::File *file = dynamic_cast<TagLib::MPEG::File*>(fileref->file())) {
|
||||
TagLib::ID3v2::Tag *tag = file->ID3v2Tag(true);
|
||||
if (!tag) return false;
|
||||
SetTextFrame("TPOS", song.disc() <= 0 -1 ? QString() : QString::number(song.disc()), tag);
|
||||
SetTextFrame("TCOM", song.composer(), tag);
|
||||
SetTextFrame("TIT1", song.grouping(), tag);
|
||||
@@ -515,10 +539,7 @@ bool TagReader::SaveFile(const QString &filename, const pb::tagreader::SongMetad
|
||||
// Skip TPE1 (which is the artist) here because we already set it
|
||||
SetTextFrame("TPE2", song.albumartist(), tag);
|
||||
SetTextFrame("TCMP", std::string(song.compilation() ? "1" : "0"), tag);
|
||||
}
|
||||
else if (TagLib::FLAC::File *file = dynamic_cast<TagLib::FLAC::File*>(fileref->file())) {
|
||||
TagLib::Ogg::XiphComment *tag = file->xiphComment();
|
||||
SetVorbisComments(tag, song);
|
||||
SetUnsyncLyricsFrame(song.lyrics(), tag);
|
||||
}
|
||||
else if (TagLib::MP4::File *file = dynamic_cast<TagLib::MP4::File*>(fileref->file())) {
|
||||
TagLib::MP4::Tag *tag = file->tag();
|
||||
@@ -571,6 +592,7 @@ void TagReader::SetUserTextFrame(const std::string &description, const std::stri
|
||||
frame->setDescription(t_description);
|
||||
frame->setText(StdStringToTaglibString(value));
|
||||
tag->addFrame(frame);
|
||||
|
||||
}
|
||||
|
||||
void TagReader::SetTextFrame(const char *id, const QString &value, TagLib::ID3v2::Tag *tag) const {
|
||||
@@ -596,10 +618,15 @@ void TagReader::SetTextFrame(const char *id, const std::string &value, TagLib::I
|
||||
frames_buffer.push_back(frame.render());
|
||||
}
|
||||
|
||||
// add frame takes ownership and clears the memory
|
||||
TagLib::ID3v2::TextIdentificationFrame *frame;
|
||||
frame->setText(StdStringToTaglibString(value));
|
||||
tag->addFrame(frame);
|
||||
// Update and add the frames
|
||||
for (int lyrics_index = 0; lyrics_index < frames_buffer.size(); lyrics_index++) {
|
||||
TagLib::ID3v2::TextIdentificationFrame* frame = new TagLib::ID3v2::TextIdentificationFrame(frames_buffer.at(lyrics_index));
|
||||
if (lyrics_index == 0) {
|
||||
frame->setText(StdStringToTaglibString(value));
|
||||
}
|
||||
// add frame takes ownership and clears the memory
|
||||
tag->addFrame(frame);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -626,23 +653,26 @@ QByteArray TagReader::LoadEmbeddedArt(const QString &filename) const {
|
||||
|
||||
if (ref.isNull() || !ref.file()) return QByteArray();
|
||||
|
||||
// MP3
|
||||
TagLib::MPEG::File *file = dynamic_cast<TagLib::MPEG::File*>(ref.file());
|
||||
if (file && file->ID3v2Tag()) {
|
||||
TagLib::ID3v2::FrameList apic_frames = file->ID3v2Tag()->frameListMap()["APIC"];
|
||||
if (apic_frames.isEmpty())
|
||||
return QByteArray();
|
||||
#ifdef TAGLIB_HAS_FLAC_PICTURELIST
|
||||
// FLAC
|
||||
TagLib::FLAC::File *flac_file = dynamic_cast<TagLib::FLAC::File*>(ref.file());
|
||||
if (flac_file && flac_file->xiphComment()) {
|
||||
TagLib::List<TagLib::FLAC::Picture*> pics = flac_file->pictureList();
|
||||
if (!pics.isEmpty()) {
|
||||
// Use the first picture in the file - this could be made cleverer and
|
||||
// pick the front cover if it's present.
|
||||
|
||||
TagLib::ID3v2::AttachedPictureFrame *pic = static_cast<TagLib::ID3v2::AttachedPictureFrame*>(apic_frames.front());
|
||||
std::list<TagLib::FLAC::Picture*>::iterator it = pics.begin();
|
||||
TagLib::FLAC::Picture *picture = *it;
|
||||
|
||||
return QByteArray((const char*) pic->picture().data(), pic->picture().size());
|
||||
return QByteArray(picture->data().data(), picture->data().size());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Ogg vorbis/speex
|
||||
// Ogg Vorbis / Speex
|
||||
TagLib::Ogg::XiphComment *xiph_comment = dynamic_cast<TagLib::Ogg::XiphComment*>(ref.file()->tag());
|
||||
|
||||
if (xiph_comment) {
|
||||
|
||||
TagLib::Ogg::FieldListMap map = xiph_comment->fieldListMap();
|
||||
|
||||
#if TAGLIB_MAJOR_VERSION <= 1 && TAGLIB_MINOR_VERSION < 11
|
||||
@@ -685,22 +715,17 @@ QByteArray TagReader::LoadEmbeddedArt(const QString &filename) const {
|
||||
return QByteArray::fromBase64(map["COVERART"].toString().toCString());
|
||||
}
|
||||
|
||||
#ifdef TAGLIB_HAS_FLAC_PICTURELIST
|
||||
// Flac
|
||||
TagLib::FLAC::File *flac_file = dynamic_cast<TagLib::FLAC::File*>(ref.file());
|
||||
if (flac_file && flac_file->xiphComment()) {
|
||||
TagLib::List<TagLib::FLAC::Picture*> pics = flac_file->pictureList();
|
||||
if (!pics.isEmpty()) {
|
||||
// Use the first picture in the file - this could be made cleverer and
|
||||
// pick the front cover if it's present.
|
||||
// MP3
|
||||
TagLib::MPEG::File *file = dynamic_cast<TagLib::MPEG::File*>(ref.file());
|
||||
if (file && file->ID3v2Tag()) {
|
||||
TagLib::ID3v2::FrameList apic_frames = file->ID3v2Tag()->frameListMap()["APIC"];
|
||||
if (apic_frames.isEmpty())
|
||||
return QByteArray();
|
||||
|
||||
std::list<TagLib::FLAC::Picture*>::iterator it = pics.begin();
|
||||
TagLib::FLAC::Picture *picture = *it;
|
||||
TagLib::ID3v2::AttachedPictureFrame *pic = static_cast<TagLib::ID3v2::AttachedPictureFrame*>(apic_frames.front());
|
||||
|
||||
return QByteArray(picture->data().data(), picture->data().size());
|
||||
}
|
||||
return QByteArray((const char*) pic->picture().data(), pic->picture().size());
|
||||
}
|
||||
#endif
|
||||
|
||||
// MP4/AAC
|
||||
TagLib::MP4::File *aac_file = dynamic_cast<TagLib::MP4::File*>(ref.file());
|
||||
@@ -722,3 +747,33 @@ QByteArray TagReader::LoadEmbeddedArt(const QString &filename) const {
|
||||
return QByteArray();
|
||||
|
||||
}
|
||||
|
||||
void TagReader::SetUnsyncLyricsFrame(const std::string& value, TagLib::ID3v2::Tag* tag) const {
|
||||
|
||||
TagLib::ByteVector id_vector("USLT");
|
||||
QVector<TagLib::ByteVector> frames_buffer;
|
||||
|
||||
// Store and clear existing frames
|
||||
while (tag->frameListMap().contains(id_vector) && tag->frameListMap()[id_vector].size() != 0) {
|
||||
frames_buffer.push_back(tag->frameListMap()[id_vector].front()->render());
|
||||
tag->removeFrame(tag->frameListMap()[id_vector].front());
|
||||
}
|
||||
|
||||
// If no frames stored create empty frame
|
||||
if (frames_buffer.isEmpty()) {
|
||||
TagLib::ID3v2::UnsynchronizedLyricsFrame frame(TagLib::String::UTF8);
|
||||
frame.setDescription("Clementine editor");
|
||||
frames_buffer.push_back(frame.render());
|
||||
}
|
||||
|
||||
// Update and add the frames
|
||||
for (int lyrics_index = 0; lyrics_index < frames_buffer.size(); lyrics_index++) {
|
||||
TagLib::ID3v2::UnsynchronizedLyricsFrame* frame = new TagLib::ID3v2::UnsynchronizedLyricsFrame(frames_buffer.at(lyrics_index));
|
||||
if (lyrics_index == 0) {
|
||||
frame->setText(StdStringToTaglibString(value));
|
||||
}
|
||||
// add frame takes ownership and clears the memory
|
||||
tag->addFrame(frame);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/* This file is part of Strawberry.
|
||||
Copyright 2013, David Sansome <me@davidsansome.com>
|
||||
Copyright 2018, Jonas Kvinge <jonas@jkvinge.net>
|
||||
|
||||
Strawberry is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -64,13 +65,14 @@ class TagReader {
|
||||
void ParseOggTag(const TagLib::Ogg::FieldListMap &map, const QTextCodec *codec, QString *disc, QString *compilation, pb::tagreader::SongMetadata *song) const;
|
||||
void SetVorbisComments(TagLib::Ogg::XiphComment *vorbis_comments, const pb::tagreader::SongMetadata &song) const;
|
||||
|
||||
pb::tagreader::SongMetadata_Type GuessFileType(TagLib::FileRef *fileref) const;
|
||||
pb::tagreader::SongMetadata_FileType GuessFileType(TagLib::FileRef *fileref) const;
|
||||
|
||||
void SetUserTextFrame(const QString &description, const QString &value, TagLib::ID3v2::Tag *tag) const;
|
||||
void SetUserTextFrame(const std::string &description, const std::string& value, TagLib::ID3v2::Tag *tag) const;
|
||||
|
||||
void SetTextFrame(const char *id, const QString &value, TagLib::ID3v2::Tag *tag) const;
|
||||
void SetTextFrame(const char *id, const std::string &value, TagLib::ID3v2::Tag *tag) const;
|
||||
void SetUnsyncLyricsFrame(const std::string& value, TagLib::ID3v2::Tag* tag) const;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ package pb.tagreader;
|
||||
|
||||
message SongMetadata {
|
||||
|
||||
enum Type {
|
||||
enum FileType {
|
||||
UNKNOWN = 0;
|
||||
WAV = 1;
|
||||
FLAC = 2;
|
||||
@@ -19,12 +19,14 @@ message SongMetadata {
|
||||
AIFF = 11;
|
||||
MPC = 12;
|
||||
TRUEAUDIO = 13;
|
||||
DSF = 14;
|
||||
DSDIFF = 15;
|
||||
CDDA = 90;
|
||||
STREAM = 91;
|
||||
}
|
||||
|
||||
optional bool valid = 1;
|
||||
|
||||
|
||||
optional string title = 2;
|
||||
optional string album = 3;
|
||||
optional string artist = 4;
|
||||
@@ -39,26 +41,27 @@ message SongMetadata {
|
||||
optional string performer = 13;
|
||||
optional string grouping = 14;
|
||||
optional string comment = 15;
|
||||
|
||||
optional uint64 length_nanosec = 16;
|
||||
|
||||
optional int32 bitrate = 17;
|
||||
optional int32 samplerate = 18;
|
||||
optional int32 bitdepth = 19;
|
||||
optional string lyrics = 16;
|
||||
|
||||
optional string url = 20;
|
||||
optional string basefilename = 21;
|
||||
optional Type filetype = 22;
|
||||
optional int32 filesize = 23;
|
||||
optional int32 mtime = 24;
|
||||
optional int32 ctime = 25;
|
||||
optional uint64 length_nanosec = 17;
|
||||
|
||||
optional int32 playcount = 26;
|
||||
optional int32 skipcount = 27;
|
||||
optional int32 lastplayed = 28;
|
||||
optional int32 bitrate = 18;
|
||||
optional int32 samplerate = 19;
|
||||
optional int32 bitdepth = 20;
|
||||
|
||||
optional bool suspicious_tags = 29;
|
||||
optional string art_automatic = 30;
|
||||
optional string url = 21;
|
||||
optional string basefilename = 22;
|
||||
optional FileType filetype = 23;
|
||||
optional int32 filesize = 24;
|
||||
optional int32 mtime = 25;
|
||||
optional int32 ctime = 26;
|
||||
|
||||
optional int32 playcount = 27;
|
||||
optional int32 skipcount = 28;
|
||||
optional int32 lastplayed = 29;
|
||||
|
||||
optional bool suspicious_tags = 30;
|
||||
optional string art_automatic = 31;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -74,11 +74,6 @@ include_directories(${CMAKE_SOURCE_DIR}/ext/libstrawberry-common)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/ext/libstrawberry-tagreader)
|
||||
include_directories(${CMAKE_BINARY_DIR}/ext/libstrawberry-tagreader)
|
||||
|
||||
# Windows
|
||||
if (WIN32)
|
||||
include_directories(../3rdparty/qtwin)
|
||||
endif (WIN32)
|
||||
|
||||
set(SOURCES
|
||||
core/mainwindow.cpp
|
||||
core/application.cpp
|
||||
@@ -107,7 +102,6 @@ set(SOURCES
|
||||
core/urlhandler.cpp
|
||||
core/utilities.cpp
|
||||
core/scangiomodulepath.cpp
|
||||
core/flowlayout.cpp
|
||||
core/iconloader.cpp
|
||||
core/qtsystemtrayicon.cpp
|
||||
core/standarditemiconloader.cpp
|
||||
@@ -129,6 +123,10 @@ set(SOURCES
|
||||
equalizer/equalizer.cpp
|
||||
equalizer/equalizerslider.cpp
|
||||
|
||||
context/contextview.cpp
|
||||
context/contextalbumsmodel.cpp
|
||||
context/contextalbumsview.cpp
|
||||
|
||||
collection/collection.cpp
|
||||
collection/collectionmodel.cpp
|
||||
collection/collectionbackend.cpp
|
||||
@@ -193,9 +191,15 @@ set(SOURCES
|
||||
covermanager/currentartloader.cpp
|
||||
covermanager/coverfromurldialog.cpp
|
||||
covermanager/musicbrainzcoverprovider.cpp
|
||||
covermanager/amazoncoverprovider.cpp
|
||||
covermanager/discogscoverprovider.cpp
|
||||
|
||||
|
||||
lyrics/lyricsproviders.cpp
|
||||
lyrics/lyricsprovider.cpp
|
||||
lyrics/lyricsfetcher.cpp
|
||||
lyrics/lyricsfetchersearch.cpp
|
||||
lyrics/auddlyricsprovider.cpp
|
||||
lyrics/apiseedslyricsprovider.cpp
|
||||
|
||||
settings/settingsdialog.cpp
|
||||
settings/settingspage.cpp
|
||||
settings/behavioursettingspage.cpp
|
||||
@@ -207,6 +211,7 @@ set(SOURCES
|
||||
settings/shortcutssettingspage.cpp
|
||||
settings/appearancesettingspage.cpp
|
||||
settings/notificationssettingspage.cpp
|
||||
settings/tidalsettingspage.cpp
|
||||
|
||||
dialogs/about.cpp
|
||||
dialogs/console.cpp
|
||||
@@ -217,8 +222,6 @@ set(SOURCES
|
||||
widgets/autoexpandingtreeview.cpp
|
||||
widgets/busyindicator.cpp
|
||||
widgets/clickablelabel.cpp
|
||||
widgets/didyoumean.cpp
|
||||
widgets/elidedlabel.cpp
|
||||
widgets/fancytabwidget.cpp
|
||||
widgets/favoritewidget.cpp
|
||||
widgets/fileview.cpp
|
||||
@@ -229,14 +232,9 @@ set(SOURCES
|
||||
widgets/lineedit.cpp
|
||||
widgets/linetextedit.cpp
|
||||
widgets/multiloadingindicator.cpp
|
||||
widgets/statusview.cpp
|
||||
widgets/playingwidget.cpp
|
||||
widgets/osd.cpp
|
||||
widgets/osdpretty.cpp
|
||||
widgets/prettyimage.cpp
|
||||
widgets/prettyimageview.cpp
|
||||
widgets/progressitemdelegate.cpp
|
||||
widgets/ratingwidget.cpp
|
||||
widgets/renametablineedit.cpp
|
||||
widgets/sliderwidget.cpp
|
||||
widgets/stickyslider.cpp
|
||||
@@ -245,7 +243,7 @@ set(SOURCES
|
||||
widgets/trackslider.cpp
|
||||
widgets/tracksliderpopup.cpp
|
||||
widgets/tracksliderslider.cpp
|
||||
widgets/widgetfadehelper.cpp
|
||||
widgets/loginstatewidget.cpp
|
||||
|
||||
musicbrainz/acoustidclient.cpp
|
||||
musicbrainz/musicbrainzclient.cpp
|
||||
@@ -255,16 +253,18 @@ set(SOURCES
|
||||
globalshortcuts/gnomeglobalshortcutbackend.cpp
|
||||
globalshortcuts/qxtglobalshortcutbackend.cpp
|
||||
globalshortcuts/globalshortcutgrabber.cpp
|
||||
|
||||
device/connecteddevice.cpp
|
||||
device/devicedatabasebackend.cpp
|
||||
device/devicelister.cpp
|
||||
device/devicemanager.cpp
|
||||
device/deviceproperties.cpp
|
||||
device/devicestatefiltermodel.cpp
|
||||
device/deviceview.cpp
|
||||
device/deviceviewcontainer.cpp
|
||||
device/filesystemdevice.cpp
|
||||
|
||||
internet/internetmodel.cpp
|
||||
internet/internetservice.cpp
|
||||
internet/internetplaylistitem.cpp
|
||||
|
||||
tidal/tidalservice.cpp
|
||||
tidal/tidalsearch.cpp
|
||||
tidal/tidalsearchview.cpp
|
||||
tidal/tidalsearchmodel.cpp
|
||||
tidal/tidalsearchsortmodel.cpp
|
||||
tidal/tidalsearchitemdelegate.cpp
|
||||
tidal/tidalurlhandler.cpp
|
||||
|
||||
)
|
||||
|
||||
@@ -297,6 +297,10 @@ set(HEADERS
|
||||
|
||||
equalizer/equalizer.h
|
||||
equalizer/equalizerslider.h
|
||||
|
||||
context/contextview.h
|
||||
context/contextalbumsmodel.h
|
||||
context/contextalbumsview.h
|
||||
|
||||
collection/collection.h
|
||||
collection/collectionmodel.h
|
||||
@@ -353,10 +357,16 @@ set(HEADERS
|
||||
covermanager/coverexportrunnable.h
|
||||
covermanager/currentartloader.h
|
||||
covermanager/coverfromurldialog.h
|
||||
covermanager/amazoncoverprovider.h
|
||||
covermanager/musicbrainzcoverprovider.h
|
||||
covermanager/discogscoverprovider.h
|
||||
|
||||
|
||||
lyrics/lyricsproviders.h
|
||||
lyrics/lyricsprovider.h
|
||||
lyrics/lyricsfetcher.h
|
||||
lyrics/lyricsfetchersearch.h
|
||||
lyrics/auddlyricsprovider.h
|
||||
lyrics/apiseedslyricsprovider.h
|
||||
|
||||
settings/settingsdialog.h
|
||||
settings/settingspage.h
|
||||
settings/behavioursettingspage.h
|
||||
@@ -368,7 +378,8 @@ set(HEADERS
|
||||
settings/shortcutssettingspage.h
|
||||
settings/appearancesettingspage.h
|
||||
settings/notificationssettingspage.h
|
||||
|
||||
settings/tidalsettingspage.h
|
||||
|
||||
dialogs/about.h
|
||||
dialogs/errordialog.h
|
||||
dialogs/console.h
|
||||
@@ -378,8 +389,6 @@ set(HEADERS
|
||||
widgets/autoexpandingtreeview.h
|
||||
widgets/busyindicator.h
|
||||
widgets/clickablelabel.h
|
||||
widgets/didyoumean.h
|
||||
widgets/elidedlabel.h
|
||||
widgets/fancytabwidget.h
|
||||
widgets/favoritewidget.h
|
||||
widgets/fileview.h
|
||||
@@ -389,14 +398,9 @@ set(HEADERS
|
||||
widgets/lineedit.h
|
||||
widgets/linetextedit.h
|
||||
widgets/multiloadingindicator.h
|
||||
widgets/statusview.h
|
||||
widgets/playingwidget.h
|
||||
widgets/osd.h
|
||||
widgets/osdpretty.h
|
||||
widgets/prettyimage.h
|
||||
widgets/prettyimageview.h
|
||||
widgets/progressitemdelegate.h
|
||||
widgets/ratingwidget.h
|
||||
widgets/renametablineedit.h
|
||||
widgets/sliderwidget.h
|
||||
widgets/stickyslider.h
|
||||
@@ -404,7 +408,7 @@ set(HEADERS
|
||||
widgets/trackslider.h
|
||||
widgets/tracksliderpopup.h
|
||||
widgets/tracksliderslider.h
|
||||
widgets/widgetfadehelper.h
|
||||
widgets/loginstatewidget.h
|
||||
|
||||
musicbrainz/acoustidclient.h
|
||||
musicbrainz/musicbrainzclient.h
|
||||
@@ -413,16 +417,17 @@ set(HEADERS
|
||||
globalshortcuts/globalshortcuts.h
|
||||
globalshortcuts/gnomeglobalshortcutbackend.h
|
||||
globalshortcuts/globalshortcutgrabber.h
|
||||
|
||||
device/connecteddevice.h
|
||||
device/devicedatabasebackend.h
|
||||
device/devicelister.h
|
||||
device/devicemanager.h
|
||||
device/deviceproperties.h
|
||||
device/devicestatefiltermodel.h
|
||||
device/deviceviewcontainer.h
|
||||
device/deviceview.h
|
||||
device/filesystemdevice.h
|
||||
|
||||
internet/internetmodel.h
|
||||
internet/internetservice.h
|
||||
internet/internetmimedata.h
|
||||
internet/internetsongmimedata.h
|
||||
|
||||
tidal/tidalservice.h
|
||||
tidal/tidalsearch.h
|
||||
tidal/tidalsearchview.h
|
||||
tidal/tidalsearchmodel.h
|
||||
tidal/tidalurlhandler.h
|
||||
|
||||
)
|
||||
|
||||
@@ -430,6 +435,8 @@ set(UI
|
||||
|
||||
core/mainwindow.ui
|
||||
|
||||
context/contextviewcontainer.ui
|
||||
|
||||
collection/groupbydialog.ui
|
||||
collection/collectionfilterwidget.ui
|
||||
collection/collectionviewcontainer.ui
|
||||
@@ -457,6 +464,7 @@ set(UI
|
||||
settings/shortcutssettingspage.ui
|
||||
settings/appearancesettingspage.ui
|
||||
settings/notificationssettingspage.ui
|
||||
settings/tidalsettingspage.ui
|
||||
|
||||
equalizer/equalizer.ui
|
||||
equalizer/equalizerslider.ui
|
||||
@@ -470,12 +478,12 @@ set(UI
|
||||
widgets/trackslider.ui
|
||||
widgets/osdpretty.ui
|
||||
widgets/fileview.ui
|
||||
|
||||
device/deviceproperties.ui
|
||||
device/deviceviewcontainer.ui
|
||||
widgets/loginstatewidget.ui
|
||||
|
||||
globalshortcuts/globalshortcutgrabber.ui
|
||||
|
||||
tidal/tidalsearchview.ui
|
||||
|
||||
)
|
||||
|
||||
set(RESOURCES ../data/data.qrc)
|
||||
@@ -500,7 +508,7 @@ optional_source(HAVE_GSTREAMER
|
||||
|
||||
# Xine
|
||||
optional_source(HAVE_XINE
|
||||
SOURCES engine/xineengine.cpp engine/xinescope.c engine/xinefader.cpp
|
||||
SOURCES engine/xineengine.cpp engine/xinescope.c
|
||||
HEADERS engine/xineengine.h
|
||||
)
|
||||
|
||||
@@ -648,6 +656,32 @@ optional_source(HAVE_DBUS
|
||||
core/mpris2.h
|
||||
)
|
||||
|
||||
optional_source(UNIX
|
||||
SOURCES
|
||||
device/connecteddevice.cpp
|
||||
device/devicedatabasebackend.cpp
|
||||
device/devicelister.cpp
|
||||
device/devicemanager.cpp
|
||||
device/devicestatefiltermodel.cpp
|
||||
device/filesystemdevice.cpp
|
||||
device/deviceviewcontainer.cpp
|
||||
device/deviceview.cpp
|
||||
device/deviceproperties.cpp
|
||||
HEADERS
|
||||
device/connecteddevice.h
|
||||
device/devicedatabasebackend.h
|
||||
device/devicelister.h
|
||||
device/devicemanager.h
|
||||
device/devicestatefiltermodel.h
|
||||
device/filesystemdevice.h
|
||||
device/deviceviewcontainer.h
|
||||
device/deviceview.h
|
||||
device/deviceproperties.h
|
||||
UI
|
||||
device/deviceproperties.ui
|
||||
device/deviceviewcontainer.ui
|
||||
)
|
||||
|
||||
if(HAVE_DBUS)
|
||||
optional_source(HAVE_DEVICEKIT
|
||||
SOURCES device/devicekitlister.cpp
|
||||
@@ -724,8 +758,6 @@ SOURCES
|
||||
settings/transcodersettingspage.cpp
|
||||
dialogs/organisedialog.cpp
|
||||
dialogs/organiseerrordialog.cpp
|
||||
musicbrainz/chromaprinter.cpp
|
||||
musicbrainz/tagfetcher.cpp
|
||||
transcoder/transcoder.cpp
|
||||
transcoder/transcodedialog.cpp
|
||||
transcoder/transcoderoptionsaac.cpp
|
||||
@@ -741,7 +773,6 @@ HEADERS
|
||||
settings/transcodersettingspage.h
|
||||
dialogs/organisedialog.h
|
||||
dialogs/organiseerrordialog.h
|
||||
musicbrainz/tagfetcher.h
|
||||
transcoder/transcoder.h
|
||||
transcoder/transcodedialog.h
|
||||
transcoder/transcoderoptionsdialog.h
|
||||
@@ -764,6 +795,13 @@ UI
|
||||
|
||||
# CDIO backend and device
|
||||
if(HAVE_GSTREAMER)
|
||||
optional_source(HAVE_CHROMAPRINT
|
||||
SOURCES
|
||||
musicbrainz/chromaprinter.cpp
|
||||
musicbrainz/tagfetcher.cpp
|
||||
HEADERS
|
||||
musicbrainz/tagfetcher.h
|
||||
)
|
||||
optional_source(HAVE_AUDIOCD
|
||||
SOURCES
|
||||
device/cddadevice.cpp
|
||||
@@ -816,6 +854,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.h.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/version.h)
|
||||
|
||||
|
||||
qt5_wrap_cpp(MOC ${HEADERS})
|
||||
qt5_wrap_ui(UIC ${UI})
|
||||
qt5_add_resources(QRC ${RESOURCES})
|
||||
@@ -924,7 +963,6 @@ endif (APPLE)
|
||||
if (WIN32)
|
||||
target_link_libraries(strawberry_lib
|
||||
${ZLIB_LIBRARIES}
|
||||
qtwin
|
||||
dsound
|
||||
${QT_QTGUI_LIBRARY}
|
||||
)
|
||||
|
||||
0
src/analyzer/analyzerbase.cpp
Executable file → Normal file
@@ -15,7 +15,7 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@@ -57,14 +57,12 @@ SCollection::SCollection(Application *app, QObject *parent)
|
||||
backend_->Init(app->database(), kSongsTable, kDirsTable, kSubdirsTable, kFtsTable);
|
||||
|
||||
model_ = new CollectionModel(backend_, app_, this);
|
||||
|
||||
|
||||
ReloadSettings();
|
||||
|
||||
}
|
||||
|
||||
SCollection::~SCollection() {
|
||||
|
||||
watcher_->deleteLater();
|
||||
watcher_thread_->exit();
|
||||
watcher_thread_->wait(5000 /* five seconds */);
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef COLLECTION_H
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@@ -54,7 +54,6 @@ CollectionBackend::CollectionBackend(QObject *parent)
|
||||
{}
|
||||
|
||||
void CollectionBackend::Init(Database *db, const QString &songs_table, const QString &dirs_table, const QString &subdirs_table, const QString &fts_table) {
|
||||
|
||||
db_ = db;
|
||||
songs_table_ = songs_table;
|
||||
dirs_table_ = dirs_table;
|
||||
@@ -110,12 +109,14 @@ void CollectionBackend::ChangeDirPath(int id, const QString &old_path, const QSt
|
||||
ScopedTransaction t(&db);
|
||||
|
||||
// Do the dirs table
|
||||
QSqlQuery q(db);
|
||||
q.prepare(QString("UPDATE %1 SET path=:path WHERE ROWID=:id").arg(dirs_table_));
|
||||
q.bindValue(":path", new_path);
|
||||
q.bindValue(":id", id);
|
||||
q.exec();
|
||||
if (db_->CheckErrors(q)) return;
|
||||
{
|
||||
QSqlQuery q(db);
|
||||
q.prepare(QString("UPDATE %1 SET path=:path WHERE ROWID=:id").arg(dirs_table_));
|
||||
q.bindValue(":path", new_path);
|
||||
q.bindValue(":id", id);
|
||||
q.exec();
|
||||
if (db_->CheckErrors(q)) return;
|
||||
}
|
||||
|
||||
const QByteArray old_url = QUrl::fromLocalFile(old_path).toEncoded();
|
||||
const QByteArray new_url = QUrl::fromLocalFile(new_path).toEncoded();
|
||||
@@ -123,20 +124,24 @@ void CollectionBackend::ChangeDirPath(int id, const QString &old_path, const QSt
|
||||
const int path_len = old_url.length();
|
||||
|
||||
// Do the subdirs table
|
||||
q = QSqlQuery(db);
|
||||
q.prepare(QString("UPDATE %1 SET path=:path || substr(path, %2) WHERE directory=:id").arg(subdirs_table_).arg(path_len));
|
||||
q.bindValue(":path", new_url);
|
||||
q.bindValue(":id", id);
|
||||
q.exec();
|
||||
if (db_->CheckErrors(q)) return;
|
||||
{
|
||||
QSqlQuery q(db);
|
||||
q.prepare(QString("UPDATE %1 SET path=:path || substr(path, %2) WHERE directory=:id").arg(subdirs_table_).arg(path_len));
|
||||
q.bindValue(":path", new_url);
|
||||
q.bindValue(":id", id);
|
||||
q.exec();
|
||||
if (db_->CheckErrors(q)) return;
|
||||
}
|
||||
|
||||
// Do the songs table
|
||||
q = QSqlQuery(db);
|
||||
q.prepare(QString("UPDATE %1 SET filename=:path || substr(filename, %2) WHERE directory=:id").arg(songs_table_).arg(path_len));
|
||||
q.bindValue(":path", new_url);
|
||||
q.bindValue(":id", id);
|
||||
q.exec();
|
||||
if (db_->CheckErrors(q)) return;
|
||||
{
|
||||
QSqlQuery q(db);
|
||||
q.prepare(QString("UPDATE %1 SET filename=:path || substr(filename, %2) WHERE directory=:id").arg(songs_table_).arg(path_len));
|
||||
q.bindValue(":path", new_url);
|
||||
q.bindValue(":id", id);
|
||||
q.exec();
|
||||
if (db_->CheckErrors(q)) return;
|
||||
}
|
||||
|
||||
t.Commit();
|
||||
|
||||
@@ -219,8 +224,6 @@ void CollectionBackend::UpdateTotalArtistCount() {
|
||||
q.exec();
|
||||
if (db_->CheckErrors(q)) return;
|
||||
if (!q.next()) return;
|
||||
|
||||
//qLog(Debug) << "TotalArtist: " << q.value(0).toInt();
|
||||
|
||||
emit TotalArtistCountUpdated(q.value(0).toInt());
|
||||
|
||||
@@ -236,8 +239,6 @@ void CollectionBackend::UpdateTotalAlbumCount() {
|
||||
q.exec();
|
||||
if (db_->CheckErrors(q)) return;
|
||||
if (!q.next()) return;
|
||||
|
||||
//qLog(Debug) << "TotalAlbum: " << q.value(0).toInt();
|
||||
|
||||
emit TotalAlbumCountUpdated(q.value(0).toInt());
|
||||
|
||||
@@ -530,7 +531,7 @@ void CollectionBackend::MarkSongsUnavailable(const SongList &songs, bool unavail
|
||||
}
|
||||
|
||||
QStringList CollectionBackend::GetAll(const QString &column, const QueryOptions &opt) {
|
||||
|
||||
|
||||
CollectionQuery query(opt);
|
||||
query.SetColumnSpec("DISTINCT " + column);
|
||||
query.AddCompilationRequirement(false);
|
||||
@@ -547,6 +548,7 @@ QStringList CollectionBackend::GetAll(const QString &column, const QueryOptions
|
||||
}
|
||||
|
||||
QStringList CollectionBackend::GetAllArtists(const QueryOptions &opt) {
|
||||
|
||||
return GetAll("artist", opt);
|
||||
}
|
||||
|
||||
@@ -596,8 +598,7 @@ CollectionBackend::AlbumList CollectionBackend::GetAlbumsByArtist(const QString
|
||||
return GetAlbums(artist, QString(), false, opt);
|
||||
}
|
||||
|
||||
CollectionBackend::AlbumList CollectionBackend::GetAlbumsByAlbumArtist(
|
||||
const QString &album_artist, const QueryOptions &opt) {
|
||||
CollectionBackend::AlbumList CollectionBackend::GetAlbumsByAlbumArtist(const QString &album_artist, const QueryOptions &opt) {
|
||||
return GetAlbums(QString(), album_artist, false, opt);
|
||||
}
|
||||
|
||||
@@ -629,6 +630,7 @@ SongList CollectionBackend::ExecCollectionQuery(CollectionQuery *query) {
|
||||
ret << song;
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
Song CollectionBackend::GetSongById(int id) {
|
||||
@@ -638,7 +640,6 @@ Song CollectionBackend::GetSongById(int id) {
|
||||
}
|
||||
|
||||
SongList CollectionBackend::GetSongsById(const QList<int> &ids) {
|
||||
|
||||
QMutexLocker l(db_->Mutex());
|
||||
QSqlDatabase db(db_->Connect());
|
||||
|
||||
@@ -658,7 +659,6 @@ SongList CollectionBackend::GetSongsById(const QStringList &ids) {
|
||||
}
|
||||
|
||||
SongList CollectionBackend::GetSongsByForeignId(const QStringList &ids, const QString &table, const QString &column) {
|
||||
|
||||
QMutexLocker l(db_->Mutex());
|
||||
QSqlDatabase db(db_->Connect());
|
||||
|
||||
@@ -687,7 +687,6 @@ Song CollectionBackend::GetSongById(int id, QSqlDatabase &db) {
|
||||
}
|
||||
|
||||
SongList CollectionBackend::GetSongsById(const QStringList &ids, QSqlDatabase &db) {
|
||||
|
||||
QString in = ids.join(",");
|
||||
|
||||
QSqlQuery q(db);
|
||||
@@ -705,7 +704,6 @@ SongList CollectionBackend::GetSongsById(const QStringList &ids, QSqlDatabase &d
|
||||
}
|
||||
|
||||
Song CollectionBackend::GetSongByUrl(const QUrl &url, qint64 beginning) {
|
||||
|
||||
CollectionQuery query;
|
||||
query.SetColumnSpec("%songs_table.ROWID, " + Song::kColumnSpec);
|
||||
query.AddWhere("filename", url.toEncoded());
|
||||
@@ -719,7 +717,6 @@ Song CollectionBackend::GetSongByUrl(const QUrl &url, qint64 beginning) {
|
||||
}
|
||||
|
||||
SongList CollectionBackend::GetSongsByUrl(const QUrl &url) {
|
||||
|
||||
CollectionQuery query;
|
||||
query.SetColumnSpec("%songs_table.ROWID, " + Song::kColumnSpec);
|
||||
query.AddWhere("filename", url.toEncoded());
|
||||
@@ -729,7 +726,6 @@ SongList CollectionBackend::GetSongsByUrl(const QUrl &url) {
|
||||
while (query.Next()) {
|
||||
Song song;
|
||||
song.InitFromQuery(query, true);
|
||||
|
||||
songlist << song;
|
||||
}
|
||||
}
|
||||
@@ -757,6 +753,7 @@ SongList CollectionBackend::GetCompilationSongs(const QString &album, const Quer
|
||||
ret << song;
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
void CollectionBackend::UpdateCompilations() {
|
||||
@@ -789,7 +786,7 @@ void CollectionBackend::UpdateCompilations() {
|
||||
info.artists.insert(artist);
|
||||
info.directories.insert(filename.left(last_separator));
|
||||
if (compilation_detected) info.has_compilation_detected = true;
|
||||
else info.has_not_compilation_detected = true;
|
||||
else info.has_not_compilation_detected = true;
|
||||
}
|
||||
|
||||
// Now mark the songs that we think are in compilations
|
||||
@@ -933,7 +930,7 @@ CollectionBackend::Album CollectionBackend::GetAlbumArt(const QString &artist, c
|
||||
}
|
||||
|
||||
void CollectionBackend::UpdateManualAlbumArtAsync(const QString &artist, const QString &albumartist, const QString &album, const QString &art) {
|
||||
|
||||
|
||||
metaObject()->invokeMethod(this, "UpdateManualAlbumArt", Qt::QueuedConnection, Q_ARG(QString, artist), Q_ARG(QString, albumartist), Q_ARG(QString, album), Q_ARG(QString, art));
|
||||
|
||||
}
|
||||
|
||||