diff options
Diffstat (limited to 'libre/clementine-libre/remove-and-disable-spotify.patch')
-rw-r--r-- | libre/clementine-libre/remove-and-disable-spotify.patch | 3268 |
1 files changed, 3268 insertions, 0 deletions
diff --git a/libre/clementine-libre/remove-and-disable-spotify.patch b/libre/clementine-libre/remove-and-disable-spotify.patch new file mode 100644 index 000000000..9cfc3092a --- /dev/null +++ b/libre/clementine-libre/remove-and-disable-spotify.patch @@ -0,0 +1,3268 @@ +diff -rauN clementine-1.0.1/3rdparty/SPMediaKeyTap/SPMediaKeyTap.m clementine-libre-1.0.1/3rdparty/SPMediaKeyTap/SPMediaKeyTap.m +--- clementine-1.0.1/3rdparty/SPMediaKeyTap/SPMediaKeyTap.m 2011-12-02 19:24:43.000000000 -0200 ++++ clementine-libre-1.0.1/3rdparty/SPMediaKeyTap/SPMediaKeyTap.m 2012-05-28 17:19:14.612750904 -0300 +@@ -98,7 +98,6 @@ + { + return [NSArray arrayWithObjects: + [[NSBundle mainBundle] bundleIdentifier], // your app +- @"com.spotify.client", + @"com.apple.iTunes", + @"com.apple.QuickTimePlayerX", + @"com.apple.quicktimeplayer", +diff -rauN clementine-1.0.1/Changelog clementine-libre-1.0.1/Changelog +--- clementine-1.0.1/Changelog 2012-01-22 10:43:26.000000000 -0200 ++++ clementine-libre-1.0.1/Changelog 2012-05-28 13:50:10.422664725 -0300 +@@ -1,3 +1,7 @@ ++Version 1.0.1 (libre version): ++ Major features: ++ * Disabled and removed Spotify. ++ + Version 1.0.1: + Bugfixes: + * Use Chromaprinter and Acoustid instead of Echoprint and MusicDNS. +diff -rauN clementine-1.0.1/cmake/SpotifyVersion.cmake /dev/null +--- clementine-1.0.1/cmake/SpotifyVersion.cmake 2011-12-02 19:24:43.000000000 -0200 ++++ /dev/null 2012-05-28 12:50:04.796939473 -0300 +@@ -1,3 +0,0 @@ +-# Increment this whenever the user needs to download a new blob +-# Remember to upload and sign the new version of the blob. +-set(SPOTIFY_BLOB_VERSION 11) +diff -rauN clementine-1.0.1/CMakeLists.txt clementine-libre-1.0.1/CMakeLists.txt +--- clementine-1.0.1/CMakeLists.txt 2012-01-22 10:43:26.000000000 -0200 ++++ clementine-libre-1.0.1/CMakeLists.txt 2012-05-28 17:32:48.690568781 -0300 +@@ -6,7 +6,6 @@ + include(cmake/Version.cmake) + include(cmake/Deb.cmake) + include(cmake/Rpm.cmake) +-include(cmake/SpotifyVersion.cmake) + include(cmake/OptionalSource.cmake) + + if (UNIX AND NOT APPLE) +@@ -66,7 +65,6 @@ + pkg_check_modules(USBMUXD libusbmuxd) + pkg_check_modules(LIBMTP libmtp>=1.0) + pkg_check_modules(INDICATEQT indicate-qt) +-pkg_check_modules(SPOTIFY libspotify>=10.1.16) + pkg_check_modules(CDIO libcdio) + pkg_check_modules(QCA qca2) + pkg_check_modules(CHROMAPRINT libchromaprint) +@@ -90,13 +88,6 @@ + set(HAVE_SPARKLE ON) + endif (ENABLE_SPARKLE AND SPARKLE) + +- find_library(SPOTIFY libspotify) +- if (SPOTIFY) +- set (SPOTIFY_FOUND ON) +- set (SPOTIFY_INCLUDE_DIRS ${SPOTIFY}) +- set (SPOTIFY_LIBRARIES ${SPOTIFY}) +- endif (SPOTIFY) +- + add_subdirectory(3rdparty/SPMediaKeyTap) + set(SPMEDIAKEYTAP_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/SPMediaKeyTap) + set(SPMEDIAKEYTAP_LIBRARIES SPMediaKeyTap) +@@ -191,8 +182,8 @@ + option(ENABLE_LIBLASTFM "Use liblastfm for fetching song info, scrobbling and radio streams" ON) + option(ENABLE_REMOTE "Enable support for using remote controls with Clementine" OFF) + option(ENABLE_BREAKPAD "Enable crash reporting" OFF) +-option(ENABLE_SPOTIFY_BLOB "Build the spotify non-GPL binary" ON) +-option(ENABLE_SPOTIFY "Enable spotify support" ON) ++option(ENABLE_SPOTIFY_BLOB "Build the spotify non-GPL binary" OFF) ++option(ENABLE_SPOTIFY "Enable spotify support" OFF) + option(ENABLE_PLASMARUNNER "Enable plasma krunner global search" OFF) + + if(WIN32) +@@ -235,24 +226,6 @@ + set(HAVE_BREAKPAD ON) + endif(ENABLE_BREAKPAD) + +-if(ENABLE_SPOTIFY AND PROTOBUF_FOUND AND PROTOBUF_PROTOC_EXECUTABLE) +- set(HAVE_SPOTIFY ON) +-endif(ENABLE_SPOTIFY AND PROTOBUF_FOUND AND PROTOBUF_PROTOC_EXECUTABLE) +- +-if(ENABLE_SPOTIFY_BLOB AND PROTOBUF_FOUND AND PROTOBUF_PROTOC_EXECUTABLE AND SPOTIFY_FOUND) +- set(HAVE_SPOTIFY_BLOB ON) +-endif(ENABLE_SPOTIFY_BLOB AND PROTOBUF_FOUND AND PROTOBUF_PROTOC_EXECUTABLE AND SPOTIFY_FOUND) +- +-if((NOT HAVE_SPOTIFY_BLOB) AND (NOT QCA_FOUND)) +- # If we're not bundling the spotify blob then we must ensure QCA is available +- # so we can verify the blob we download at runtime. +- unset(HAVE_SPOTIFY) +-endif((NOT HAVE_SPOTIFY_BLOB) AND (NOT QCA_FOUND)) +- +-if(QCA_FOUND AND HAVE_SPOTIFY) +- set(HAVE_QCA ON) +-endif(QCA_FOUND AND HAVE_SPOTIFY) +- + + if(ENABLE_VISUALISATIONS) + # When/if upstream accepts our patches then these options can be used to link +@@ -391,14 +364,6 @@ + add_subdirectory(3rdparty/google-breakpad) + endif(HAVE_BREAKPAD) + +-if(HAVE_SPOTIFY) +- add_subdirectory(spotifyblob/common) +-endif(HAVE_SPOTIFY) +- +-if(HAVE_SPOTIFY_BLOB) +- add_subdirectory(spotifyblob/blob) +-endif(HAVE_SPOTIFY_BLOB) +- + # This goes after everything else because KDE fucks everything else up with its + # cmake includes. + find_package(KDE4 4.3.60) +@@ -430,8 +395,6 @@ + summary_add("Devices: GIO backend" HAVE_GIO) + summary_add("Gnome sound menu integration" HAVE_LIBINDICATE) + summary_add("Last.fm support" HAVE_LIBLASTFM) +-summary_add("Spotify support: core code" HAVE_SPOTIFY) +-summary_add("Spotify support: non-GPL binary helper" HAVE_SPOTIFY_BLOB) + summary_add("Visualisations" ENABLE_VISUALISATIONS) + summary_add("Wiimote support" HAVE_WIIMOTEDEV) + summary_add("(KDE) Plasma global search" HAVE_PLASMARUNNER) +diff -rauN clementine-1.0.1/data/data.qrc clementine-libre-1.0.1/data/data.qrc +--- clementine-1.0.1/data/data.qrc 2012-01-22 10:43:26.000000000 -0200 ++++ clementine-libre-1.0.1/data/data.qrc 2012-05-28 17:50:22.768352061 -0300 +@@ -49,9 +49,6 @@ + <file>providers/magnatune.png</file> + <file>schema/schema-8.sql</file> + <file>schema/schema-9.sql</file> +- <file>icons/22x22/spotify.png</file> +- <file>icons/32x32/spotify.png</file> +- <file>icons/48x48/spotify.png</file> + <file>icons/22x22/application-exit.png</file> + <file>icons/22x22/applications-internet.png</file> + <file>icons/22x22/configure.png</file> +@@ -320,7 +317,6 @@ + <file>icons/32x32/edit-find.png</file> + <file>icons/48x48/edit-find.png</file> + <file>schema/schema-33.sql</file> +- <file>spotify-core-logo-128x128.png</file> + <file>icons/22x22/dialog-warning.png</file> + <file>icons/22x22/dialog-ok-apply.png</file> + <file>schema/schema-34.sql</file> +@@ -331,7 +327,6 @@ + <file>providers/grooveshark.png</file> + <file>allthethings.png</file> + <file>globalsearch.css</file> +- <file>clementine-spotify-public.pem</file> + <file>icons/22x22/user-away.png</file> + <file>icons/32x32/search.png</file> + <file>schema/schema-35.sql</file> +diff -rauN clementine-1.0.1/data/icons/svg/spotify.svg /dev/null +--- clementine-1.0.1/data/icons/svg/spotify.svg 2011-12-02 19:24:43.000000000 -0200 ++++ /dev/null 2012-05-28 12:50:04.796939473 -0300 +@@ -1,285 +0,0 @@ +-<?xml version="1.0" encoding="UTF-8" standalone="no"?> +-<!-- Created with Inkscape (http://www.inkscape.org/) --> +-<svg +- xmlns:dc="http://purl.org/dc/elements/1.1/" +- xmlns:cc="http://creativecommons.org/ns#" +- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" +- xmlns:svg="http://www.w3.org/2000/svg" +- xmlns="http://www.w3.org/2000/svg" +- xmlns:xlink="http://www.w3.org/1999/xlink" +- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" +- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" +- width="48" +- height="48" +- id="svg2" +- sodipodi:version="0.32" +- inkscape:version="0.46" +- version="1.0" +- sodipodi:docname="spotify.svg" +- inkscape:output_extension="org.inkscape.output.svg.inkscape"> +- <defs +- id="defs4"> +- <linearGradient +- inkscape:collect="always" +- id="linearGradient7729"> +- <stop +- style="stop-color:#467700;stop-opacity:1" +- offset="0" +- id="stop7731" /> +- <stop +- style="stop-color:#518900;stop-opacity:1" +- offset="1" +- id="stop7733" /> +- </linearGradient> +- <linearGradient +- inkscape:collect="always" +- id="linearGradient7721"> +- <stop +- style="stop-color:#1a4300;stop-opacity:1" +- offset="0" +- id="stop7723" /> +- <stop +- style="stop-color:#215300;stop-opacity:1" +- offset="1" +- id="stop7725" /> +- </linearGradient> +- <linearGradient +- inkscape:collect="always" +- id="linearGradient7713"> +- <stop +- style="stop-color:#193d00;stop-opacity:1" +- offset="0" +- id="stop7715" /> +- <stop +- style="stop-color:#1f4b00;stop-opacity:1" +- offset="1" +- id="stop7717" /> +- </linearGradient> +- <linearGradient +- inkscape:collect="always" +- id="linearGradient6355"> +- <stop +- style="stop-color:#23371c;stop-opacity:1" +- offset="0" +- id="stop6357" /> +- <stop +- style="stop-color:#004100;stop-opacity:1" +- offset="1" +- id="stop6359" /> +- </linearGradient> +- <linearGradient +- inkscape:collect="always" +- id="linearGradient6347"> +- <stop +- style="stop-color:#abd033;stop-opacity:1" +- offset="0" +- id="stop6349" /> +- <stop +- style="stop-color:#9ec02d;stop-opacity:0;" +- offset="1" +- id="stop6351" /> +- </linearGradient> +- <linearGradient +- id="linearGradient5519"> +- <stop +- style="stop-color:#88ae04;stop-opacity:1" +- offset="0" +- id="stop5521" /> +- <stop +- style="stop-color:#73a400;stop-opacity:1" +- offset="1" +- id="stop5523" /> +- </linearGradient> +- <inkscape:perspective +- sodipodi:type="inkscape:persp3d" +- inkscape:vp_x="0 : 526.18109 : 1" +- inkscape:vp_y="0 : 1000 : 0" +- inkscape:vp_z="744.09448 : 526.18109 : 1" +- inkscape:persp3d-origin="372.04724 : 350.78739 : 1" +- id="perspective10" /> +- <inkscape:perspective +- id="perspective5505" +- inkscape:persp3d-origin="372.04724 : 350.78739 : 1" +- inkscape:vp_z="744.09448 : 526.18109 : 1" +- inkscape:vp_y="0 : 1000 : 0" +- inkscape:vp_x="0 : 526.18109 : 1" +- sodipodi:type="inkscape:persp3d" /> +- <linearGradient +- inkscape:collect="always" +- xlink:href="#linearGradient5519" +- id="linearGradient6853" +- gradientUnits="userSpaceOnUse" +- x1="119.5" +- y1="91.362183" +- x2="102.5" +- y2="128.36218" /> +- <radialGradient +- inkscape:collect="always" +- xlink:href="#linearGradient6355" +- id="radialGradient6855" +- gradientUnits="userSpaceOnUse" +- gradientTransform="matrix(1.1318093,0.197699,-0.1703116,0.9750189,-125.44033,-100.50883)" +- cx="147.76869" +- cy="120.16964" +- fx="147.76869" +- fy="120.16964" +- r="14.451495" /> +- <linearGradient +- inkscape:collect="always" +- xlink:href="#linearGradient6347" +- id="linearGradient6857" +- gradientUnits="userSpaceOnUse" +- gradientTransform="translate(-125.45979,-77.491488)" +- x1="149.09062" +- y1="85.104187" +- x2="139.1649" +- y2="106.61218" /> +- <filter +- inkscape:collect="always" +- id="filter7655" +- x="-1.0712544" +- width="3.1425087" +- y="-1.0712544" +- height="3.1425087"> +- <feGaussianBlur +- inkscape:collect="always" +- stdDeviation="20.086019" +- id="feGaussianBlur7657" /> +- </filter> +- <linearGradient +- inkscape:collect="always" +- xlink:href="#linearGradient7713" +- id="linearGradient7719" +- x1="38.714096" +- y1="17.417631" +- x2="31.1127" +- y2="15.165503" +- gradientUnits="userSpaceOnUse" +- gradientTransform="matrix(0.999924,1.232938e-2,-1.232938e-2,0.999924,0.2587749,-0.2864042)" /> +- <linearGradient +- inkscape:collect="always" +- xlink:href="#linearGradient7721" +- id="linearGradient7727" +- x1="35.708893" +- y1="25.90625" +- x2="27.400389" +- y2="22.312458" +- gradientUnits="userSpaceOnUse" +- gradientTransform="matrix(0.965063,1.1899533e-2,-1.232938e-2,0.999924,1.1112913,-0.2758924)" /> +- <linearGradient +- inkscape:collect="always" +- xlink:href="#linearGradient7729" +- id="linearGradient7735" +- x1="35.607697" +- y1="31.414557" +- x2="23.13369" +- y2="26.433243" +- gradientUnits="userSpaceOnUse" +- gradientTransform="matrix(0.8596429,1.059967e-2,-1.232938e-2,0.999924,3.5039934,-0.2463897)" /> +- <filter +- inkscape:collect="always" +- id="filter7785" +- x="-0.089479765" +- width="1.1789595" +- y="-0.14834692" +- height="1.2966938"> +- <feGaussianBlur +- inkscape:collect="always" +- stdDeviation="1.5684595" +- id="feGaussianBlur7787" /> +- </filter> +- </defs> +- <sodipodi:namedview +- id="base" +- pagecolor="#ffffff" +- bordercolor="#666666" +- borderopacity="1.0" +- gridtolerance="10000" +- guidetolerance="10" +- objecttolerance="10" +- inkscape:pageopacity="0.0" +- inkscape:pageshadow="2" +- inkscape:zoom="5.6568542" +- inkscape:cx="-0.10040691" +- inkscape:cy="47.355194" +- inkscape:document-units="px" +- inkscape:current-layer="layer1" +- showgrid="false" +- inkscape:snap-bbox="true" +- inkscape:snap-nodes="false" +- inkscape:window-width="1440" +- inkscape:window-height="853" +- inkscape:window-x="0" +- inkscape:window-y="25"> +- <inkscape:grid +- type="xygrid" +- id="grid5511" +- visible="true" +- enabled="true" /> +- </sodipodi:namedview> +- <metadata +- id="metadata7"> +- <rdf:RDF> +- <cc:Work +- rdf:about=""> +- <dc:format>image/svg+xml</dc:format> +- <dc:type +- rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> +- </cc:Work> +- </rdf:RDF> +- </metadata> +- <g +- inkscape:label="Layer 1" +- inkscape:groupmode="layer" +- id="layer1"> +- <g +- id="g6847" +- transform="translate(-0.29021,-0.7456946)"> +- <path +- sodipodi:type="arc" +- style="opacity:0.64566926;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter7655);enable-background:accumulate" +- id="path6363" +- sodipodi:cx="112.5" +- sodipodi:cy="109.86218" +- sodipodi:rx="22.5" +- sodipodi:ry="22.5" +- d="M 135,109.86218 A 22.5,22.5 0 1 1 90,109.86218 A 22.5,22.5 0 1 1 135,109.86218 z" +- transform="matrix(0.4666666,0,0,0.111111,-28.709782,33.038802)" /> +- <path +- transform="translate(-88.70979,-85.616488)" +- d="M 135,109.86218 A 22.5,22.5 0 1 1 90,109.86218 A 22.5,22.5 0 1 1 135,109.86218 z" +- sodipodi:ry="22.5" +- sodipodi:rx="22.5" +- sodipodi:cy="109.86218" +- sodipodi:cx="112.5" +- id="path5513" +- style="opacity:1;fill:url(#linearGradient6853);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" +- sodipodi:type="arc" /> +- <path +- sodipodi:nodetypes="csccscc" +- id="path5529" +- d="M 7.6378996,39.420202 C 8.1682296,39.420202 11.29843,32.092852 23.23086,33.507062 C 35.16329,34.921272 36.54089,42.778952 36.54089,42.778952 C 34.49039,44.179572 32.3092,45.405922 29.55821,45.872552 C 29.55821,45.872552 26.55929,40.325532 21.1676,40.679082 C 15.77591,41.032632 13.91347,44.193172 13.91347,44.193172 C 11.14188,43.198092 8.9957096,41.593432 7.6378996,39.420202 z" +- style="fill:url(#radialGradient6855);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> +- <path +- sodipodi:nodetypes="cccc" +- id="path5531" +- d="M 2.6652096,29.120692 C 35.315841,10.631207 30.66521,27.370692 44.66521,26.495692 C 44.14296,15.562843 35.20292,3.7456934 23.66521,3.7456934 C 6.6997296,4.3119254 1.9479196,20.58416 2.6652096,29.120692 z" +- style="fill:url(#linearGradient6857);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter7785)" /> +- </g> +- <path +- style="opacity:1;fill:url(#linearGradient7719);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" +- d="M 10.300245,11.619555 C 8.241027,12.012805 7.9425774,15.355405 10.765465,15.313073 C 21.977063,13.20149 31.048724,15.49889 39.670046,19.826041 C 40.808245,20.378971 42.647611,18.028703 41.02047,16.758511 C 31.316836,11.614062 19.960975,9.8780472 10.300245,11.619555 z" +- id="path7661" +- sodipodi:nodetypes="ccccc" /> +- <path +- style="opacity:1;fill:url(#linearGradient7727);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" +- d="M 12.303532,19.144827 C 10.172718,19.381037 9.829391,22.969311 12.56196,22.64828 C 21.903655,21.50982 27.85363,22.62879 35.683323,25.808592 C 37.647192,26.873264 38.724998,23.482585 36.929338,22.604961 C 28.133565,18.889799 21.412131,18.726151 12.303532,19.144827 z" +- id="path7666" +- sodipodi:nodetypes="ccccc" /> +- <path +- style="opacity:1;fill:url(#linearGradient7735);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" +- d="M 14.447653,25.703011 C 12.75416,26.30833 13.053805,29.148649 14.863112,29.052139 C 17.870832,28.722372 20.153948,28.706138 23.615532,29.097554 C 27.126432,29.494545 29.233258,30.435974 32.157356,31.453048 C 33.350406,31.961876 34.447173,29.764482 33.187538,28.528027 C 29.966426,27.274723 27.415802,26.174879 23.388506,25.719498 C 20.084015,25.348048 17.755584,25.371512 14.447653,25.703011 z" +- id="path7668" +- sodipodi:nodetypes="ccscccc" /> +- </g> +-</svg> +diff -rauN clementine-1.0.1/data/schema/schema-30.sql clementine-libre-1.0.1/data/schema/schema-30.sql +--- clementine-1.0.1/data/schema/schema-30.sql 2011-12-02 19:24:43.000000000 -0200 ++++ clementine-libre-1.0.1/data/schema/schema-30.sql 2012-05-28 17:55:40.840489308 -0300 +@@ -1,45 +1 @@ +-CREATE TABLE spotify_search_songs ( +- title TEXT, +- album TEXT, +- artist TEXT, +- albumartist TEXT, +- composer TEXT, +- track INTEGER, +- disc INTEGER, +- bpm REAL, +- year INTEGER, +- genre TEXT, +- comment TEXT, +- compilation INTEGER, +- +- length INTEGER, +- bitrate INTEGER, +- samplerate INTEGER, +- +- directory INTEGER NOT NULL, +- filename TEXT NOT NULL, +- mtime INTEGER NOT NULL, +- ctime INTEGER NOT NULL, +- filesize INTEGER NOT NULL, +- sampler INTEGER NOT NULL DEFAULT 0, +- art_automatic TEXT, +- art_manual TEXT, +- filetype INTEGER NOT NULL DEFAULT 0, +- playcount INTEGER NOT NULL DEFAULT 0, +- lastplayed INTEGER, +- rating INTEGER, +- forced_compilation_on INTEGER NOT NULL DEFAULT 0, +- forced_compilation_off INTEGER NOT NULL DEFAULT 0, +- effective_compilation NOT NULL DEFAULT 0, +- skipcount INTEGER NOT NULL DEFAULT 0, +- score INTEGER NOT NULL DEFAULT 0, +- beginning INTEGER NOT NULL DEFAULT 0, +- cue_path TEXT +-); +- +-CREATE VIRTUAL TABLE spotify_search_songs_fts USING fts3 ( +- ftstitle, ftsalbum, ftsartist, ftsalbumartist, ftscomposer, ftsgenre, ftscomment, +- tokenize=unicode +-); +- + UPDATE schema_version SET version=30; +diff -rauN clementine-1.0.1/dist/macdeploy.py clementine-libre-1.0.1/dist/macdeploy.py +--- clementine-1.0.1/dist/macdeploy.py 2012-01-22 10:43:26.000000000 -0200 ++++ clementine-libre-1.0.1/dist/macdeploy.py 2012-05-28 17:58:29.937662793 -0300 +@@ -367,11 +367,6 @@ + + FixPlugin(FindGstreamerPlugin('gst-plugin-scanner'), '.') + +-try: +- FixPlugin('clementine-spotifyblob', '.') +-except: +- print 'Failed to find spotify blob' +- + for plugin in QT_PLUGINS: + FixPlugin(FindQtPlugin(plugin), os.path.dirname(plugin)) + +diff -rauN clementine-1.0.1/dist/windows/clementine.nsi clementine-libre-1.0.1/dist/windows/clementine.nsi +--- clementine-1.0.1/dist/windows/clementine.nsi 2012-01-22 10:43:46.000000000 -0200 ++++ clementine-libre-1.0.1/dist/windows/clementine.nsi 2012-05-28 18:06:56.812551755 -0300 +@@ -95,7 +95,6 @@ + Delete "$INSTDIR\gstreamer-plugins\libgstsoup.dll" + + ; 1.0 prerelease +- Delete "$INSTDIR\spotify.dll" + + ; 1.0 + Delete "$INSTDIR\libofa.dll" +@@ -109,7 +108,6 @@ + File "avformat-52.dll" + File "avutil-50.dll" + File "clementine.exe" +- File "clementine-spotifyblob.exe" + File "clementine.ico" + File "glew32.dll" + File "intl.dll" +@@ -163,7 +161,6 @@ + File "libqjson.dll" + File "libsoup-2.4-1.dll" + File "libspeex-1.dll" +- File "libspotify.dll" + File "libtag.dll" + File "libtasn1-3.dll" + File "libusbmuxd.dll" +@@ -949,7 +946,6 @@ + Delete "$INSTDIR\avutil-50.dll" + Delete "$INSTDIR\clementine.ico" + Delete "$INSTDIR\clementine.exe" +- Delete "$INSTDIR\clementine-spotifyblob.exe" + Delete "$INSTDIR\glew32.dll" + Delete "$INSTDIR\intl.dll" + Delete "$INSTDIR\libcdio-12.dll" +@@ -1002,7 +998,6 @@ + Delete "$INSTDIR\libqjson.dll" + Delete "$INSTDIR\libsoup-2.4-1.dll" + Delete "$INSTDIR\libspeex-1.dll" +- Delete "$INSTDIR\libspotify.dll" + Delete "$INSTDIR\libtag.dll" + Delete "$INSTDIR\libtasn1-3.dll" + Delete "$INSTDIR\libusbmuxd.dll" +diff -rauN clementine-1.0.1/dist/windows/clementine.nsi.in clementine-libre-1.0.1/dist/windows/clementine.nsi.in +--- clementine-1.0.1/dist/windows/clementine.nsi.in 2012-01-22 10:43:26.000000000 -0200 ++++ clementine-libre-1.0.1/dist/windows/clementine.nsi.in 2012-05-28 18:09:14.664818947 -0300 +@@ -95,7 +95,6 @@ + Delete "$INSTDIR\gstreamer-plugins\libgstsoup.dll" + + ; 1.0 prerelease +- Delete "$INSTDIR\spotify.dll" + + ; 1.0 + Delete "$INSTDIR\libofa.dll" +@@ -109,7 +108,6 @@ + File "avformat-52.dll" + File "avutil-50.dll" + File "clementine.exe" +- File "clementine-spotifyblob.exe" + File "clementine.ico" + File "glew32.dll" + File "intl.dll" +@@ -163,7 +161,6 @@ + File "libqjson.dll" + File "libsoup-2.4-1.dll" + File "libspeex-1.dll" +- File "libspotify.dll" + File "libtag.dll" + File "libtasn1-3.dll" + File "libusbmuxd.dll" +@@ -949,7 +946,6 @@ + Delete "$INSTDIR\avutil-50.dll" + Delete "$INSTDIR\clementine.ico" + Delete "$INSTDIR\clementine.exe" +- Delete "$INSTDIR\clementine-spotifyblob.exe" + Delete "$INSTDIR\glew32.dll" + Delete "$INSTDIR\intl.dll" + Delete "$INSTDIR\libcdio-12.dll" +@@ -1002,7 +998,6 @@ + Delete "$INSTDIR\libqjson.dll" + Delete "$INSTDIR\libsoup-2.4-1.dll" + Delete "$INSTDIR\libspeex-1.dll" +- Delete "$INSTDIR\libspotify.dll" + Delete "$INSTDIR\libtag.dll" + Delete "$INSTDIR\libtasn1-3.dll" + Delete "$INSTDIR\libusbmuxd.dll" +diff -rauN clementine-1.0.1/src/CMakeLists.txt clementine-libre-1.0.1/src/CMakeLists.txt +--- clementine-1.0.1/src/CMakeLists.txt 2012-01-22 10:43:26.000000000 -0200 ++++ clementine-libre-1.0.1/src/CMakeLists.txt 2012-05-30 02:50:15.725755468 -0300 +@@ -552,7 +552,6 @@ + internet/internetviewcontainer.ui + internet/magnatunedownloaddialog.ui + internet/magnatunesettingspage.ui +- internet/spotifysettingspage.ui + + library/groupbydialog.ui + library/libraryfilterwidget.ui +@@ -690,23 +689,6 @@ + internet/lastfmstationdialog.ui + ) + +-# Spotify +-optional_source(HAVE_SPOTIFY +- SOURCES +- globalsearch/spotifysearchprovider.cpp +- internet/spotifyblobdownloader.cpp +- internet/spotifysearchplaylisttype.cpp +- internet/spotifyserver.cpp +- internet/spotifyservice.cpp +- internet/spotifysettingspage.cpp +- HEADERS +- globalsearch/spotifysearchprovider.h +- internet/spotifyblobdownloader.h +- internet/spotifyserver.h +- internet/spotifyservice.h +- internet/spotifysettingspage.h +-) +- + optional_source(HAVE_QCA INCLUDE_DIRECTORIES ${QCA_INCLUDE_DIRS}) + + # Platform specific - OS X +@@ -1037,14 +1019,6 @@ + endif (LINUX) + endif(HAVE_BREAKPAD) + +-if(HAVE_SPOTIFY) +- target_link_libraries(clementine_lib +- clementine-spotifyblob-messages +- ${QCA_LIBRARIES} +- ) +- link_directories(${QCA_LIBRARY_DIRS}) +-endif(HAVE_SPOTIFY) +- + if (APPLE) + target_link_libraries(clementine_lib + ${GROWL} +@@ -1118,11 +1092,6 @@ + clementine_lib + ) + +-# macdeploy.py relies on the blob being built first. +-if(HAVE_SPOTIFY_BLOB) +- add_dependencies(clementine clementine-spotifyblob) +-endif(HAVE_SPOTIFY_BLOB) +- + set_target_properties(clementine PROPERTIES + MACOSX_BUNDLE_INFO_PLIST "../dist/Info.plist" + ) +diff -rauN clementine-1.0.1/src/config.h.in clementine-libre-1.0.1/src/config.h.in +--- clementine-1.0.1/src/config.h.in 2011-12-02 19:24:43.000000000 -0200 ++++ clementine-libre-1.0.1/src/config.h.in 2012-05-28 18:17:13.027993639 -0300 +@@ -35,7 +35,6 @@ + #cmakedefine HAVE_QCA + #cmakedefine HAVE_REMOTE + #cmakedefine HAVE_SPARKLE +-#cmakedefine HAVE_SPOTIFY + #cmakedefine HAVE_STATIC_SQLITE + #cmakedefine HAVE_WIIMOTEDEV + #cmakedefine LEOPARD +diff -rauN clementine-1.0.1/src/core/utilities.cpp clementine-libre-1.0.1/src/core/utilities.cpp +--- clementine-1.0.1/src/core/utilities.cpp 2012-01-22 10:43:26.000000000 -0200 ++++ clementine-libre-1.0.1/src/core/utilities.cpp 2012-05-28 18:25:43.252728803 -0300 +@@ -277,9 +277,6 @@ + return QDir::homePath(); + #endif + +- case Path_LocalSpotifyBlob: +- return GetConfigPath(Path_Root) + "/spotifyblob"; +- + default: + qFatal("%s", Q_FUNC_INFO); + return QString::null; +diff -rauN clementine-1.0.1/src/core/utilities.h clementine-libre-1.0.1/src/core/utilities.h +--- clementine-1.0.1/src/core/utilities.h 2012-01-22 10:43:26.000000000 -0200 ++++ clementine-libre-1.0.1/src/core/utilities.h 2012-05-28 18:27:31.686659381 -0300 +@@ -88,7 +88,6 @@ + Path_NetworkCache, + Path_GstreamerRegistry, + Path_DefaultMusicLibrary, +- Path_LocalSpotifyBlob, + }; + QString GetConfigPath(ConfigPath config); + +diff -rauN clementine-1.0.1/src/covers/albumcoverloader.cpp clementine-libre-1.0.1/src/covers/albumcoverloader.cpp +--- clementine-1.0.1/src/covers/albumcoverloader.cpp 2011-12-02 19:24:44.000000000 -0200 ++++ clementine-libre-1.0.1/src/covers/albumcoverloader.cpp 2012-05-28 18:34:26.543457483 -0300 +@@ -28,10 +28,6 @@ + #include <QUrl> + #include <QNetworkReply> + +-#ifdef HAVE_SPOTIFY +-# include "internet/spotifyservice.h" +-#endif +- + + AlbumCoverLoader::AlbumCoverLoader(QObject* parent) + : QObject(parent), +@@ -40,8 +36,7 @@ + scale_(true), + padding_(true), + next_id_(0), +- network_(new NetworkAccessManager(this)), +- connected_spotify_(false) ++ network_(new NetworkAccessManager(this)) + { + } + +@@ -148,46 +143,12 @@ + + remote_tasks_.insert(reply, task); + return TryLoadResult(true, false, QImage()); +- } else if (filename.toLower().startsWith("spotify://image/")) { +- // HACK: we should add generic image URL handlers +- #ifdef HAVE_SPOTIFY +- SpotifyService* spotify = InternetModel::Service<SpotifyService>(); +- +- if (!connected_spotify_) { +- connect(spotify, SIGNAL(ImageLoaded(QString,QImage)), +- SLOT(SpotifyImageLoaded(QString,QImage))); +- connected_spotify_ = true; +- } +- +- QString id = QUrl(filename).path(); +- if (id.startsWith('/')) { +- id.remove(0, 1); +- } +- remote_spotify_tasks_.insert(id, task); +- +- // Need to schedule this in the spotify service's thread +- QMetaObject::invokeMethod(spotify, "LoadImage", Qt::QueuedConnection, +- Q_ARG(QString, id)); +- return TryLoadResult(true, false, QImage()); +- #else +- return TryLoadResult(false, false, QImage()); +- #endif + } + + QImage image(filename); + return TryLoadResult(false, !image.isNull(), image.isNull() ? default_ : image); + } + +-void AlbumCoverLoader::SpotifyImageLoaded(const QString& id, const QImage& image) { +- if (!remote_spotify_tasks_.contains(id)) +- return; +- +- Task task = remote_spotify_tasks_.take(id); +- QImage scaled = ScaleAndPad(image); +- emit ImageLoaded(task.id, scaled); +- emit ImageLoaded(task.id, scaled, image); +-} +- + void AlbumCoverLoader::RemoteFetchFinished() { + QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender()); + if (!reply) +diff -rauN clementine-1.0.1/src/covers/albumcoverloader.h clementine-libre-1.0.1/src/covers/albumcoverloader.h +--- clementine-1.0.1/src/covers/albumcoverloader.h 2011-12-02 19:24:44.000000000 -0200 ++++ clementine-libre-1.0.1/src/covers/albumcoverloader.h 2012-05-28 18:38:03.228006474 -0300 +@@ -65,7 +65,6 @@ + protected slots: + void ProcessTasks(); + void RemoteFetchFinished(); +- void SpotifyImageLoaded(const QString& url, const QImage& image); + + protected: + enum State { +@@ -108,13 +107,10 @@ + QMutex mutex_; + QQueue<Task> tasks_; + QMap<QNetworkReply*, Task> remote_tasks_; +- QMap<QString, Task> remote_spotify_tasks_; + quint64 next_id_; + + NetworkAccessManager* network_; + +- bool connected_spotify_; +- + static const int kMaxRedirects = 3; + }; + +diff -rauN clementine-1.0.1/src/engines/gstenginepipeline.cpp clementine-libre-1.0.1/src/engines/gstenginepipeline.cpp +--- clementine-1.0.1/src/engines/gstenginepipeline.cpp 2011-12-02 19:24:44.000000000 -0200 ++++ clementine-libre-1.0.1/src/engines/gstenginepipeline.cpp 2012-05-28 18:51:35.779395089 -0300 +@@ -26,11 +26,6 @@ + #include "core/utilities.h" + #include "internet/internetmodel.h" + +-#ifdef HAVE_SPOTIFY +-# include "internet/spotifyserver.h" +-# include "internet/spotifyservice.h" +-#endif +- + #include <QtConcurrentRun> + + const int GstEnginePipeline::kGstStateTimeoutNanosecs = 10000000; +@@ -131,36 +126,6 @@ + bool GstEnginePipeline::ReplaceDecodeBin(const QUrl& url) { + GstElement* new_bin = NULL; + +- if (url.scheme() == "spotify") { +- #ifdef HAVE_SPOTIFY +- new_bin = gst_bin_new("spotify_bin"); +- +- // Create elements +- GstElement* src = engine_->CreateElement("tcpserversrc", new_bin); +- GstElement* gdp = engine_->CreateElement("gdpdepay", new_bin); +- if (!src || !gdp) +- return false; +- +- // Pick a port number +- const int port = Utilities::PickUnusedPort(); +- g_object_set(G_OBJECT(src), "host", "127.0.0.1", NULL); +- g_object_set(G_OBJECT(src), "port", port, NULL); +- +- // Link the elements +- gst_element_link(src, gdp); +- +- // Add a ghost pad +- GstPad* pad = gst_element_get_static_pad(gdp, "src"); +- gst_element_add_pad(GST_ELEMENT(new_bin), gst_ghost_pad_new("src", pad)); +- gst_object_unref(GST_OBJECT(pad)); +- +- // Tell spotify to start sending data to us. +- InternetModel::Service<SpotifyService>()->server()->StartPlaybackLater(url.toString(), port); +- #else // HAVE_SPOTIFY +- qLog(Error) << "Tried to play a spotify:// url, but spotify support is not compiled in"; +- return false; +- #endif +- } else { + new_bin = engine_->CreateElement("uridecodebin"); + g_object_set(G_OBJECT(new_bin), "uri", url.toEncoded().constData(), NULL); + g_object_set(G_OBJECT(new_bin), "buffer-duration", buffer_duration_nanosec_, NULL); +@@ -169,7 +134,6 @@ + g_signal_connect(G_OBJECT(new_bin), "drained", G_CALLBACK(SourceDrainedCallback), this); + g_signal_connect(G_OBJECT(new_bin), "pad-added", G_CALLBACK(NewPadCallback), this); + g_signal_connect(G_OBJECT(new_bin), "notify::source", G_CALLBACK(SourceSetupCallback), this); +- } + + return ReplaceDecodeBin(new_bin); + } +diff -rauN clementine-1.0.1/src/globalsearch/spotifysearchprovider.cpp /dev/null +--- clementine-1.0.1/src/globalsearch/spotifysearchprovider.cpp 2011-12-02 19:24:44.000000000 -0200 ++++ /dev/null 2012-05-28 12:50:04.796939473 -0300 +@@ -1,208 +0,0 @@ +-/* This file is part of Clementine. +- Copyright 2010, David Sansome <me@davidsansome.com> +- +- Clementine 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 3 of the License, or +- (at your option) any later version. +- +- Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>. +-*/ +- +-#include "spotifysearchprovider.h" +-#include "core/logging.h" +-#include "internet/internetmodel.h" +-#include "internet/spotifyserver.h" +-#include "internet/spotifyservice.h" +-#include "playlist/songmimedata.h" +-#include "spotifyblob/common/spotifymessagehandler.h" +- +-SpotifySearchProvider::SpotifySearchProvider(QObject* parent) +- : SearchProvider(parent), +- server_(NULL), +- service_(NULL) +-{ +- Init("Spotify", "spotify", QIcon(":icons/32x32/spotify.png"), +- WantsDelayedQueries | WantsSerialisedArtQueries | ArtIsProbablyRemote | +- CanShowConfig); +-} +- +-SpotifyServer* SpotifySearchProvider::server() { +- if (server_) +- return server_; +- +- if (!service_) +- service_ = InternetModel::Service<SpotifyService>(); +- +- if (service_->login_state() != SpotifyService::LoginState_LoggedIn) +- return NULL; +- +- server_ = service_->server(); +- connect(server_, SIGNAL(SearchResults(spotify_pb::SearchResponse)), +- SLOT(SearchFinishedSlot(spotify_pb::SearchResponse))); +- connect(server_, SIGNAL(ImageLoaded(QString,QImage)), +- SLOT(ArtLoadedSlot(QString,QImage))); +- connect(server_, SIGNAL(AlbumBrowseResults(spotify_pb::BrowseAlbumResponse)), +- SLOT(AlbumBrowseResponse(spotify_pb::BrowseAlbumResponse))); +- connect(server_, SIGNAL(destroyed()), SLOT(ServerDestroyed())); +- +- return server_; +-} +- +-void SpotifySearchProvider::ServerDestroyed() { +- server_ = NULL; +-} +- +-void SpotifySearchProvider::SearchAsync(int id, const QString& query) { +- SpotifyServer* s = server(); +- if (!s) { +- emit SearchFinished(id); +- return; +- } +- +- PendingState state; +- state.orig_id_ = id; +- state.tokens_ = TokenizeQuery(query); +- +- const QString query_string = state.tokens_.join(" "); +- s->Search(query_string, 5, 5); +- queries_[query_string] = state; +-} +- +-void SpotifySearchProvider::SearchFinishedSlot(const spotify_pb::SearchResponse& response) { +- QString query_string = QString::fromUtf8(response.request().query().c_str()); +- QMap<QString, PendingState>::iterator it = queries_.find(query_string); +- if (it == queries_.end()) +- return; +- +- PendingState state = it.value(); +- queries_.erase(it); +- +- ResultList ret; +- for (int i=0; i < response.result_size() ; ++i) { +- const spotify_pb::Track& track = response.result(i); +- +- Result result(this); +- result.type_ = globalsearch::Type_Track; +- SpotifyService::SongFromProtobuf(track, &result.metadata_); +- result.match_quality_ = MatchQuality(state.tokens_, result.metadata_.title()); +- +- ret << result; +- } +- +- for (int i=0 ; i<response.album_size() ; ++i) { +- const spotify_pb::Album& album = response.album(i); +- +- Result result(this); +- result.type_ = globalsearch::Type_Album; +- SpotifyService::SongFromProtobuf(album.metadata(), &result.metadata_); +- result.match_quality_ = +- qMin(MatchQuality(state.tokens_, result.metadata_.album()), +- MatchQuality(state.tokens_, result.metadata_.artist())); +- result.album_size_ = album.metadata().track(); +- +- for (int j=0; j < album.track_size() ; ++j) { +- Song track_song; +- SpotifyService::SongFromProtobuf(album.track(j), &track_song); +- result.album_songs_ << track_song; +- } +- +- ret << result; +- } +- +- emit ResultsAvailable(state.orig_id_, ret); +- emit SearchFinished(state.orig_id_); +-} +- +-void SpotifySearchProvider::LoadArtAsync(int id, const Result& result) { +- SpotifyServer* s = server(); +- if (!s) { +- emit ArtLoaded(id, QImage()); +- return; +- } +- +- QString image_id = QUrl(result.metadata_.art_automatic()).path(); +- if (image_id.startsWith('/')) +- image_id.remove(0, 1); +- +- pending_art_[image_id] = id; +- s->LoadImage(image_id); +-} +- +-void SpotifySearchProvider::ArtLoadedSlot(const QString& id, const QImage& image) { +- QMap<QString, int>::iterator it = pending_art_.find(id); +- if (it == pending_art_.end()) +- return; +- +- const int orig_id = it.value(); +- pending_art_.erase(it); +- +- emit ArtLoaded(orig_id, ScaleAndPad(image)); +-} +- +-void SpotifySearchProvider::LoadTracksAsync(int id, const Result& result) { +- switch (result.type_) { +- case globalsearch::Type_Track: { +- SongMimeData* mime_data = new SongMimeData; +- mime_data->songs = SongList() << result.metadata_; +- emit TracksLoaded(id, mime_data); +- break; +- } +- +- case globalsearch::Type_Album: { +- SpotifyServer* s = server(); +- if (!s) { +- emit TracksLoaded(id, NULL); +- return; +- } +- +- QString uri = result.metadata_.url().toString(); +- +- pending_tracks_[uri] = id; +- s->AlbumBrowse(uri); +- break; +- } +- +- default: +- break; +- } +-} +- +-void SpotifySearchProvider::AlbumBrowseResponse(const spotify_pb::BrowseAlbumResponse& response) { +- QString uri = QStringFromStdString(response.uri()); +- QMap<QString, int>::iterator it = pending_tracks_.find(uri); +- if (it == pending_tracks_.end()) +- return; +- +- const int orig_id = it.value(); +- pending_tracks_.erase(it); +- +- SongMimeData* mime_data = new SongMimeData; +- +- for (int i=0 ; i<response.track_size() ; ++i) { +- Song song; +- SpotifyService::SongFromProtobuf(response.track(i), &song); +- mime_data->songs << song; +- } +- +- emit TracksLoaded(orig_id, mime_data); +-} +- +-bool SpotifySearchProvider::IsLoggedIn() { +- if (server()) { +- return service_->IsLoggedIn(); +- } +- return false; +-} +- +-void SpotifySearchProvider::ShowConfig() { +- if (service_) { +- return service_->ShowConfig(); +- } +-} +diff -rauN clementine-1.0.1/src/globalsearch/spotifysearchprovider.h /dev/null +--- clementine-1.0.1/src/globalsearch/spotifysearchprovider.h 2011-12-02 19:24:44.000000000 -0200 ++++ /dev/null 2012-05-28 12:50:04.796939473 -0300 +@@ -1,60 +0,0 @@ +-/* This file is part of Clementine. +- Copyright 2010, David Sansome <me@davidsansome.com> +- +- Clementine 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 3 of the License, or +- (at your option) any later version. +- +- Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>. +-*/ +- +-#ifndef SPOTIFYSEARCHPROVIDER_H +-#define SPOTIFYSEARCHPROVIDER_H +- +-#include "searchprovider.h" +-#include "spotifyblob/common/spotifymessages.pb.h" +- +-class SpotifyServer; +-class SpotifyService; +- +- +-class SpotifySearchProvider : public SearchProvider { +- Q_OBJECT +- +-public: +- SpotifySearchProvider(QObject* parent = 0); +- +- void SearchAsync(int id, const QString& query); +- void LoadArtAsync(int id, const Result& result); +- void LoadTracksAsync(int id, const Result& result); +- +- bool IsLoggedIn(); +- void ShowConfig(); +- +-private slots: +- void ServerDestroyed(); +- void SearchFinishedSlot(const spotify_pb::SearchResponse& response); +- void ArtLoadedSlot(const QString& id, const QImage& image); +- +- void AlbumBrowseResponse(const spotify_pb::BrowseAlbumResponse& response); +- +-private: +- SpotifyServer* server(); +- +-private: +- SpotifyServer* server_; +- SpotifyService* service_; +- +- QMap<QString, PendingState> queries_; +- QMap<QString, int> pending_art_; +- QMap<QString, int> pending_tracks_; +-}; +- +-#endif // SPOTIFYSEARCHPROVIDER_H +diff -rauN clementine-1.0.1/src/internet/internetmodel.cpp clementine-libre-1.0.1/src/internet/internetmodel.cpp +--- clementine-1.0.1/src/internet/internetmodel.cpp 2011-12-02 19:24:44.000000000 -0200 ++++ clementine-libre-1.0.1/src/internet/internetmodel.cpp 2012-05-28 18:56:58.934758916 -0300 +@@ -32,9 +32,6 @@ + #ifdef HAVE_LIBLASTFM + #include "lastfmservice.h" + #endif +-#ifdef HAVE_SPOTIFY +- #include "spotifyservice.h" +-#endif + + #include <QMimeData> + #include <QtDebug> +@@ -75,9 +72,6 @@ + AddService(new SavedRadio(this)); + AddService(new SkyFmService(this)); + AddService(new SomaFMService(this)); +-#ifdef HAVE_SPOTIFY +- AddService(new SpotifyService(this)); +-#endif + } + + void InternetModel::AddService(InternetService *service) { +diff -rauN clementine-1.0.1/src/internet/spotifyblobdownloader.cpp /dev/null +--- clementine-1.0.1/src/internet/spotifyblobdownloader.cpp 2011-12-02 19:24:44.000000000 -0200 ++++ /dev/null 2012-05-28 12:50:04.796939473 -0300 +@@ -1,222 +0,0 @@ +-/* This file is part of Clementine. +- Copyright 2010, David Sansome <me@davidsansome.com> +- +- Clementine 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 3 of the License, or +- (at your option) any later version. +- +- Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>. +-*/ +- +-#include "config.h" +-#include "spotifyblobdownloader.h" +-#include "spotifyservice.h" +-#include "core/logging.h" +-#include "core/network.h" +-#include "core/utilities.h" +- +-#include <QDir> +-#include <QMessageBox> +-#include <QNetworkReply> +-#include <QProgressDialog> +- +-#ifdef HAVE_QCA +- #include <QtCrypto> +-#endif // HAVE_QCA +- +-const char* SpotifyBlobDownloader::kSignatureSuffix = ".sha1"; +- +- +-SpotifyBlobDownloader::SpotifyBlobDownloader( +- const QString& version, const QString& path, QObject* parent) +- : QObject(parent), +- version_(version), +- path_(path), +- network_(new NetworkAccessManager(this)), +- progress_(new QProgressDialog(tr("Downloading Spotify plugin"), tr("Cancel"), 0, 0)) +-{ +- progress_->setWindowTitle(QCoreApplication::applicationName()); +- connect(progress_, SIGNAL(canceled()), SLOT(Cancel())); +-} +- +-SpotifyBlobDownloader::~SpotifyBlobDownloader() { +- qDeleteAll(replies_); +- replies_.clear(); +- +- delete progress_; +-} +- +-bool SpotifyBlobDownloader::Prompt() { +- QMessageBox::StandardButton ret = QMessageBox::question(NULL, +- tr("Spotify plugin not installed"), +- tr("An additional plugin is required to use Spotify in Clementine. Would you like to download and install it now?"), +- QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); +- return ret == QMessageBox::Yes; +-} +- +-void SpotifyBlobDownloader::Start() { +- qDeleteAll(replies_); +- replies_.clear(); +- +- const QStringList filenames = QStringList() +- << "blob" +- << "blob" + QString(kSignatureSuffix) +- << "libspotify.so.10.1.16" +- << "libspotify.so.10.1.16" + QString(kSignatureSuffix); +- +- foreach (const QString& filename, filenames) { +- const QUrl url(SpotifyService::kBlobDownloadUrl + version_ + "/" + filename); +- qLog(Info) << "Downloading" << url; +- +- QNetworkReply* reply = network_->get(QNetworkRequest(url)); +- connect(reply, SIGNAL(finished()), SLOT(ReplyFinished())); +- connect(reply, SIGNAL(downloadProgress(qint64,qint64)), SLOT(ReplyProgress())); +- +- replies_ << reply; +- } +- +- progress_->show(); +-} +- +-void SpotifyBlobDownloader::ReplyFinished() { +- QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender()); +- if (reply->error() != QNetworkReply::NoError) { +- // Handle network errors +- ShowError(reply->errorString()); +- return; +- } +- +- // Is everything finished? +- foreach (QNetworkReply* reply, replies_) { +- if (!reply->isFinished()) { +- return; +- } +- } +- +- // Read files into memory first. +- QMap<QString, QByteArray> file_data; +- QStringList signature_filenames; +- +- foreach (QNetworkReply* reply, replies_) { +- const QString filename = reply->url().path().section('/', -1, -1); +- +- if (filename.endsWith(kSignatureSuffix)) { +- signature_filenames << filename; +- } +- +- file_data[filename] = reply->readAll(); +- } +- +-#ifdef HAVE_QCA +- // Load the public key +- QCA::ConvertResult conversion_result; +- QCA::PublicKey key = QCA::PublicKey::fromPEMFile(":/clementine-spotify-public.pem", +- &conversion_result); +- if (QCA::ConvertGood != conversion_result) { +- ShowError("Failed to load Spotify public key"); +- return; +- } +- +- // Verify signatures +- foreach (const QString& signature_filename, signature_filenames) { +- QString actual_filename = signature_filename; +- actual_filename.remove(kSignatureSuffix); +- +- qLog(Debug) << "Verifying" << actual_filename << "against" << signature_filename; +- +- if (!key.verifyMessage(file_data[actual_filename], +- file_data[signature_filename], +- QCA::EMSA3_SHA1)) { +- ShowError("Invalid signature: " + actual_filename); +- return; +- } +- } +-#endif // HAVE_QCA +- +- // Make the destination directory and write the files into it +- QDir().mkpath(path_); +- +- foreach (const QString& filename, file_data.keys()) { +- const QString dest_path = path_ + "/" + filename; +- +- if (filename.endsWith(kSignatureSuffix)) +- continue; +- +- qLog(Info) << "Writing" << dest_path; +- +- QFile file(dest_path); +- if (!file.open(QIODevice::WriteOnly)) { +- ShowError("Failed to open " + dest_path + " for writing"); +- return; +- } +- +- file.write(file_data[filename]); +- file.close(); +- file.setPermissions(QFile::Permissions(0x7755)); +- +-#ifdef Q_OS_UNIX +- const int so_pos = filename.lastIndexOf(".so."); +- if (so_pos != -1) { +- QString link_path = path_ + "/" + filename.left(so_pos + 3); +- QStringList version_parts = filename.mid(so_pos + 4).split('.'); +- +- while (!version_parts.isEmpty()) { +- qLog(Debug) << "Linking" << dest_path << "to" << link_path; +- int ret = symlink(dest_path.toLocal8Bit().constData(), +- link_path.toLocal8Bit().constData()); +- +- if (ret != 0) { +- qLog(Warning) << "Creating symlink failed with return code" << ret; +- } +- +- link_path += "." + version_parts.takeFirst(); +- } +- } +-#endif // Q_OS_UNIX +- } +- +- EmitFinished(); +-} +- +-void SpotifyBlobDownloader::ReplyProgress() { +- int progress = 0; +- int total = 0; +- +- foreach (QNetworkReply* reply, replies_) { +- progress += reply->bytesAvailable(); +- total += reply->rawHeader("Content-Length").toInt(); +- } +- +- progress_->setMaximum(total); +- progress_->setValue(progress); +-} +- +-void SpotifyBlobDownloader::Cancel() { +- deleteLater(); +-} +- +-void SpotifyBlobDownloader::ShowError(const QString& message) { +- // Stop any remaining replies before showing the dialog so they don't +- // carry on in the background +- foreach (QNetworkReply* reply, replies_) { +- disconnect(reply, 0, this, 0); +- reply->abort(); +- } +- +- qLog(Warning) << message; +- QMessageBox::warning(NULL, tr("Error downloading Spotify plugin"), message, +- QMessageBox::Close); +- deleteLater(); +-} +- +-void SpotifyBlobDownloader::EmitFinished() { +- emit Finished(); +- deleteLater(); +-} +diff -rauN clementine-1.0.1/src/internet/spotifyblobdownloader.h /dev/null +--- clementine-1.0.1/src/internet/spotifyblobdownloader.h 2011-12-02 19:24:44.000000000 -0200 ++++ /dev/null 2012-05-28 12:50:04.796939473 -0300 +@@ -1,63 +0,0 @@ +-/* This file is part of Clementine. +- Copyright 2010, David Sansome <me@davidsansome.com> +- +- Clementine 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 3 of the License, or +- (at your option) any later version. +- +- Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>. +-*/ +- +-#ifndef SPOTIFYBLOBDOWNLOADER_H +-#define SPOTIFYBLOBDOWNLOADER_H +- +-#include <QObject> +- +-class QNetworkAccessManager; +-class QNetworkReply; +-class QProgressDialog; +- +-class SpotifyBlobDownloader : public QObject { +- Q_OBJECT +- +-public: +- SpotifyBlobDownloader(const QString& version, const QString& path, +- QObject* parent = 0); +- ~SpotifyBlobDownloader(); +- +- static const char* kSignatureSuffix; +- +- static bool Prompt(); +- +- void Start(); +- +-signals: +- void Finished(); +- +-private slots: +- void ReplyFinished(); +- void ReplyProgress(); +- void Cancel(); +- +-private: +- void ShowError(const QString& message); +- void EmitFinished(); +- +-private: +- QString version_; +- QString path_; +- +- QNetworkAccessManager* network_; +- QList<QNetworkReply*> replies_; +- +- QProgressDialog* progress_; +-}; +- +-#endif // SPOTIFYBLOBDOWNLOADER_H +diff -rauN clementine-1.0.1/src/internet/spotifysearchplaylisttype.cpp /dev/null +--- clementine-1.0.1/src/internet/spotifysearchplaylisttype.cpp 2011-12-02 19:24:44.000000000 -0200 ++++ /dev/null 2012-05-28 12:50:04.796939473 -0300 +@@ -1,49 +0,0 @@ +-/* This file is part of Clementine. +- Copyright 2010, David Sansome <me@davidsansome.com> +- +- Clementine 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 3 of the License, or +- (at your option) any later version. +- +- Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>. +-*/ +- +-#include "spotifysearchplaylisttype.h" +-#include "spotifyservice.h" +- +-const char* SpotifySearchPlaylistType::kName = "spotify-search"; +- +-SpotifySearchPlaylistType::SpotifySearchPlaylistType(SpotifyService* service) +- : service_(service) { +-} +- +-QIcon SpotifySearchPlaylistType::icon(Playlist* playlist) const { +- return QIcon(":icons/32x32/spotify.png"); +-} +- +-QString SpotifySearchPlaylistType::search_hint_text(Playlist* playlist) const { +- return QObject::tr("Search Spotify"); +-} +- +-QString SpotifySearchPlaylistType::empty_playlist_text(Playlist* playlist) const { +- return QObject::tr("Start typing in the search box above to find music on %1.").arg("Spotify"); +-} +- +-bool SpotifySearchPlaylistType::has_special_search_behaviour(Playlist* playlist) const { +- return true; +-} +- +-void SpotifySearchPlaylistType::Search(const QString& text, Playlist* playlist) { +- service_->Search(text, playlist); +-} +- +-void SpotifySearchPlaylistType::DidYouMeanClicked(const QString& text, Playlist* playlist) { +- service_->Search(text, playlist, true); +-} +diff -rauN clementine-1.0.1/src/internet/spotifysearchplaylisttype.h /dev/null +--- clementine-1.0.1/src/internet/spotifysearchplaylisttype.h 2011-12-02 19:24:44.000000000 -0200 ++++ /dev/null 2012-05-28 12:50:04.796939473 -0300 +@@ -1,44 +0,0 @@ +-/* This file is part of Clementine. +- Copyright 2010, David Sansome <me@davidsansome.com> +- +- Clementine 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 3 of the License, or +- (at your option) any later version. +- +- Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>. +-*/ +- +-#ifndef SPOTIFYSEARCHPLAYLISTTYPE_H +-#define SPOTIFYSEARCHPLAYLISTTYPE_H +- +-#include "playlist/specialplaylisttype.h" +- +-class SpotifyService; +- +-class SpotifySearchPlaylistType : public SpecialPlaylistType { +-public: +- SpotifySearchPlaylistType(SpotifyService* service); +- +- static const char* kName; +- virtual QString name() const { return kName; } +- +- virtual QIcon icon(Playlist* playlist) const; +- virtual QString search_hint_text(Playlist* playlist) const; +- virtual QString empty_playlist_text(Playlist* playlist) const; +- +- virtual bool has_special_search_behaviour(Playlist* playlist) const; +- virtual void Search(const QString& text, Playlist* playlist); +- virtual void DidYouMeanClicked(const QString& text, Playlist* playlist); +- +-private: +- SpotifyService* service_; +-}; +- +-#endif // SPOTIFYSEARCHPLAYLISTTYPE_H +diff -rauN clementine-1.0.1/src/internet/spotifyserver.cpp /dev/null +--- clementine-1.0.1/src/internet/spotifyserver.cpp 2011-12-02 19:24:44.000000000 -0200 ++++ /dev/null 2012-05-28 12:50:04.796939473 -0300 +@@ -1,261 +0,0 @@ +-/* This file is part of Clementine. +- Copyright 2010, David Sansome <me@davidsansome.com> +- +- Clementine 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 3 of the License, or +- (at your option) any later version. +- +- Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>. +-*/ +- +-#include "spotifyserver.h" +-#include "core/closure.h" +-#include "core/logging.h" +- +-#include "spotifyblob/common/spotifymessages.pb.h" +-#include "spotifyblob/common/spotifymessagehandler.h" +- +-#include <QTcpServer> +-#include <QTcpSocket> +-#include <QTimer> +- +-SpotifyServer::SpotifyServer(QObject* parent) +- : QObject(parent), +- server_(new QTcpServer(this)), +- protocol_socket_(NULL), +- handler_(NULL), +- logged_in_(false) +-{ +- connect(server_, SIGNAL(newConnection()), SLOT(NewConnection())); +-} +- +-void SpotifyServer::Init() { +- if (!server_->listen(QHostAddress::LocalHost)) { +- qLog(Error) << "Couldn't open server socket" << server_->errorString(); +- } +-} +- +-int SpotifyServer::server_port() const { +- return server_->serverPort(); +-} +- +-void SpotifyServer::NewConnection() { +- delete protocol_socket_; +- delete handler_; +- +- protocol_socket_ = server_->nextPendingConnection(); +- handler_ = new SpotifyMessageHandler(protocol_socket_, this); +- connect(handler_, SIGNAL(MessageArrived(spotify_pb::SpotifyMessage)), +- SLOT(HandleMessage(spotify_pb::SpotifyMessage))); +- +- qLog(Info) << "Connection from port" << protocol_socket_->peerPort(); +- +- // Send any login messages that were queued before the client connected +- foreach (const spotify_pb::SpotifyMessage& message, queued_login_messages_) { +- SendMessage(message); +- } +- queued_login_messages_.clear(); +-} +- +-void SpotifyServer::SendMessage(const spotify_pb::SpotifyMessage& message) { +- const bool is_login_message = message.has_login_request(); +- +- QList<spotify_pb::SpotifyMessage>* queue = +- is_login_message ? &queued_login_messages_ : &queued_messages_; +- +- if (!protocol_socket_ || (!is_login_message && !logged_in_)) { +- queue->append(message); +- } else { +- handler_->SendMessage(message); +- } +-} +- +-void SpotifyServer::Login(const QString& username, const QString& password, +- spotify_pb::Bitrate bitrate, bool volume_normalisation) { +- spotify_pb::SpotifyMessage message; +- +- spotify_pb::LoginRequest* request = message.mutable_login_request(); +- request->set_username(DataCommaSizeFromQString(username)); +- if (!password.isEmpty()) { +- request->set_password(DataCommaSizeFromQString(password)); +- } +- request->mutable_playback_settings()->set_bitrate(bitrate); +- request->mutable_playback_settings()->set_volume_normalisation(volume_normalisation); +- +- SendMessage(message); +-} +- +-void SpotifyServer::SetPlaybackSettings(spotify_pb::Bitrate bitrate, bool volume_normalisation) { +- spotify_pb::SpotifyMessage message; +- +- spotify_pb::PlaybackSettings* request = message.mutable_set_playback_settings_request(); +- request->set_bitrate(bitrate); +- request->set_volume_normalisation(volume_normalisation); +- +- SendMessage(message); +-} +- +-void SpotifyServer::HandleMessage(const spotify_pb::SpotifyMessage& message) { +- if (message.has_login_response()) { +- const spotify_pb::LoginResponse& response = message.login_response(); +- logged_in_ = response.success(); +- +- if (response.success()) { +- // Send any messages that were queued before the client logged in +- foreach (const spotify_pb::SpotifyMessage& message, queued_messages_) { +- SendMessage(message); +- } +- queued_messages_.clear(); +- } +- +- emit LoginCompleted(response.success(), QStringFromStdString(response.error()), +- response.error_code()); +- } else if (message.has_playlists_updated()) { +- emit PlaylistsUpdated(message.playlists_updated()); +- } else if (message.has_load_playlist_response()) { +- const spotify_pb::LoadPlaylistResponse& response = message.load_playlist_response(); +- +- switch (response.request().type()) { +- case spotify_pb::Inbox: +- emit InboxLoaded(response); +- break; +- +- case spotify_pb::Starred: +- emit StarredLoaded(response); +- break; +- +- case spotify_pb::UserPlaylist: +- emit UserPlaylistLoaded(response); +- break; +- } +- } else if (message.has_playback_error()) { +- emit PlaybackError(QStringFromStdString(message.playback_error().error())); +- } else if (message.has_search_response()) { +- emit SearchResults(message.search_response()); +- } else if (message.has_image_response()) { +- const spotify_pb::ImageResponse& response = message.image_response(); +- const QString id = QStringFromStdString(response.id()); +- +- if (response.has_data()) { +- emit ImageLoaded(id, QImage::fromData(QByteArray( +- response.data().data(), response.data().size()))); +- } else { +- emit ImageLoaded(id, QImage()); +- } +- } else if (message.has_sync_playlist_progress()) { +- emit SyncPlaylistProgress(message.sync_playlist_progress()); +- } else if (message.has_browse_album_response()) { +- emit AlbumBrowseResults(message.browse_album_response()); +- } +-} +- +-void SpotifyServer::LoadPlaylist(spotify_pb::PlaylistType type, int index) { +- spotify_pb::SpotifyMessage message; +- spotify_pb::LoadPlaylistRequest* req = message.mutable_load_playlist_request(); +- +- req->set_type(type); +- if (index != -1) { +- req->set_user_playlist_index(index); +- } +- +- SendMessage(message); +-} +- +-void SpotifyServer::SyncPlaylist( +- spotify_pb::PlaylistType type, int index, bool offline) { +- spotify_pb::SpotifyMessage message; +- spotify_pb::SyncPlaylistRequest* req = message.mutable_sync_playlist_request(); +- req->mutable_request()->set_type(type); +- if (index != -1) { +- req->mutable_request()->set_user_playlist_index(index); +- } +- req->set_offline_sync(offline); +- +- SendMessage(message); +-} +- +-void SpotifyServer::SyncInbox() { +- SyncPlaylist(spotify_pb::Inbox, -1, true); +-} +- +-void SpotifyServer::SyncStarred() { +- SyncPlaylist(spotify_pb::Starred, -1, true); +-} +- +-void SpotifyServer::SyncUserPlaylist(int index) { +- Q_ASSERT(index >= 0); +- SyncPlaylist(spotify_pb::UserPlaylist, index, true); +-} +- +-void SpotifyServer::LoadInbox() { +- LoadPlaylist(spotify_pb::Inbox); +-} +- +-void SpotifyServer::LoadStarred() { +- LoadPlaylist(spotify_pb::Starred); +-} +- +-void SpotifyServer::LoadUserPlaylist(int index) { +- Q_ASSERT(index >= 0); +- LoadPlaylist(spotify_pb::UserPlaylist, index); +-} +- +-void SpotifyServer::StartPlaybackLater(const QString& uri, quint16 port) { +- QTimer* timer = new QTimer(this); +- connect(timer, SIGNAL(timeout()), timer, SLOT(deleteLater())); +- +- timer->start(100); // lol +- NewClosure(timer, SIGNAL(timeout()), +- this, SLOT(StartPlayback(QString,quint16)), +- uri, port); +-} +- +-void SpotifyServer::StartPlayback(const QString& uri, quint16 port) { +- spotify_pb::SpotifyMessage message; +- spotify_pb::PlaybackRequest* req = message.mutable_playback_request(); +- +- req->set_track_uri(DataCommaSizeFromQString(uri)); +- req->set_media_port(port); +- SendMessage(message); +-} +- +-void SpotifyServer::Seek(qint64 offset_bytes) { +- spotify_pb::SpotifyMessage message; +- spotify_pb::SeekRequest* req = message.mutable_seek_request(); +- +- req->set_offset_bytes(offset_bytes); +- SendMessage(message); +-} +- +-void SpotifyServer::Search(const QString& text, int limit, int limit_album) { +- spotify_pb::SpotifyMessage message; +- spotify_pb::SearchRequest* req = message.mutable_search_request(); +- +- req->set_query(DataCommaSizeFromQString(text)); +- req->set_limit(limit); +- req->set_limit_album(limit_album); +- SendMessage(message); +-} +- +-void SpotifyServer::LoadImage(const QString& id) { +- spotify_pb::SpotifyMessage message; +- spotify_pb::ImageRequest* req = message.mutable_image_request(); +- +- req->set_id(DataCommaSizeFromQString(id)); +- SendMessage(message); +-} +- +-void SpotifyServer::AlbumBrowse(const QString& uri) { +- spotify_pb::SpotifyMessage message; +- spotify_pb::BrowseAlbumRequest* req = message.mutable_browse_album_request(); +- +- req->set_uri(DataCommaSizeFromQString(uri)); +- SendMessage(message); +-} +diff -rauN clementine-1.0.1/src/internet/spotifyserver.h /dev/null +--- clementine-1.0.1/src/internet/spotifyserver.h 2011-12-02 19:24:44.000000000 -0200 ++++ /dev/null 2012-05-28 12:50:04.796939473 -0300 +@@ -1,91 +0,0 @@ +-/* This file is part of Clementine. +- Copyright 2010, David Sansome <me@davidsansome.com> +- +- Clementine 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 3 of the License, or +- (at your option) any later version. +- +- Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>. +-*/ +- +-#ifndef SPOTIFYSERVER_H +-#define SPOTIFYSERVER_H +- +-#include "spotifyblob/common/spotifymessages.pb.h" +- +-#include <QImage> +-#include <QObject> +- +-class SpotifyMessageHandler; +- +-class QTcpServer; +-class QTcpSocket; +- +-class SpotifyServer : public QObject { +- Q_OBJECT +- +-public: +- SpotifyServer(QObject* parent = 0); +- +- void Init(); +- void Login(const QString& username, const QString& password, +- spotify_pb::Bitrate bitrate, bool volume_normalisation); +- +- void LoadStarred(); +- void SyncStarred(); +- void LoadInbox(); +- void SyncInbox(); +- void LoadUserPlaylist(int index); +- void SyncUserPlaylist(int index); +- void StartPlaybackLater(const QString& uri, quint16 port); +- void Search(const QString& text, int limit, int limit_album = 0); +- void LoadImage(const QString& id); +- void AlbumBrowse(const QString& uri); +- void SetPlaybackSettings(spotify_pb::Bitrate bitrate, bool volume_normalisation); +- +- int server_port() const; +- +-public slots: +- void StartPlayback(const QString& uri, quint16 port); +- void Seek(qint64 offset_bytes); +- +-signals: +- void LoginCompleted(bool success, const QString& error, +- spotify_pb::LoginResponse_Error error_code); +- void PlaylistsUpdated(const spotify_pb::Playlists& playlists); +- +- void StarredLoaded(const spotify_pb::LoadPlaylistResponse& response); +- void InboxLoaded(const spotify_pb::LoadPlaylistResponse& response); +- void UserPlaylistLoaded(const spotify_pb::LoadPlaylistResponse& response); +- void PlaybackError(const QString& message); +- void SearchResults(const spotify_pb::SearchResponse& response); +- void ImageLoaded(const QString& id, const QImage& image); +- void SyncPlaylistProgress(const spotify_pb::SyncPlaylistProgress& progress); +- void AlbumBrowseResults(const spotify_pb::BrowseAlbumResponse& response); +- +-private slots: +- void NewConnection(); +- void HandleMessage(const spotify_pb::SpotifyMessage& message); +- +-private: +- void LoadPlaylist(spotify_pb::PlaylistType type, int index = -1); +- void SyncPlaylist(spotify_pb::PlaylistType type, int index, bool offline); +- void SendMessage(const spotify_pb::SpotifyMessage& message); +- +- QTcpServer* server_; +- QTcpSocket* protocol_socket_; +- SpotifyMessageHandler* handler_; +- bool logged_in_; +- +- QList<spotify_pb::SpotifyMessage> queued_login_messages_; +- QList<spotify_pb::SpotifyMessage> queued_messages_; +-}; +- +-#endif // SPOTIFYSERVER_H +diff -rauN clementine-1.0.1/src/internet/spotifyservice.cpp /dev/null +--- clementine-1.0.1/src/internet/spotifyservice.cpp 2011-12-02 19:24:44.000000000 -0200 ++++ /dev/null 2012-05-28 12:50:04.796939473 -0300 +@@ -1,669 +0,0 @@ +-#include "config.h" +-#include "internetmodel.h" +-#include "spotifyblobdownloader.h" +-#include "spotifyserver.h" +-#include "spotifyservice.h" +-#include "spotifysearchplaylisttype.h" +-#include "core/database.h" +-#include "core/logging.h" +-#include "core/player.h" +-#include "core/taskmanager.h" +-#include "core/timeconstants.h" +-#include "core/utilities.h" +-#include "globalsearch/globalsearch.h" +-#include "globalsearch/spotifysearchprovider.h" +-#include "playlist/playlist.h" +-#include "playlist/playlistcontainer.h" +-#include "playlist/playlistmanager.h" +-#include "spotifyblob/common/blobversion.h" +-#include "spotifyblob/common/spotifymessagehandler.h" +-#include "widgets/didyoumean.h" +-#include "ui/iconloader.h" +- +-#include <QCoreApplication> +-#include <QFile> +-#include <QFileInfo> +-#include <QMenu> +-#include <QMessageBox> +-#include <QProcess> +-#include <QSettings> +-#include <QVariant> +- +-Q_DECLARE_METATYPE(QStandardItem*); +- +-const char* SpotifyService::kServiceName = "Spotify"; +-const char* SpotifyService::kSettingsGroup = "Spotify"; +-const char* SpotifyService::kBlobDownloadUrl = "http://spotify.clementine-player.org/"; +-const int SpotifyService::kSearchDelayMsec = 400; +- +-SpotifyService::SpotifyService(InternetModel* parent) +- : InternetService(kServiceName, parent, parent), +- server_(NULL), +- blob_process_(NULL), +- root_(NULL), +- search_(NULL), +- starred_(NULL), +- inbox_(NULL), +- login_task_id_(0), +- pending_search_playlist_(NULL), +- context_menu_(NULL), +- search_delay_(new QTimer(this)), +- login_state_(LoginState_OtherError), +- bitrate_(spotify_pb::Bitrate320k), +- volume_normalisation_(false) +-{ +- // Build the search path for the binary blob. +- // Look for one distributed alongside clementine first, then check in the +- // user's home directory for any that have been downloaded. +-#ifdef Q_OS_MAC +- system_blob_path_ = QCoreApplication::applicationDirPath() + +- "/../PlugIns/clementine-spotifyblob"; +-#else +- system_blob_path_ = QCoreApplication::applicationDirPath() + +- "/clementine-spotifyblob" CMAKE_EXECUTABLE_SUFFIX; +-#endif +- +- local_blob_version_ = QString("version%1-%2bit").arg(SPOTIFY_BLOB_VERSION).arg(sizeof(void*) * 8); +- local_blob_path_ = Utilities::GetConfigPath(Utilities::Path_LocalSpotifyBlob) + +- "/" + local_blob_version_ + "/blob"; +- +- qLog(Debug) << "Spotify system blob path:" << system_blob_path_; +- qLog(Debug) << "Spotify local blob path:" << local_blob_path_; +- +- model()->player()->playlists()->RegisterSpecialPlaylistType( +- new SpotifySearchPlaylistType(this)); +- +- model()->global_search()->AddProvider(new SpotifySearchProvider(this)); +- +- search_delay_->setInterval(kSearchDelayMsec); +- search_delay_->setSingleShot(true); +- connect(search_delay_, SIGNAL(timeout()), SLOT(DoSearch())); +-} +- +-SpotifyService::~SpotifyService() { +- if (blob_process_ && blob_process_->state() == QProcess::Running) { +- qLog(Info) << "Terminating blob process..."; +- blob_process_->terminate(); +- blob_process_->waitForFinished(1000); +- } +-} +- +-QStandardItem* SpotifyService::CreateRootItem() { +- root_ = new QStandardItem(QIcon(":icons/22x22/spotify.png"), kServiceName); +- root_->setData(true, InternetModel::Role_CanLazyLoad); +- return root_; +-} +- +-void SpotifyService::LazyPopulate(QStandardItem* item) { +- switch (item->data(InternetModel::Role_Type).toInt()) { +- case InternetModel::Type_Service: +- EnsureServerCreated(); +- break; +- +- case Type_SearchResults: +- break; +- +- case Type_InboxPlaylist: +- EnsureServerCreated(); +- server_->LoadInbox(); +- break; +- +- case Type_StarredPlaylist: +- EnsureServerCreated(); +- server_->LoadStarred(); +- break; +- +- case InternetModel::Type_UserPlaylist: +- EnsureServerCreated(); +- server_->LoadUserPlaylist(item->data(Role_UserPlaylistIndex).toInt()); +- break; +- +- default: +- break; +- } +- +- return; +-} +- +-QModelIndex SpotifyService::GetCurrentIndex() { +- return QModelIndex(); +-} +- +-void SpotifyService::Login(const QString& username, const QString& password) { +- Logout(); +- EnsureServerCreated(username, password); +-} +- +-void SpotifyService::LoginCompleted(bool success, const QString& error, +- spotify_pb::LoginResponse_Error error_code) { +- if (login_task_id_) { +- model()->task_manager()->SetTaskFinished(login_task_id_); +- login_task_id_ = 0; +- } +- +- if (!success) { +- bool show_error_dialog = true; +- QString error_copy(error); +- +- switch (error_code) { +- case spotify_pb::LoginResponse_Error_BadUsernameOrPassword: +- login_state_ = LoginState_BadCredentials; +- break; +- +- case spotify_pb::LoginResponse_Error_UserBanned: +- login_state_ = LoginState_Banned; +- break; +- +- case spotify_pb::LoginResponse_Error_UserNeedsPremium: +- login_state_ = LoginState_NoPremium; +- break; +- +- case spotify_pb::LoginResponse_Error_ReloginFailed: +- if (login_state_ == LoginState_LoggedIn) { +- // This is the first time the relogin has failed - show a message this +- // time only. +- error_copy = tr("You have been logged out of Spotify, please re-enter your password in the Settings dialog."); +- } else { +- show_error_dialog = false; +- } +- +- login_state_ = LoginState_ReloginFailed; +- break; +- +- default: +- login_state_ = LoginState_OtherError; +- break; +- } +- +- if (show_error_dialog) { +- QMessageBox::warning(NULL, tr("Spotify login error"), error_copy, QMessageBox::Close); +- } +- } else { +- login_state_ = LoginState_LoggedIn; +- } +- +- QSettings s; +- s.beginGroup(kSettingsGroup); +- s.setValue("login_state", login_state_); +- +- emit LoginFinished(success); +-} +- +-void SpotifyService::BlobProcessError(QProcess::ProcessError error) { +- qLog(Error) << "Spotify blob process failed:" << error; +- blob_process_->deleteLater(); +- blob_process_ = NULL; +- +- if (login_task_id_) { +- model()->task_manager()->SetTaskFinished(login_task_id_); +- } +-} +- +-void SpotifyService::ReloadSettings() { +- QSettings s; +- s.beginGroup(kSettingsGroup); +- +- login_state_ = LoginState(s.value("login_state", LoginState_OtherError).toInt()); +- bitrate_ = static_cast<spotify_pb::Bitrate>( +- s.value("bitrate", spotify_pb::Bitrate320k).toInt()); +- volume_normalisation_ = s.value("volume_normalisation", false).toBool(); +- +- if (server_ && blob_process_) { +- server_->SetPlaybackSettings(bitrate_, volume_normalisation_); +- } +-} +- +-void SpotifyService::EnsureServerCreated(const QString& username, +- const QString& password) { +- if (server_ && blob_process_) { +- return; +- } +- +- delete server_; +- server_ = new SpotifyServer(this); +- +- connect(server_, SIGNAL(LoginCompleted(bool,QString,spotify_pb::LoginResponse_Error)), +- SLOT(LoginCompleted(bool,QString,spotify_pb::LoginResponse_Error))); +- connect(server_, SIGNAL(PlaylistsUpdated(spotify_pb::Playlists)), +- SLOT(PlaylistsUpdated(spotify_pb::Playlists))); +- connect(server_, SIGNAL(InboxLoaded(spotify_pb::LoadPlaylistResponse)), +- SLOT(InboxLoaded(spotify_pb::LoadPlaylistResponse))); +- connect(server_, SIGNAL(StarredLoaded(spotify_pb::LoadPlaylistResponse)), +- SLOT(StarredLoaded(spotify_pb::LoadPlaylistResponse))); +- connect(server_, SIGNAL(UserPlaylistLoaded(spotify_pb::LoadPlaylistResponse)), +- SLOT(UserPlaylistLoaded(spotify_pb::LoadPlaylistResponse))); +- connect(server_, SIGNAL(PlaybackError(QString)), +- SIGNAL(StreamError(QString))); +- connect(server_, SIGNAL(SearchResults(spotify_pb::SearchResponse)), +- SLOT(SearchResults(spotify_pb::SearchResponse))); +- connect(server_, SIGNAL(ImageLoaded(QString,QImage)), +- SIGNAL(ImageLoaded(QString,QImage))); +- connect(server_, SIGNAL(SyncPlaylistProgress(spotify_pb::SyncPlaylistProgress)), +- SLOT(SyncPlaylistProgress(spotify_pb::SyncPlaylistProgress))); +- +- server_->Init(); +- +- login_task_id_ = model()->task_manager()->StartTask(tr("Connecting to Spotify")); +- +- QString login_username = username; +- QString login_password = password; +- +- if (username.isEmpty()) { +- QSettings s; +- s.beginGroup(kSettingsGroup); +- +- login_username = s.value("username").toString(); +- login_password = QString(); +- } +- +- server_->Login(login_username, login_password, bitrate_, volume_normalisation_); +- +- StartBlobProcess(); +-} +- +-void SpotifyService::StartBlobProcess() { +- // Try to find an executable to run +- QString blob_path; +- QProcessEnvironment env(QProcessEnvironment::systemEnvironment()); +- +- // Look in the system search path first +- if (QFile::exists(system_blob_path_)) { +- blob_path = system_blob_path_; +- } +- +- // Next look in the local path +- if (blob_path.isEmpty()) { +- if (QFile::exists(local_blob_path_)) { +- blob_path = local_blob_path_; +- env.insert("LD_LIBRARY_PATH", QFileInfo(local_blob_path_).path()); +- } +- } +- +- if (blob_path.isEmpty()) { +- // If the blob still wasn't found then we'll prompt the user to download one +- if (login_task_id_) { +- model()->task_manager()->SetTaskFinished(login_task_id_); +- } +- +- #ifdef Q_OS_LINUX +- if (SpotifyBlobDownloader::Prompt()) { +- InstallBlob(); +- } +- #endif +- +- return; +- } +- +- delete blob_process_; +- blob_process_ = new QProcess(this); +- blob_process_->setProcessChannelMode(QProcess::ForwardedChannels); +- blob_process_->setProcessEnvironment(env); +- +- connect(blob_process_, +- SIGNAL(error(QProcess::ProcessError)), +- SLOT(BlobProcessError(QProcess::ProcessError))); +- +- qLog(Info) << "Starting" << blob_path; +- blob_process_->start( +- blob_path, QStringList() << QString::number(server_->server_port())); +-} +- +-bool SpotifyService::IsBlobInstalled() const { +- return QFile::exists(system_blob_path_) || +- QFile::exists(local_blob_path_); +-} +- +-void SpotifyService::InstallBlob() { +- // The downloader deletes itself when it finishes +- SpotifyBlobDownloader* downloader = new SpotifyBlobDownloader( +- local_blob_version_, QFileInfo(local_blob_path_).path(), this); +- connect(downloader, SIGNAL(Finished()), SLOT(BlobDownloadFinished())); +- connect(downloader, SIGNAL(Finished()), SIGNAL(BlobStateChanged())); +- downloader->Start(); +-} +- +-void SpotifyService::BlobDownloadFinished() { +- EnsureServerCreated(); +-} +- +-void SpotifyService::PlaylistsUpdated(const spotify_pb::Playlists& response) { +- if (login_task_id_) { +- model()->task_manager()->SetTaskFinished(login_task_id_); +- login_task_id_ = 0; +- } +- +- // Create starred and inbox playlists if they're not here already +- if (!search_) { +- search_ = new QStandardItem(IconLoader::Load("edit-find"), +- tr("Search Spotify (opens a new tab)")); +- search_->setData(Type_SearchResults, InternetModel::Role_Type); +- search_->setData(InternetModel::PlayBehaviour_DoubleClickAction, +- InternetModel::Role_PlayBehaviour); +- +- starred_ = new QStandardItem(QIcon(":/star-on.png"), tr("Starred")); +- starred_->setData(Type_StarredPlaylist, InternetModel::Role_Type); +- starred_->setData(true, InternetModel::Role_CanLazyLoad); +- +- inbox_ = new QStandardItem(IconLoader::Load("mail-message"), tr("Inbox")); +- inbox_->setData(Type_InboxPlaylist, InternetModel::Role_Type); +- inbox_->setData(true, InternetModel::Role_CanLazyLoad); +- +- root_->appendRow(search_); +- root_->appendRow(starred_); +- root_->appendRow(inbox_); +- } +- +- // Don't do anything if the playlists haven't changed since last time. +- if (!DoPlaylistsDiffer(response)) { +- qLog(Debug) << "Playlists haven't changed - not updating"; +- return; +- } +- +- // Remove and recreate the other playlists +- foreach (QStandardItem* item, playlists_) { +- item->parent()->removeRow(item->row()); +- } +- playlists_.clear(); +- +- for (int i=0 ; i<response.playlist_size() ; ++i) { +- const spotify_pb::Playlists::Playlist& msg = response.playlist(i); +- +- QStandardItem* item = new QStandardItem(QStringFromStdString(msg.name())); +- item->setData(InternetModel::Type_UserPlaylist, InternetModel::Role_Type); +- item->setData(true, InternetModel::Role_CanLazyLoad); +- item->setData(msg.index(), Role_UserPlaylistIndex); +- item->setData(InternetModel::PlayBehaviour_SingleItem, InternetModel::Role_PlayBehaviour); +- +- root_->appendRow(item); +- playlists_ << item; +- +- // Preload the playlist items so that drag & drop works immediately. +- LazyPopulate(item); +- } +-} +- +-bool SpotifyService::DoPlaylistsDiffer(const spotify_pb::Playlists& response) const { +- if (playlists_.count() != response.playlist_size()) { +- return true; +- } +- +- for (int i=0 ; i<response.playlist_size() ; ++i) { +- const spotify_pb::Playlists::Playlist& msg = response.playlist(i); +- const QStandardItem* item = PlaylistBySpotifyIndex(msg.index()); +- +- if (!item) { +- return true; +- } +- +- if (QStringFromStdString(msg.name()) != item->text()) { +- return true; +- } +- } +- +- return false; +-} +- +-void SpotifyService::InboxLoaded(const spotify_pb::LoadPlaylistResponse& response) { +- FillPlaylist(inbox_, response); +-} +- +-void SpotifyService::StarredLoaded(const spotify_pb::LoadPlaylistResponse& response) { +- FillPlaylist(starred_, response); +-} +- +-QStandardItem* SpotifyService::PlaylistBySpotifyIndex(int index) const { +- foreach (QStandardItem* item, playlists_) { +- if (item->data(Role_UserPlaylistIndex).toInt() == index) { +- return item; +- } +- } +- return NULL; +-} +- +-void SpotifyService::UserPlaylistLoaded(const spotify_pb::LoadPlaylistResponse& response) { +- // Find a playlist with this index +- QStandardItem* item = PlaylistBySpotifyIndex(response.request().user_playlist_index()); +- if (item) { +- FillPlaylist(item, response); +- } +-} +- +-void SpotifyService::FillPlaylist(QStandardItem* item, const spotify_pb::LoadPlaylistResponse& response) { +- qLog(Debug) << "Filling playlist:" << item->text(); +- if (item->hasChildren()) +- item->removeRows(0, item->rowCount()); +- +- for (int i=0 ; i<response.track_size() ; ++i) { +- Song song; +- SongFromProtobuf(response.track(i), &song); +- +- QStandardItem* child = new QStandardItem(song.PrettyTitleWithArtist()); +- child->setData(Type_Track, InternetModel::Role_Type); +- child->setData(QVariant::fromValue(song), InternetModel::Role_SongMetadata); +- child->setData(InternetModel::PlayBehaviour_SingleItem, InternetModel::Role_PlayBehaviour); +- child->setData(song.url(), InternetModel::Role_Url); +- +- item->appendRow(child); +- } +-} +- +-void SpotifyService::SongFromProtobuf(const spotify_pb::Track& track, Song* song) { +- song->set_rating(track.starred() ? 1.0 : 0.0); +- song->set_title(QStringFromStdString(track.title())); +- song->set_album(QStringFromStdString(track.album())); +- song->set_length_nanosec(track.duration_msec() * kNsecPerMsec); +- song->set_score(track.popularity()); +- song->set_disc(track.disc()); +- song->set_track(track.track()); +- song->set_year(track.year()); +- song->set_url(QUrl(QStringFromStdString(track.uri()))); +- song->set_art_automatic("spotify://image/" + QStringFromStdString(track.album_art_id())); +- +- QStringList artists; +- for (int i=0 ; i<track.artist_size() ; ++i) { +- artists << QStringFromStdString(track.artist(i)); +- } +- +- song->set_artist(artists.join(", ")); +- +- song->set_filetype(Song::Type_Stream); +- song->set_valid(true); +- song->set_directory_id(0); +- song->set_mtime(0); +- song->set_ctime(0); +- song->set_filesize(0); +-} +- +-PlaylistItem::Options SpotifyService::playlistitem_options() const { +- return PlaylistItem::PauseDisabled | PlaylistItem::SeekDisabled; +-} +- +-void SpotifyService::EnsureMenuCreated() { +- if (context_menu_) +- return; +- +- context_menu_ = new QMenu; +- +- context_menu_->addActions(GetPlaylistActions()); +- context_menu_->addSeparator(); +- context_menu_->addAction(IconLoader::Load("edit-find"), tr("Search Spotify (opens a new tab)..."), this, SLOT(OpenSearchTab())); +- context_menu_->addSeparator(); +- context_menu_->addAction(IconLoader::Load("configure"), tr("Configure Spotify..."), this, SLOT(ShowConfig())); +- +- playlist_context_menu_ = new QMenu; +- playlist_sync_action_ = playlist_context_menu_->addAction( +- IconLoader::Load("view-refresh"), +- tr("Make playlist available offline"), +- this, +- SLOT(SyncPlaylist())); +-} +- +-void SpotifyService::SyncPlaylist() { +- QStandardItem* item = playlist_sync_action_->data().value<QStandardItem*>(); +- Q_ASSERT(item); +- +- switch (item->data(InternetModel::Role_Type).toInt()) { +- case InternetModel::Type_UserPlaylist: { +- int index = item->data(Role_UserPlaylistIndex).toInt(); +- server_->SyncUserPlaylist(index); +- playlist_sync_ids_[index] = +- model()->task_manager()->StartTask(tr("Syncing Spotify playlist")); +- break; +- } +- case Type_InboxPlaylist: +- server_->SyncInbox(); +- inbox_sync_id_ = model()->task_manager()->StartTask(tr("Syncing Spotify inbox")); +- break; +- case Type_StarredPlaylist: +- server_->SyncStarred(); +- starred_sync_id_ = model()->task_manager()->StartTask(tr("Syncing Spotify starred tracks")); +- break; +- default: +- break; +- } +-} +- +-void SpotifyService::Search(const QString& text, Playlist* playlist, bool now) { +- EnsureServerCreated(); +- +- pending_search_ = text; +- pending_search_playlist_ = playlist; +- +- if (now) { +- search_delay_->stop(); +- DoSearch(); +- } else { +- search_delay_->start(); +- } +-} +- +-void SpotifyService::DoSearch() { +- if (!pending_search_.isEmpty()) { +- server_->Search(pending_search_, 200); +- } +-} +- +-void SpotifyService::SearchResults(const spotify_pb::SearchResponse& response) { +- if (QStringFromStdString(response.request().query()) != pending_search_) { +- qLog(Debug) << "Old search result for" +- << QStringFromStdString(response.request().query()) +- << "expecting" << pending_search_; +- return; +- } +- pending_search_.clear(); +- +- SongList songs; +- for (int i=0 ; i<response.result_size() ; ++i) { +- Song song; +- SongFromProtobuf(response.result(i), &song); +- songs << song; +- } +- +- qLog(Debug) << "Got" << songs.count() << "results"; +- +- pending_search_playlist_->Clear(); +- pending_search_playlist_->InsertSongs(songs); +- +- const QString did_you_mean = QStringFromStdString(response.did_you_mean()); +- if (!did_you_mean.isEmpty()) { +- model()->player()->playlists()->playlist_container()->did_you_mean()->Show(did_you_mean); +- } +-} +- +-SpotifyServer* SpotifyService::server() const { +- SpotifyService* nonconst_this = const_cast<SpotifyService*>(this); +- +- if (QThread::currentThread() != thread()) { +- metaObject()->invokeMethod(nonconst_this, "EnsureServerCreated", +- Qt::BlockingQueuedConnection); +- } else { +- nonconst_this->EnsureServerCreated(); +- } +- +- return server_; +-} +- +-void SpotifyService::ShowContextMenu(const QModelIndex& index, const QPoint& global_pos) { +- EnsureMenuCreated(); +- QStandardItem* item = model()->itemFromIndex(index); +- if (item) { +- int type = item->data(InternetModel::Role_Type).toInt(); +- if (type == Type_InboxPlaylist || +- type == Type_StarredPlaylist || +- type == InternetModel::Type_UserPlaylist) { +- playlist_sync_action_->setData(qVariantFromValue(item)); +- playlist_context_menu_->popup(global_pos); +- return; +- } +- } +- +- context_menu_->popup(global_pos); +-} +- +-void SpotifyService::OpenSearchTab() { +- model()->player()->playlists()->New(tr("Search Spotify"), SongList(), +- SpotifySearchPlaylistType::kName); +-} +- +-void SpotifyService::ItemDoubleClicked(QStandardItem* item) { +- if (item == search_) { +- OpenSearchTab(); +- } +-} +- +-void SpotifyService::LoadImage(const QString& id) { +- EnsureServerCreated(); +- server_->LoadImage(id); +-} +- +-void SpotifyService::SyncPlaylistProgress( +- const spotify_pb::SyncPlaylistProgress& progress) { +- qLog(Debug) << "Sync progress:" << progress.sync_progress(); +- int task_id = -1; +- switch (progress.request().type()) { +- case spotify_pb::Inbox: +- task_id = inbox_sync_id_; +- break; +- case spotify_pb::Starred: +- task_id = starred_sync_id_; +- break; +- case spotify_pb::UserPlaylist: { +- QMap<int, int>::const_iterator it = playlist_sync_ids_.constFind( +- progress.request().user_playlist_index()); +- if (it != playlist_sync_ids_.constEnd()) { +- task_id = it.value(); +- } +- break; +- } +- default: +- break; +- } +- if (task_id == -1) { +- qLog(Warning) << "Received sync progress for unknown playlist"; +- return; +- } +- model()->task_manager()->SetTaskProgress(task_id, progress.sync_progress(), 100); +- if (progress.sync_progress() == 100) { +- model()->task_manager()->SetTaskFinished(task_id); +- if (progress.request().type() == spotify_pb::UserPlaylist) { +- playlist_sync_ids_.remove(task_id); +- } +- } +-} +- +-void SpotifyService::ShowConfig() { +- emit OpenSettingsAtPage(SettingsDialog::Page_Spotify); +-} +- +-void SpotifyService::Logout() { +- delete server_; +- delete blob_process_; +- server_ = NULL; +- blob_process_ = NULL; +- +- login_state_ = LoginState_OtherError; +- +- QSettings s; +- s.beginGroup(kSettingsGroup); +- s.setValue("login_state", login_state_); +-} +diff -rauN clementine-1.0.1/src/internet/spotifyservice.h /dev/null +--- clementine-1.0.1/src/internet/spotifyservice.h 2011-12-02 19:24:44.000000000 -0200 ++++ /dev/null 2012-05-28 12:50:04.796939473 -0300 +@@ -1,147 +0,0 @@ +-#ifndef SPOTIFYSERVICE_H +-#define SPOTIFYSERVICE_H +- +-#include "internetmodel.h" +-#include "internetservice.h" +-#include "spotifyblob/common/spotifymessages.pb.h" +- +-#include <QProcess> +-#include <QTimer> +- +-#include <boost/shared_ptr.hpp> +- +-class Playlist; +-class SpotifyServer; +- +-class QMenu; +- +-class SpotifyService : public InternetService { +- Q_OBJECT +- +-public: +- SpotifyService(InternetModel* parent); +- ~SpotifyService(); +- +- enum Type { +- Type_SearchResults = InternetModel::TypeCount, +- Type_StarredPlaylist, +- Type_InboxPlaylist, +- Type_Track, +- }; +- +- enum Role { +- Role_UserPlaylistIndex = InternetModel::RoleCount, +- }; +- +- // Values are persisted - don't change. +- enum LoginState { +- LoginState_LoggedIn = 1, +- LoginState_Banned = 2, +- LoginState_BadCredentials = 3, +- LoginState_NoPremium = 4, +- LoginState_OtherError = 5, +- LoginState_ReloginFailed = 6 +- }; +- +- static const char* kServiceName; +- static const char* kSettingsGroup; +- static const char* kBlobDownloadUrl; +- static const int kSearchDelayMsec; +- +- void ReloadSettings(); +- +- QStandardItem* CreateRootItem(); +- void LazyPopulate(QStandardItem* parent); +- void ShowContextMenu(const QModelIndex& index, const QPoint& global_pos); +- void ItemDoubleClicked(QStandardItem* item); +- PlaylistItem::Options playlistitem_options() const; +- +- void Logout(); +- void Login(const QString& username, const QString& password); +- void Search(const QString& text, Playlist* playlist, bool now = false); +- Q_INVOKABLE void LoadImage(const QString& id); +- +- SpotifyServer* server() const; +- +- bool IsBlobInstalled() const; +- void InstallBlob(); +- +- // Persisted in the settings and updated on each Login(). +- LoginState login_state() const { return login_state_; } +- bool IsLoggedIn() const { return login_state_ == LoginState_LoggedIn; } +- +- static void SongFromProtobuf(const spotify_pb::Track& track, Song* song); +- +-signals: +- void BlobStateChanged(); +- void LoginFinished(bool success); +- void ImageLoaded(const QString& id, const QImage& image); +- +-public slots: +- void ShowConfig(); +- +-protected: +- virtual QModelIndex GetCurrentIndex(); +- +-private: +- void StartBlobProcess(); +- void FillPlaylist(QStandardItem* item, const spotify_pb::LoadPlaylistResponse& response); +- void EnsureMenuCreated(); +- +- QStandardItem* PlaylistBySpotifyIndex(int index) const; +- bool DoPlaylistsDiffer(const spotify_pb::Playlists& response) const; +- +-private slots: +- void EnsureServerCreated(const QString& username = QString(), +- const QString& password = QString()); +- void BlobProcessError(QProcess::ProcessError error); +- void LoginCompleted(bool success, const QString& error, +- spotify_pb::LoginResponse_Error error_code); +- void PlaylistsUpdated(const spotify_pb::Playlists& response); +- void InboxLoaded(const spotify_pb::LoadPlaylistResponse& response); +- void StarredLoaded(const spotify_pb::LoadPlaylistResponse& response); +- void UserPlaylistLoaded(const spotify_pb::LoadPlaylistResponse& response); +- void SearchResults(const spotify_pb::SearchResponse& response); +- void SyncPlaylistProgress(const spotify_pb::SyncPlaylistProgress& progress); +- +- void OpenSearchTab(); +- void DoSearch(); +- +- void SyncPlaylist(); +- void BlobDownloadFinished(); +- +-private: +- SpotifyServer* server_; +- +- QString system_blob_path_; +- QString local_blob_version_; +- QString local_blob_path_; +- QProcess* blob_process_; +- +- QStandardItem* root_; +- QStandardItem* search_; +- QStandardItem* starred_; +- QStandardItem* inbox_; +- QList<QStandardItem*> playlists_; +- +- int login_task_id_; +- QString pending_search_; +- Playlist* pending_search_playlist_; +- +- QMenu* context_menu_; +- QMenu* playlist_context_menu_; +- QAction* playlist_sync_action_; +- QModelIndex context_item_; +- +- QTimer* search_delay_; +- +- int inbox_sync_id_; +- int starred_sync_id_; +- QMap<int, int> playlist_sync_ids_; +- +- LoginState login_state_; +- spotify_pb::Bitrate bitrate_; +- bool volume_normalisation_; +-}; +- +-#endif +diff -rauN clementine-1.0.1/src/internet/spotifysettingspage.cpp /dev/null +--- clementine-1.0.1/src/internet/spotifysettingspage.cpp 2011-12-02 19:24:44.000000000 -0200 ++++ /dev/null 2012-05-28 12:50:04.796939473 -0300 +@@ -1,172 +0,0 @@ +-/* This file is part of Clementine. +- Copyright 2010, David Sansome <me@davidsansome.com> +- +- Clementine 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 3 of the License, or +- (at your option) any later version. +- +- Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>. +-*/ +- +-#include "spotifysettingspage.h" +- +-#include "spotifyservice.h" +-#include "internetmodel.h" +-#include "ui_spotifysettingspage.h" +-#include "core/network.h" +-#include "spotifyblob/common/spotifymessages.pb.h" +-#include "ui/iconloader.h" +- +-#include <QMessageBox> +-#include <QNetworkReply> +-#include <QNetworkRequest> +-#include <QSettings> +-#include <QtDebug> +- +-SpotifySettingsPage::SpotifySettingsPage(SettingsDialog* dialog) +- : SettingsPage(dialog), +- network_(new NetworkAccessManager(this)), +- ui_(new Ui_SpotifySettingsPage), +- service_(InternetModel::Service<SpotifyService>()), +- validated_(false) +-{ +- ui_->setupUi(this); +- +- setWindowIcon(QIcon(":/icons/48x48/spotify.png")); +- +- QFont bold_font(font()); +- bold_font.setBold(true); +- ui_->blob_status->setFont(bold_font); +- +- connect(ui_->download_blob, SIGNAL(clicked()), SLOT(DownloadBlob())); +- connect(ui_->login, SIGNAL(clicked()), SLOT(Login())); +- connect(ui_->login_state, SIGNAL(LogoutClicked()), SLOT(Logout())); +- connect(ui_->login_state, SIGNAL(LoginClicked()), SLOT(Login())); +- +- connect(service_, SIGNAL(LoginFinished(bool)), SLOT(LoginFinished(bool))); +- connect(service_, SIGNAL(BlobStateChanged()), SLOT(BlobStateChanged())); +- +- ui_->login_state->AddCredentialField(ui_->username); +- ui_->login_state->AddCredentialField(ui_->password); +- ui_->login_state->AddCredentialGroup(ui_->account_group); +- +- ui_->bitrate->addItem("96 " + tr("kbps"), spotify_pb::Bitrate96k); +- ui_->bitrate->addItem("160 " + tr("kbps"), spotify_pb::Bitrate160k); +- ui_->bitrate->addItem("320 " + tr("kbps"), spotify_pb::Bitrate320k); +- +- BlobStateChanged(); +-} +- +-SpotifySettingsPage::~SpotifySettingsPage() { +- delete ui_; +-} +- +-void SpotifySettingsPage::BlobStateChanged() { +- const bool installed = service_->IsBlobInstalled(); +- +- ui_->account_group->setEnabled(installed); +- ui_->blob_status->setText(installed ? tr("Installed") : tr("Not installed")); +- +-#ifdef Q_OS_LINUX +- ui_->download_blob->setEnabled(!installed); +-#else +- ui_->download_blob->setEnabled(false); +-#endif +-} +- +-void SpotifySettingsPage::DownloadBlob() { +- service_->InstallBlob(); +-} +- +-void SpotifySettingsPage::Login() { +- if (!service_->IsBlobInstalled()) { +- return; +- } +- +- if (ui_->username->text() == original_username_ && +- ui_->password->text() == original_password_ && +- service_->login_state() == SpotifyService::LoginState_LoggedIn) { +- return; +- } +- +- ui_->login_state->SetLoggedIn(LoginStateWidget::LoginInProgress); +- service_->Login(ui_->username->text(), ui_->password->text()); +-} +- +-void SpotifySettingsPage::Load() { +- QSettings s; +- s.beginGroup(SpotifyService::kSettingsGroup); +- +- original_username_ = s.value("username").toString(); +- +- ui_->username->setText(original_username_); +- validated_ = false; +- +- ui_->bitrate->setCurrentIndex(ui_->bitrate->findData( +- s.value("bitrate", spotify_pb::Bitrate320k).toInt())); +- ui_->volume_normalisation->setChecked( +- s.value("volume_normalisation", false).toBool()); +- +- UpdateLoginState(); +-} +- +-void SpotifySettingsPage::Save() { +- QSettings s; +- s.beginGroup(SpotifyService::kSettingsGroup); +- +- s.setValue("username", ui_->username->text()); +- s.setValue("password", ui_->password->text()); +- +- s.setValue("bitrate", ui_->bitrate->itemData(ui_->bitrate->currentIndex()).toInt()); +- s.setValue("volume_normalisation", ui_->volume_normalisation->isChecked()); +-} +- +-void SpotifySettingsPage::LoginFinished(bool success) { +- validated_ = success; +- +- Save(); +- UpdateLoginState(); +-} +- +-void SpotifySettingsPage::UpdateLoginState() { +- const bool logged_in = +- service_->login_state() == SpotifyService::LoginState_LoggedIn; +- +- ui_->login_state->SetLoggedIn(logged_in ? LoginStateWidget::LoggedIn +- : LoginStateWidget::LoggedOut, +- ui_->username->text()); +- ui_->login_state->SetAccountTypeVisible(!logged_in); +- +- switch (service_->login_state()) { +- case SpotifyService::LoginState_NoPremium: +- ui_->login_state->SetAccountTypeText(tr("You do not have a Spotify Premium account.")); +- break; +- +- case SpotifyService::LoginState_Banned: +- case SpotifyService::LoginState_BadCredentials: +- ui_->login_state->SetAccountTypeText(tr("Your username or password was incorrect.")); +- break; +- +- case SpotifyService::LoginState_ReloginFailed: +- ui_->login_state->SetAccountTypeText(tr("You have been logged out of Spotify, please re-enter your password.")); +- break; +- +- default: +- ui_->login_state->SetAccountTypeText(tr("A Spotify Premium account is required.")); +- break; +- } +-} +- +-void SpotifySettingsPage::Logout() { +- service_->Logout(); +- UpdateLoginState(); +- +- ui_->username->clear(); +-} +diff -rauN clementine-1.0.1/src/internet/spotifysettingspage.h /dev/null +--- clementine-1.0.1/src/internet/spotifysettingspage.h 2011-12-02 19:24:44.000000000 -0200 ++++ /dev/null 2012-05-28 12:50:04.796939473 -0300 +@@ -1,59 +0,0 @@ +-/* This file is part of Clementine. +- Copyright 2010, David Sansome <me@davidsansome.com> +- +- Clementine 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 3 of the License, or +- (at your option) any later version. +- +- Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>. +-*/ +- +-#ifndef SPOTIFYSETTINGSPAGE_H +-#define SPOTIFYSETTINGSPAGE_H +- +-#include "ui/settingspage.h" +- +-class NetworkAccessManager; +-class Ui_SpotifySettingsPage; +-class SpotifyService; +- +-class SpotifySettingsPage : public SettingsPage { +- Q_OBJECT +- +-public: +- SpotifySettingsPage(SettingsDialog* dialog); +- ~SpotifySettingsPage(); +- +- void Load(); +- void Save(); +- +-public slots: +- void BlobStateChanged(); +- void DownloadBlob(); +- +-private slots: +- void Login(); +- void LoginFinished(bool success); +- void Logout(); +- +-private: +- void UpdateLoginState(); +- +-private: +- NetworkAccessManager* network_; +- Ui_SpotifySettingsPage* ui_; +- SpotifyService* service_; +- +- bool validated_; +- QString original_username_; +- QString original_password_; +-}; +- +-#endif // SPOTIFYSETTINGSPAGE_H +diff -rauN clementine-1.0.1/src/internet/spotifysettingspage.ui /dev/null +--- clementine-1.0.1/src/internet/spotifysettingspage.ui 2011-12-02 19:24:44.000000000 -0200 ++++ /dev/null 2012-05-28 12:50:04.796939473 -0300 +@@ -1,214 +0,0 @@ +-<?xml version="1.0" encoding="UTF-8"?> +-<ui version="4.0"> +- <class>SpotifySettingsPage</class> +- <widget class="QWidget" name="SpotifySettingsPage"> +- <property name="geometry"> +- <rect> +- <x>0</x> +- <y>0</y> +- <width>545</width> +- <height>458</height> +- </rect> +- </property> +- <property name="windowTitle"> +- <string>Spotify</string> +- </property> +- <layout class="QVBoxLayout" name="verticalLayout_2"> +- <item> +- <widget class="LoginStateWidget" name="login_state" native="true"/> +- </item> +- <item> +- <widget class="QGroupBox" name="account_group"> +- <property name="title"> +- <string>Account details</string> +- </property> +- <layout class="QVBoxLayout" name="verticalLayout_3"> +- <item> +- <widget class="QWidget" name="login_container" native="true"> +- <property name="enabled"> +- <bool>true</bool> +- </property> +- <layout class="QGridLayout" name="gridLayout"> +- <property name="margin"> +- <number>0</number> +- </property> +- <item row="1" column="0"> +- <widget class="QLabel" name="username_label"> +- <property name="text"> +- <string>Username</string> +- </property> +- </widget> +- </item> +- <item row="1" column="1"> +- <widget class="QLineEdit" name="username"/> +- </item> +- <item row="2" column="0"> +- <widget class="QLabel" name="password_label"> +- <property name="text"> +- <string>Password</string> +- </property> +- </widget> +- </item> +- <item row="2" column="1" colspan="2"> +- <widget class="QLineEdit" name="password"> +- <property name="echoMode"> +- <enum>QLineEdit::Password</enum> +- </property> +- </widget> +- </item> +- <item row="1" column="2"> +- <widget class="QPushButton" name="login"> +- <property name="text"> +- <string>Login</string> +- </property> +- </widget> +- </item> +- </layout> +- </widget> +- </item> +- </layout> +- </widget> +- </item> +- <item> +- <widget class="QGroupBox" name="groupBox_2"> +- <property name="title"> +- <string>Spotify plugin</string> +- </property> +- <layout class="QVBoxLayout" name="verticalLayout"> +- <item> +- <widget class="QLabel" name="label"> +- <property name="text"> +- <string>For licensing reasons Spotify support is in a separate plugin.</string> +- </property> +- </widget> +- </item> +- <item> +- <layout class="QHBoxLayout" name="horizontalLayout_2"> +- <item> +- <widget class="QLabel" name="label_2"> +- <property name="text"> +- <string>Plugin status:</string> +- </property> +- </widget> +- </item> +- <item> +- <widget class="QLabel" name="blob_status"/> +- </item> +- <item> +- <spacer name="horizontalSpacer"> +- <property name="orientation"> +- <enum>Qt::Horizontal</enum> +- </property> +- <property name="sizeHint" stdset="0"> +- <size> +- <width>40</width> +- <height>20</height> +- </size> +- </property> +- </spacer> +- </item> +- <item> +- <widget class="QPushButton" name="download_blob"> +- <property name="text"> +- <string>Download...</string> +- </property> +- </widget> +- </item> +- </layout> +- </item> +- </layout> +- </widget> +- </item> +- <item> +- <widget class="QGroupBox" name="groupBox"> +- <property name="title"> +- <string>Preferences</string> +- </property> +- <layout class="QFormLayout" name="formLayout"> +- <item row="0" column="0"> +- <widget class="QLabel" name="label_4"> +- <property name="text"> +- <string>Preferred bitrate</string> +- </property> +- </widget> +- </item> +- <item row="0" column="1"> +- <widget class="QComboBox" name="bitrate"/> +- </item> +- <item row="1" column="0" colspan="2"> +- <widget class="QCheckBox" name="volume_normalisation"> +- <property name="text"> +- <string>Use volume normalisation</string> +- </property> +- </widget> +- </item> +- </layout> +- </widget> +- </item> +- <item> +- <spacer name="verticalSpacer"> +- <property name="orientation"> +- <enum>Qt::Vertical</enum> +- </property> +- <property name="sizeHint" stdset="0"> +- <size> +- <width>20</width> +- <height>30</height> +- </size> +- </property> +- </spacer> +- </item> +- <item> +- <layout class="QHBoxLayout" name="horizontalLayout_3"> +- <item> +- <spacer name="horizontalSpacer_2"> +- <property name="orientation"> +- <enum>Qt::Horizontal</enum> +- </property> +- <property name="sizeHint" stdset="0"> +- <size> +- <width>40</width> +- <height>20</height> +- </size> +- </property> +- </spacer> +- </item> +- <item> +- <widget class="QLabel" name="label_3"> +- <property name="minimumSize"> +- <size> +- <width>64</width> +- <height>64</height> +- </size> +- </property> +- <property name="maximumSize"> +- <size> +- <width>64</width> +- <height>64</height> +- </size> +- </property> +- <property name="pixmap"> +- <pixmap resource="../../data/data.qrc">:/spotify-core-logo-128x128.png</pixmap> +- </property> +- <property name="scaledContents"> +- <bool>true</bool> +- </property> +- </widget> +- </item> +- </layout> +- </item> +- </layout> +- </widget> +- <customwidgets> +- <customwidget> +- <class>LoginStateWidget</class> +- <extends>QWidget</extends> +- <header>widgets/loginstatewidget.h</header> +- <container>1</container> +- </customwidget> +- </customwidgets> +- <resources> +- <include location="../../data/data.qrc"/> +- </resources> +- <connections/> +-</ui> +diff -rauN clementine-1.0.1/src/ui/about.cpp clementine-libre-1.0.1/src/ui/about.cpp +--- clementine-1.0.1/src/ui/about.cpp 2012-01-22 10:43:26.000000000 -0200 ++++ clementine-libre-1.0.1/src/ui/about.cpp 2012-05-28 19:44:38.760244927 -0300 +@@ -79,12 +79,6 @@ + ret += QString("<br /><a href=\"http://www.smitelli.com/?page=blog&p=54\">Scott Smitelli</a>"); + ret += QString("<br /><a href=\"http://hyperboleandahalf.blogspot.com\">Allie Brosh</a></p>"); + +-#ifdef HAVE_SPOTIFY +- ret += "<p>This product uses SPOTIFY(R) CORE but is not endorsed, certified " +- "or otherwise approved in any way by Spotify. Spotify is the " +- "registered trade mark of the Spotify Group.</p>"; +-#endif // HAVE_SPOTIFY +- + return ret; + } + +diff -rauN clementine-1.0.1/src/ui/settingsdialog.cpp clementine-libre-1.0.1/src/ui/settingsdialog.cpp +--- clementine-1.0.1/src/ui/settingsdialog.cpp 2011-12-02 19:24:44.000000000 -0200 ++++ clementine-libre-1.0.1/src/ui/settingsdialog.cpp 2012-05-28 19:46:49.506369764 -0300 +@@ -55,10 +55,6 @@ + # include "remote/remotesettingspage.h" + #endif + +-#ifdef HAVE_SPOTIFY +-# include "internet/spotifysettingspage.h" +-#endif +- + #include <QDesktopWidget> + #include <QPainter> + #include <QPushButton> +@@ -140,10 +136,6 @@ + + AddPage(Page_Grooveshark, new GroovesharkSettingsPage(this), providers); + +-#ifdef HAVE_SPOTIFY +- AddPage(Page_Spotify, new SpotifySettingsPage(this), providers); +-#endif +- + AddPage(Page_Magnatune, new MagnatuneSettingsPage(this), providers); + AddPage(Page_DigitallyImported, new DigitallyImportedSettingsPage(this), providers); + AddPage(Page_BackgroundStreams, new BackgroundStreamsSettingsPage(this), providers); +diff -rauN clementine-1.0.1/src/ui/settingsdialog.h clementine-libre-1.0.1/src/ui/settingsdialog.h +--- clementine-1.0.1/src/ui/settingsdialog.h 2011-12-02 19:24:44.000000000 -0200 ++++ clementine-libre-1.0.1/src/ui/settingsdialog.h 2012-05-28 19:48:55.399426104 -0300 +@@ -65,7 +65,6 @@ + Page_Library, + Page_Lastfm, + Page_Grooveshark, +- Page_Spotify, + Page_Magnatune, + Page_DigitallyImported, + Page_BackgroundStreams, +--- clementine-1.0.1/src/core/logging.cpp 2011-12-02 19:24:43.000000000 -0200 ++++ clementine-libre-1.0.1/src/core/logging.cpp 2012-05-30 03:09:25.554790760 -0300 +@@ -14,10 +14,6 @@ + limitations under the License. + */ + +-// Note: this file is licensed under the Apache License instead of GPL because +-// it is used by the Spotify blob which links against libspotify and is not GPL +-// compatible. +- + + #include <QCoreApplication> + #include <QDateTime> +--- clementine-1.0.1/src/core/logging.h 2011-12-02 19:24:43.000000000 -0200 ++++ clementine-libre-1.0.1/src/core/logging.h 2012-05-30 03:09:44.390404481 -0300 +@@ -14,10 +14,6 @@ + limitations under the License. + */ + +-// Note: this file is licensed under the Apache License instead of GPL because +-// it is used by the Spotify blob which links against libspotify and is not GPL +-// compatible. +- + + #ifndef LOGGING_H + #define LOGGING_H +--- clementine-1.0.1/src/core/timeconstants.h 2011-12-02 19:24:44.000000000 -0200 ++++ clementine-libre-1.0.1/src/core/timeconstants.h 2012-05-30 03:10:10.338953893 -0300 +@@ -14,10 +14,6 @@ + limitations under the License. + */ + +-// Note: this file is licensed under the Apache License instead of GPL because +-// it is used by the Spotify blob which links against libspotify and is not GPL +-// compatible. +- + #ifndef TIMECONSTANTS_H + #define TIMECONSTANTS_H + |