Initial commit
This commit is contained in:
commit
e7a07a37b5
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# Use target-compatible line endings as the safe default for cross compilation.
|
||||||
|
* text=auto eol=lf
|
340
LICENSE
Normal file
340
LICENSE
Normal file
@ -0,0 +1,340 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||||
|
<https://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Lesser General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Moe Ghoul>, 1 April 1989
|
||||||
|
Moe Ghoul, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License.
|
||||||
|
|
||||||
|
|
5
README.md
Normal file
5
README.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# Volumio
|
||||||
|
|
||||||
|
A simple Volumio player!
|
||||||
|
|
||||||
|
Volumio devices needs to have UPnP enabled for the app to discover them. When discovered it simply connects to the webbased player in a WebView.
|
20
harbour-volumio.desktop
Normal file
20
harbour-volumio.desktop
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Type=Application
|
||||||
|
X-Nemo-Application-Type=silica-qt5
|
||||||
|
Icon=harbour-volumio
|
||||||
|
Exec=harbour-volumio
|
||||||
|
Name=harbour-volumio
|
||||||
|
# translation example:
|
||||||
|
# your app name in German locale (de)
|
||||||
|
#
|
||||||
|
# Remember to comment out the following line, if you do not want to use
|
||||||
|
# a different app name in German locale (de).
|
||||||
|
Name[de]=harbour-volumio
|
||||||
|
|
||||||
|
[X-Sailjail]
|
||||||
|
# Replace with your organization as a reverse domain name
|
||||||
|
OrganizationName=org.myorg
|
||||||
|
# ApplicationName does not have to be identical to Name
|
||||||
|
ApplicationName=volumio
|
||||||
|
# Add the required permissions here
|
||||||
|
Permissions=WebView;Internet
|
43
harbour-volumio.pro
Normal file
43
harbour-volumio.pro
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# NOTICE:
|
||||||
|
#
|
||||||
|
# Application name defined in TARGET has a corresponding QML filename.
|
||||||
|
# If name defined in TARGET is changed, the following needs to be done
|
||||||
|
# to match new name:
|
||||||
|
# - corresponding QML filename must be changed
|
||||||
|
# - desktop icon filename must be changed
|
||||||
|
# - desktop filename must be changed
|
||||||
|
# - icon definition filename in desktop file must be changed
|
||||||
|
# - translation filenames have to be changed
|
||||||
|
|
||||||
|
# The name of your application
|
||||||
|
TARGET = harbour-volumio
|
||||||
|
|
||||||
|
CONFIG += sailfishapp
|
||||||
|
|
||||||
|
SOURCES += src/harbour-volumio.cpp
|
||||||
|
|
||||||
|
DISTFILES += qml/harbour-volumio.qml \
|
||||||
|
LICENSE \
|
||||||
|
README.md \
|
||||||
|
qml/cover/CoverPage.qml \
|
||||||
|
qml/pages/Splash.qml \
|
||||||
|
qml/pages/VolumIo.qml \
|
||||||
|
rpm/harbour-volumio.changes.in \
|
||||||
|
rpm/harbour-volumio.changes.run.in \
|
||||||
|
rpm/harbour-volumio.spec \
|
||||||
|
translations/*.ts \
|
||||||
|
harbour-volumio.desktop
|
||||||
|
|
||||||
|
SAILFISHAPP_ICONS = 86x86 108x108 128x128 172x172
|
||||||
|
|
||||||
|
# to disable building translations every time, comment out the
|
||||||
|
# following CONFIG line
|
||||||
|
CONFIG += sailfishapp_i18n
|
||||||
|
|
||||||
|
PKGCONFIG += qt5embedwidget
|
||||||
|
|
||||||
|
# German translation is enabled as an example. If you aren't
|
||||||
|
# planning to localize your app, remember to comment out the
|
||||||
|
# following TRANSLATIONS line. And also do not forget to
|
||||||
|
# modify the localized app name in the the .desktop file.
|
||||||
|
TRANSLATIONS += translations/harbour-volumio-de.ts
|
BIN
icons/108x108/harbour-volumio.png
Normal file
BIN
icons/108x108/harbour-volumio.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
BIN
icons/128x128/harbour-volumio.png
Normal file
BIN
icons/128x128/harbour-volumio.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
BIN
icons/172x172/harbour-volumio.png
Normal file
BIN
icons/172x172/harbour-volumio.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
BIN
icons/86x86/harbour-volumio.png
Normal file
BIN
icons/86x86/harbour-volumio.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
13
qml/cover/CoverPage.qml
Normal file
13
qml/cover/CoverPage.qml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import QtQuick 2.0
|
||||||
|
import Sailfish.Silica 1.0
|
||||||
|
|
||||||
|
CoverBackground {
|
||||||
|
Image {
|
||||||
|
source: thumbnail
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
id: label
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: qsTr("My Cover")
|
||||||
|
}
|
||||||
|
}
|
11
qml/harbour-volumio.qml
Normal file
11
qml/harbour-volumio.qml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import QtQuick 2.0
|
||||||
|
import Sailfish.Silica 1.0
|
||||||
|
import "pages"
|
||||||
|
|
||||||
|
ApplicationWindow {
|
||||||
|
property url thumbnail: ""
|
||||||
|
|
||||||
|
initialPage: Component { VolumIo { } }
|
||||||
|
cover: Qt.resolvedUrl("cover/CoverPage.qml")
|
||||||
|
allowedOrientations: Orientation.All
|
||||||
|
}
|
225
qml/pages/Splash.qml
Normal file
225
qml/pages/Splash.qml
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
import QtQuick 2.0
|
||||||
|
import Sailfish.Silica 1.0
|
||||||
|
import Sailfish.WebView 1.0
|
||||||
|
import Sailfish.WebEngine 1.0
|
||||||
|
import QtQuick.XmlListModel 2.0
|
||||||
|
import io.thp.pyotherside 1.5
|
||||||
|
|
||||||
|
Page {
|
||||||
|
id: page
|
||||||
|
property variant devices: squeezeboxSettings.value("devices",[])
|
||||||
|
//property variant defaultDevice: squeezeboxSettings.value("defaultDevice","") // squeezeboxSettings.setValue("defaultSource",[ip,port,icon,friendlyName,modelName,source])
|
||||||
|
property bool running: true
|
||||||
|
property bool discovering: false
|
||||||
|
property int retries: 0
|
||||||
|
|
||||||
|
|
||||||
|
function getXml(source) {
|
||||||
|
var req = new XMLHttpRequest();
|
||||||
|
req.open("get", source,false);
|
||||||
|
req.onreadystatechange = function () {
|
||||||
|
if (req.readyState === 4 && req.status === 200) {
|
||||||
|
var xml = req.responseText
|
||||||
|
var friendlyName
|
||||||
|
var modelName
|
||||||
|
var icon
|
||||||
|
var ip
|
||||||
|
var port
|
||||||
|
var tmp = source.toString()
|
||||||
|
tmp = tmp.split("//")
|
||||||
|
tmp = tmp[1].split(":")
|
||||||
|
ip = tmp[0]
|
||||||
|
tmp = tmp[1].split("/")
|
||||||
|
port = tmp[0]
|
||||||
|
|
||||||
|
xml.match(/<friendlyName>(.*?)<\/friendlyName>/g).map(function(val){
|
||||||
|
friendlyName = val.replace(/<\/?friendlyName>/g,'')
|
||||||
|
//console.log(friendlyName)
|
||||||
|
});
|
||||||
|
|
||||||
|
xml.match(/<modelName>(.*?)<\/modelName>/g).map(function(val){
|
||||||
|
modelName = val.replace(/<\/?modelName>/g,'')
|
||||||
|
//console.log(modelName+" ("+ip+")")
|
||||||
|
});
|
||||||
|
|
||||||
|
xml.match(/<url>(.*?)<\/url>/g).map(function(val){
|
||||||
|
|
||||||
|
icon = val.replace(/<\/?url>/g,'')
|
||||||
|
console.log(val+" ****** 120x120 *****")
|
||||||
|
});
|
||||||
|
var patt = /^UpMPD/;
|
||||||
|
console.log(" ************ PATT: "+patt)
|
||||||
|
if (patt.test(modelName))
|
||||||
|
deviceModel.append({"friendlyName": friendlyName,"modelName": modelName,"ip":ip,"port":port,"icon":icon,"source":source});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
req.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
ListModel {id: deviceModel}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
id: volum
|
||||||
|
text: "VOLUMIO"
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: Theme.paddingLarge
|
||||||
|
color: Theme.primaryColor
|
||||||
|
font.pixelSize: Theme.fontSizeExtraLarge * 2
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
text: "THE MUSIC PLAYER"
|
||||||
|
anchors.top: volum.bottom
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
//anchors.topMargin: Theme.paddingLarge
|
||||||
|
color: Theme.primaryColor
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
visible: !page.discovering
|
||||||
|
text: "Choose a device"
|
||||||
|
anchors.bottom: listview.top
|
||||||
|
anchors.bottomMargin: Theme.paddingLarge
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
color: Theme.primaryColor
|
||||||
|
//font.pixelSize: Theme.fontSizeSmall
|
||||||
|
}
|
||||||
|
|
||||||
|
SilicaListView {
|
||||||
|
id: listview
|
||||||
|
spacing: Theme.paddingMedium
|
||||||
|
visible: true
|
||||||
|
anchors.centerIn: parent
|
||||||
|
anchors.margins: Theme.paddingSmall
|
||||||
|
height: contentHeight
|
||||||
|
width: parent.width
|
||||||
|
//anchors.fill: parent
|
||||||
|
//anchors.bottomMargin: button.height
|
||||||
|
clip: true
|
||||||
|
model: deviceModel
|
||||||
|
delegate: BackgroundItem {
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
color: Theme.highlightDimmerColor
|
||||||
|
}
|
||||||
|
property variant defVal: []
|
||||||
|
width: ListView.view.width
|
||||||
|
|
||||||
|
height: Theme.itemSizeExtraLarge
|
||||||
|
Image {
|
||||||
|
id: img
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: Theme.paddingLarge
|
||||||
|
height: Theme.itemSizeLarge
|
||||||
|
width: height
|
||||||
|
source: "http://"+ip+":"+port+icon
|
||||||
|
}
|
||||||
|
Item {
|
||||||
|
anchors.left: img.right
|
||||||
|
height: friendlyLabel.height + nameIp.height
|
||||||
|
anchors.leftMargin: Theme.paddingLarge
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
Label {
|
||||||
|
id: friendlyLabel
|
||||||
|
text: friendlyName
|
||||||
|
//color: Theme.highlightColor
|
||||||
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
id: nameIp
|
||||||
|
text: modelName + " ("+ip+")"
|
||||||
|
anchors.top: friendlyLabel.bottom
|
||||||
|
//color: Theme.highlightColor
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onClicked: {
|
||||||
|
console.log(" ********** http://"+ip+":"+port)
|
||||||
|
running = false
|
||||||
|
webPageAddress = "http://"+ip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BusyLabel {
|
||||||
|
//width: parent.width
|
||||||
|
text: "Searching for UPnP devices"
|
||||||
|
running: page.discovering
|
||||||
|
anchors.centerIn: parent
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
id: button
|
||||||
|
text: "Discover"
|
||||||
|
enabled: !page.discovering
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
width: parent.width
|
||||||
|
onClicked: {
|
||||||
|
deviceModel.clear()
|
||||||
|
python.startDownload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getIp(url) {
|
||||||
|
var res = url.split(":");
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkDevices() {
|
||||||
|
for (var i = 0; i < devices.length; i++) {
|
||||||
|
|
||||||
|
}
|
||||||
|
squeezeboxSettings.setValue("devices",devices)
|
||||||
|
}
|
||||||
|
|
||||||
|
Python {
|
||||||
|
id: python
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
addImportPath(Qt.resolvedUrl('.'));
|
||||||
|
|
||||||
|
setHandler('progress', function(ratio) {
|
||||||
|
|
||||||
|
devices.push(ratio)
|
||||||
|
});
|
||||||
|
setHandler('finished', function(newvalue) {
|
||||||
|
page.discovering = false;
|
||||||
|
button.text = "Discover";
|
||||||
|
if (retries<3 && devices.length === 0) {
|
||||||
|
retries = retries + 1
|
||||||
|
python.startDownload()
|
||||||
|
} else {
|
||||||
|
retries = 0
|
||||||
|
for (var i = 0; i < devices.length; i++) {
|
||||||
|
getXml(devices[i])
|
||||||
|
console.log(devices[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
importModule('upnpscan', function () {});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function startDownload() {
|
||||||
|
devices = []
|
||||||
|
page.discovering = true;
|
||||||
|
button.text = "Discovering";
|
||||||
|
call('upnpscan.discoverer.discover', function() {});
|
||||||
|
}
|
||||||
|
|
||||||
|
onError: {
|
||||||
|
console.log('python error: ' + traceback);
|
||||||
|
}
|
||||||
|
|
||||||
|
onReceived: {
|
||||||
|
console.log('got message from python: ' + data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
python.startDownload();
|
||||||
|
}
|
||||||
|
}
|
65
qml/pages/VolumIo.qml
Normal file
65
qml/pages/VolumIo.qml
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import QtQuick 2.0
|
||||||
|
import Sailfish.Silica 1.0
|
||||||
|
import Sailfish.WebView 1.0
|
||||||
|
|
||||||
|
WebViewPage {
|
||||||
|
id: webViewPage
|
||||||
|
allowedOrientations: Orientation.Portrait | Orientation.Landscape
|
||||||
|
|
||||||
|
property string webPageAddress: ""
|
||||||
|
property string webTitle: ""
|
||||||
|
property bool webViewLoading: false
|
||||||
|
property int webViewLoadProgress: 0
|
||||||
|
|
||||||
|
Splash {
|
||||||
|
id: splashItem
|
||||||
|
visible: running
|
||||||
|
}
|
||||||
|
|
||||||
|
WebView {
|
||||||
|
id: webView
|
||||||
|
visible: !splashItem.running
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
active: true
|
||||||
|
url: webPageAddress
|
||||||
|
|
||||||
|
onLoadingChanged: {
|
||||||
|
webViewPage.webViewLoading = loading
|
||||||
|
webViewPage.webViewLoadProgress = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
onLoadProgressChanged: {
|
||||||
|
webViewPage.webViewLoadProgress = loadProgress
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: panel
|
||||||
|
color: Theme.highlightDimmerColor
|
||||||
|
anchors {
|
||||||
|
bottom: parent.bottom
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
//margins: Theme.padding
|
||||||
|
}
|
||||||
|
width: parent.width
|
||||||
|
height: opacity === 0.0 ? 0 : Theme.paddingSmall / 3
|
||||||
|
radius: 5
|
||||||
|
|
||||||
|
opacity: (webViewPage.webViewLoading || loadStatusShowTimer.running) ? 0.75 : 0.0
|
||||||
|
Behavior on opacity { FadeAnimator {} }
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: loadStatusShowTimer
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
anchors.left: parent.left
|
||||||
|
color: Theme.secondaryHighlightColor
|
||||||
|
width: webViewPage.webViewLoading ? parent.width * (webViewPage.webViewLoadProgress / 100) : 0
|
||||||
|
height: parent.height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
50
qml/pages/upnpscan.py
Normal file
50
qml/pages/upnpscan.py
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import pyotherside
|
||||||
|
import threading
|
||||||
|
import socket
|
||||||
|
import re
|
||||||
|
|
||||||
|
# 'ST:urn:schemas-upnp-org:device:MediaRenderer:1',
|
||||||
|
|
||||||
|
|
||||||
|
def slow_function():
|
||||||
|
msg = "\r\n".join([
|
||||||
|
'M-SEARCH * HTTP/1.1',
|
||||||
|
'HOST:239.255.255.250:1900',
|
||||||
|
'MAN:"ssdp:discover"',
|
||||||
|
'ST:urn:schemas-upnp-org:device:MediaRenderer:1',
|
||||||
|
'MX:2',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
])
|
||||||
|
|
||||||
|
bytesmsg = msg.encode()
|
||||||
|
mr = "urn:schemas-upnp-org:device:MediaRenderer:1".encode()
|
||||||
|
# mr = ".".encode()
|
||||||
|
se = "(?P<url>https?://[^\s]+)".encode()
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
|
||||||
|
s.settimeout(3)
|
||||||
|
s.sendto(bytesmsg, ('239.255.255.250', 1900))
|
||||||
|
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
data = s.recvfrom(65507)
|
||||||
|
for line in data:
|
||||||
|
if mr in line:
|
||||||
|
url = re.search(se, line).group("url")
|
||||||
|
pyotherside.send('progress', url)
|
||||||
|
|
||||||
|
except socket.timeout:
|
||||||
|
pyotherside.send('finished', "DONE")
|
||||||
|
|
||||||
|
class Discoverer:
|
||||||
|
def __init__(self):
|
||||||
|
self.bgthread = threading.Thread()
|
||||||
|
self.bgthread.start()
|
||||||
|
|
||||||
|
def discover(self):
|
||||||
|
if self.bgthread.is_alive():
|
||||||
|
return
|
||||||
|
self.bgthread = threading.Thread(target=slow_function)
|
||||||
|
self.bgthread.start()
|
||||||
|
|
||||||
|
discoverer = Discoverer()
|
18
rpm/harbour-volumio.changes.in
Normal file
18
rpm/harbour-volumio.changes.in
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Rename this file as harbour-volumio.changes to include changelog
|
||||||
|
# entries in your RPM file.
|
||||||
|
#
|
||||||
|
# Add new changelog entries following the format below.
|
||||||
|
# Add newest entries to the top of the list.
|
||||||
|
# Separate entries from eachother with a blank line.
|
||||||
|
#
|
||||||
|
# Alternatively, if your changelog is automatically generated (e.g. with
|
||||||
|
# the git-change-log command provided with Sailfish OS SDK), create a
|
||||||
|
# harbour-volumio.changes.run script to let mb2 run the required commands for you.
|
||||||
|
|
||||||
|
# * date Author's Name <author's email> version-release
|
||||||
|
# - Summary of changes
|
||||||
|
|
||||||
|
* Sun Apr 13 2014 Jack Tar <jack.tar@example.com> 0.0.1-1
|
||||||
|
- Scrubbed the deck
|
||||||
|
- Hoisted the sails
|
||||||
|
|
24
rpm/harbour-volumio.changes.run.in
Normal file
24
rpm/harbour-volumio.changes.run.in
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Rename this file as harbour-volumio.changes.run to let sfdk automatically
|
||||||
|
# generate changelog from well formatted Git commit messages and tag
|
||||||
|
# annotations. Note that 'sfdk changelog' must be invoked as 'sfdk-changelog' here.
|
||||||
|
|
||||||
|
sfdk-changelog
|
||||||
|
|
||||||
|
# Here are some basic examples how to change from the default behavior. Run
|
||||||
|
# 'sfdk --help-maintaining' to learn more.
|
||||||
|
|
||||||
|
# Use a subset of tags
|
||||||
|
#sfdk-changelog --tags refs/tags/my-prefix/*
|
||||||
|
|
||||||
|
# Group entries by minor revision, suppress headlines for patch-level revisions
|
||||||
|
#sfdk-changelog --dense '/[0-9]+.[0-9+$'
|
||||||
|
|
||||||
|
# Trim very old changes
|
||||||
|
#sfdk-changelog --since 2014-04-01
|
||||||
|
#echo '[ Some changelog entries trimmed for brevity ]'
|
||||||
|
|
||||||
|
# Use the subjects (first lines) of tag annotations when no entry would be
|
||||||
|
# included for a revision otherwise
|
||||||
|
#sfdk-changelog --auto-add-annotations
|
42
rpm/harbour-volumio.spec
Normal file
42
rpm/harbour-volumio.spec
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
Name: harbour-volumio
|
||||||
|
|
||||||
|
Summary: VolumeIO
|
||||||
|
Version: 0.1
|
||||||
|
Release: 1
|
||||||
|
License: LICENSE
|
||||||
|
URL: http://example.org/
|
||||||
|
Source0: %{name}-%{version}.tar.bz2
|
||||||
|
Requires: sailfishsilica-qt5 >= 0.10.9
|
||||||
|
BuildRequires: pkgconfig(sailfishapp) >= 1.0.2
|
||||||
|
BuildRequires: pkgconfig(Qt5Core)
|
||||||
|
BuildRequires: pkgconfig(Qt5Qml)
|
||||||
|
BuildRequires: pkgconfig(Qt5Quick)
|
||||||
|
BuildRequires: desktop-file-utils
|
||||||
|
BuildRequires: pkgconfig(qt5embedwidget)
|
||||||
|
|
||||||
|
%description
|
||||||
|
Just a small restful app for Volumio
|
||||||
|
|
||||||
|
|
||||||
|
%prep
|
||||||
|
%setup -q -n %{name}-%{version}
|
||||||
|
|
||||||
|
%build
|
||||||
|
|
||||||
|
%qmake5
|
||||||
|
|
||||||
|
%make_build
|
||||||
|
|
||||||
|
|
||||||
|
%install
|
||||||
|
%qmake5_install
|
||||||
|
|
||||||
|
|
||||||
|
desktop-file-install --delete-original --dir %{buildroot}%{_datadir}/applications %{buildroot}%{_datadir}/applications/*.desktop
|
||||||
|
|
||||||
|
%files
|
||||||
|
%defattr(-,root,root,-)
|
||||||
|
%{_bindir}/%{name}
|
||||||
|
%{_datadir}/%{name}
|
||||||
|
%{_datadir}/applications/%{name}.desktop
|
||||||
|
%{_datadir}/icons/hicolor/*/apps/%{name}.png
|
20
src/harbour-volumio.cpp
Normal file
20
src/harbour-volumio.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifdef QT_QML_DEBUG
|
||||||
|
#include <QtQuick>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sailfishapp.h>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
// SailfishApp::main() will display "qml/harbour-volumio.qml", if you need more
|
||||||
|
// control over initialization, you can use:
|
||||||
|
//
|
||||||
|
// - SailfishApp::application(int, char *[]) to get the QGuiApplication *
|
||||||
|
// - SailfishApp::createView() to get a new QQuickView * instance
|
||||||
|
// - SailfishApp::pathTo(QString) to get a QUrl to a resource file
|
||||||
|
// - SailfishApp::pathToMainQml() to get a QUrl to the main QML file
|
||||||
|
//
|
||||||
|
// To display the view, call "show()" (will show fullscreen on device).
|
||||||
|
|
||||||
|
return SailfishApp::main(argc, argv);
|
||||||
|
}
|
11
translations/harbour-volumio-de.ts
Normal file
11
translations/harbour-volumio-de.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!DOCTYPE TS>
|
||||||
|
<TS version="2.1">
|
||||||
|
<context>
|
||||||
|
<name>CoverPage</name>
|
||||||
|
<message>
|
||||||
|
<source>My Cover</source>
|
||||||
|
<translation>Mein Cover</translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
|
</TS>
|
11
translations/harbour-volumio.ts
Normal file
11
translations/harbour-volumio.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!DOCTYPE TS>
|
||||||
|
<TS version="2.1">
|
||||||
|
<context>
|
||||||
|
<name>CoverPage</name>
|
||||||
|
<message>
|
||||||
|
<source>My Cover</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
|
</TS>
|
Loading…
x
Reference in New Issue
Block a user