1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-09-08 21:20:45 +02:00

Compare commits

...

180 Commits
qt4 ... 0.3.3

Author SHA1 Message Date
Christian Muehlhaeuser
98416fab64 * Added german, spanish and polish translations. 2011-12-07 08:54:40 +01:00
Christian Muehlhaeuser
0917269b55 * Fixed button label. 2011-12-07 07:56:52 +01:00
Christian Muehlhaeuser
9321369194 * Merged from master. 2011-12-07 07:22:36 +01:00
Christian Muehlhaeuser
3b55336f69 * Query's toString() supports fulltext search queries, now. 2011-12-05 21:15:48 +01:00
Christian Muehlhaeuser
a35a2f371b * Slight optimation. 2011-12-05 21:14:16 +01:00
Christian Muehlhaeuser
2b6bc8f8d3 * Don't prioritize album-less tracks in edge cases. 2011-12-05 21:14:03 +01:00
Christian Muehlhaeuser
c20ebbb8bd * In Collection view with filter set: Don't jump to the selected item when expanding an artist. 2011-12-05 21:13:46 +01:00
Christian Muehlhaeuser
93245923d8 * Moved Attica to port 80. 2011-12-05 21:13:03 +01:00
Christian Muehlhaeuser
96dc260e4b * Fixed another sidebar issue with gtk styles. 2011-12-05 21:12:47 +01:00
Christian Muehlhaeuser
9fdfb3aad6 * Fixed sidebar issues with gtk styles. 2011-12-05 21:12:40 +01:00
Christian Muehlhaeuser
fafd8158cc * Upped version to 0.3.3. 2011-12-04 09:07:16 +01:00
Christian Muehlhaeuser
bd90f292e5 * URL encode the mpris2 ArtUrl. 2011-12-04 08:09:27 +01:00
Christian Muehlhaeuser
88f59aafb8 * Potential fix for TWK-618: ArtUrl not properly encoded. 2011-12-04 08:09:27 +01:00
Christian Muehlhaeuser
41f3521042 * Remove nonsense. 2011-12-04 07:34:24 +01:00
Christian Muehlhaeuser
a11c2d1bd5 * Give instant user feedback when scanner gets kicked off. 2011-12-04 07:34:14 +01:00
Christian Muehlhaeuser
797412efa5 * Updated ChangeLog. 2011-12-04 06:41:58 +01:00
Christian Muehlhaeuser
f6156786c6 * Fixed merging error. 2011-12-04 06:40:34 +01:00
Christian Muehlhaeuser
b8f57db684 * Renamed Tomahawk / Music Player menu to Controls. Let's see how that feels cross-platform. 2011-12-04 06:21:15 +01:00
Leo Franchi
da4527b0b6 More regression hunting: fix dynamic playlist spinner disappearing prematurely 2011-12-04 06:21:09 +01:00
Leo Franchi
0bf61e05fd Fix regression from model refactor that changed function name 2011-12-04 06:21:02 +01:00
Christian Muehlhaeuser
b5f57d6baa * Fixed tomahawk:// protocol handler on Windows (Firefox related). 2011-12-04 06:20:54 +01:00
Christian Muehlhaeuser
a628fad2f4 * Merged from master. 2011-12-04 06:20:43 +01:00
Christian Muehlhaeuser
0c496937d7 * Merged from master. 2011-12-04 06:19:54 +01:00
Christian Muehlhaeuser
a69f40aac1 * Show an error dialog when a playback problem occurred. 2011-12-04 06:18:25 +01:00
Christian Muehlhaeuser
cb9b11a39a * Merged from master. 2011-12-04 06:18:11 +01:00
Dominik Schmidt
8a83f642b1 Fix opening URLs with gvfs-open, why does firefox ignore it? why does epiphany ignore it? ... 2011-12-04 06:17:30 +01:00
Dominik Schmidt
a812be4200 Boo for too pedantic desktop-file-validate 2011-12-04 06:17:08 +01:00
Dominik Schmidt
97755e1dcb Remove now unneeded files from windows installer 2011-12-04 06:16:34 +01:00
Dominik Schmidt
9109047460 Use new phonon(-vlc) builds in update-vlc.sh, yay for umlauts and no-track-skipping (hopefully) 2011-12-04 06:16:25 +01:00
Christian Muehlhaeuser
6ae58e15dd * Don't accept 0.0.0.0 as a visible / valid address. 2011-12-04 06:16:12 +01:00
Christian Muehlhaeuser
e1acbbe769 * Proper fix for TWK-422. 2011-12-04 06:16:05 +01:00
Christian Muehlhaeuser
c03abede4a * Potential fix for TWK-422: Disappearing (white on white) sidebar items for some styles (e.g. gtk/gnome). 2011-12-04 06:15:58 +01:00
Christian Muehlhaeuser
a4d1dd4ffa * Updated German translation. 2011-12-04 06:15:32 +01:00
Christian Muehlhaeuser
91a6e737dd * Updated German translation. 2011-12-04 06:15:25 +01:00
Leo Franchi
bf9af4d350 remove unneeded debug 2011-12-04 06:15:17 +01:00
Christian Muehlhaeuser
05e2b95984 * Fixing assert in JobStatusModel. 2011-12-04 06:15:08 +01:00
Christian Muehlhaeuser
604a84b8ba * Merged from master. 2011-12-04 06:14:51 +01:00
Christian Muehlhaeuser
2bdb2c3edb * More natural job view order. 2011-12-04 06:13:22 +01:00
Christian Muehlhaeuser
0a44e0c24a * Animate the JobStatusView when it changes its size. 2011-12-04 06:13:10 +01:00
Christian Muehlhaeuser
5ab40b2d17 * Merged from master. 2011-12-04 06:12:57 +01:00
Christian Muehlhaeuser
dd2d82729d * Added a splitter to SourceInfoWidget. 2011-12-04 06:12:06 +01:00
Christian Muehlhaeuser
88e8a62770 * Merged from master. 2011-12-04 06:11:55 +01:00
Christian Muehlhaeuser
d15bc8a082 * Fixed TWK-556: Auto switch to super collection mode if we don't have any 'offical' information available. 2011-12-04 06:09:51 +01:00
Christian Muehlhaeuser
7513ea123b * Fixed TWK-559: Be more consistent with our GUI text. 2011-12-04 06:09:38 +01:00
Christian Muehlhaeuser
a34dc1ae4e * Support Footnotes in TreeViews. 2011-12-04 06:08:44 +01:00
Christian Muehlhaeuser
7b8f6cea3a * Center overlay widgets before showing them the first time. 2011-12-04 06:08:30 +01:00
Christian Muehlhaeuser
c08de32713 * Added a few overlay info messages. 2011-12-04 06:08:20 +01:00
Christian Muehlhaeuser
5cd69c4a2a * Merged from master. 2011-12-04 06:07:40 +01:00
Leo Franchi
5a2ea98bce Remove upcoming tracks not from selected but from playing item 2011-12-04 06:06:45 +01:00
Leo Franchi
e231a13066 Update the tree on mac after /Volumes is shown to avoid a race condition 2011-12-04 06:06:33 +01:00
Christian Muehlhaeuser
06f597ab1f * Merged from master. 2011-12-04 06:05:38 +01:00
Christian Muehlhaeuser
c8ce81bdb0 * Merged from master. 2011-12-04 06:02:18 +01:00
Christian Muehlhaeuser
f1cc16be15 * Updated german and english translations. 2011-12-04 06:00:48 +01:00
Dominik Schmidt
d42eb6d364 Add MimeType=x-scheme-handler/tomahawk to tomahawk.desktop 2011-11-29 13:45:56 +01:00
Christian Muehlhaeuser
ba4fa88a65 * Fixed a few more translations. Could fix TWK-591. 2011-11-24 08:28:48 +01:00
Frank Osterfeld
caa64f9e89 * Merge warning fixes. 2011-11-24 08:27:40 +01:00
Christian Muehlhaeuser
a05972e9ce * Fixed merge. 2011-11-24 02:47:15 +01:00
Christian Muehlhaeuser
5157e13ba1 * Updated ChangeLog. 2011-11-24 01:48:58 +01:00
Christian Muehlhaeuser
9f97afc148 * Updated ChangeLog. 2011-11-24 01:47:48 +01:00
Christian Muehlhaeuser
8b1b0091c6 * Updated ChangeLog. 2011-11-24 01:46:42 +01:00
Christian Muehlhaeuser
3e9aee3687 * Use default locale if translation can't be found. 2011-11-24 01:35:10 +01:00
Christian Muehlhaeuser
48bb0a82f9 * Disable UbuntuUnityHack until it's working properly. 2011-11-24 01:35:03 +01:00
Christian Muehlhaeuser
1efdf38085 * Disable german translation for 0.3.2 release. Needs be updated. 2011-11-24 01:20:01 +01:00
Christian Muehlhaeuser
3e4f4d2f38 * Updated verison to 0.3.2. 2011-11-23 23:31:02 +01:00
Jason Herskowitz
a2f870f2b8 Update changelog 2011-11-23 23:26:35 +01:00
Christian Muehlhaeuser
2ac167d438 * Support .oga files (ogg mimetype). 2011-11-23 23:26:21 +01:00
Christian Muehlhaeuser
c218695a3d * Prevent stuck now playing indicator. 2011-11-23 23:26:13 +01:00
Christian Muehlhaeuser
fae5f1dbbe * Should hopefully fix Windows SettingsDialog. 2011-11-23 23:25:57 +01:00
Christian Muehlhaeuser
54d29cc05d * Try fixing SettingsDialog on Windows. 2011-11-23 23:25:45 +01:00
Christian Muehlhaeuser
5aea02def2 * Forgot to rename crash reporter in one more place. 2011-11-23 23:25:35 +01:00
Christian Muehlhaeuser
368aa20b75 * Updated new crash reporter binary name in release scripts. 2011-11-23 23:25:26 +01:00
Christian Muehlhaeuser
d2a07f2b6c * Call ensurePolished before creating buttons in SettingsDialog. 2011-11-23 23:25:08 +01:00
Christian Muehlhaeuser
14253a9c66 * DRY: Cleaned up DropJob / ShortenedLinkParser & handling spoti.fi urls now. 2011-11-23 23:25:02 +01:00
Christian Muehlhaeuser
6881f4218a * Moved charts & spotify parser to port 80. 2011-11-23 23:23:57 +01:00
Christian Muehlhaeuser
17badb972e * Prevented over-zealous assert in PlaylistModel. 2011-11-23 23:23:50 +01:00
Christian Muehlhaeuser
2ea09dd60d * Merged version check. 2011-11-23 23:22:00 +01:00
Christian Muehlhaeuser
87f7b6b2c6 * Made sure we don't duplicate connections in WelcomeWidget. 2011-11-23 23:15:52 +01:00
Christian Muehlhaeuser
01986a4129 * Use the proper color for selected playlist items on the Dashboard. 2011-11-23 23:15:43 +01:00
Christian Muehlhaeuser
2b404b517f * Use the proper highlight color for painting hovered artist names in the AlbumItemDelegate. 2011-11-23 23:15:32 +01:00
Christian Muehlhaeuser
b21b2d10f7 * Update SourceInfoWidget when collection changes. 2011-11-23 23:15:22 +01:00
Christian Muehlhaeuser
04deaba788 * Less furious logging. 2011-11-23 23:15:10 +01:00
Christian Muehlhaeuser
5cabc62733 * Update recent additions on welcome page whenever a collection changes. 2011-11-23 23:15:02 +01:00
Kuba Serafinowski
01c6c3f0b6 moar strings to translate! 2011-11-23 23:14:42 +01:00
Kuba Serafinowski
b1a5cd4dcb remove unneeded strings 2011-11-23 23:14:28 +01:00
Kuba Serafinowski
58f78725db tiny typo fix 2011-11-23 23:14:11 +01:00
Jeff Mitchell
4210e8eab8 Hopefully fix a case where the seek slider travels on when Phonon is
buffering
2011-11-23 23:13:49 +01:00
Thierry Goeckel
115492d1cc Enhance version upgrading to include a third point. 2011-11-23 23:13:21 +01:00
Leo Franchi
edadbb0c95 Fix loading XSPFs with spaces in their name. 2011-11-23 23:13:11 +01:00
Christian Muehlhaeuser
6c67dfcab7 * Revert back to using system locale. 2011-11-23 23:12:50 +01:00
Christian Muehlhaeuser
b9453ab77b * Add a default english translation. Fallback to 'en' if locale is set to 'C'. 2011-11-23 23:12:39 +01:00
Christian Muehlhaeuser
9507ffdd86 * Fixed translation issue in TomahawkUtils. 2011-11-23 23:12:26 +01:00
Christian Muehlhaeuser
ff768954f6 * Fixed window title in AudioControls. 2011-11-23 23:12:17 +01:00
Christian Muehlhaeuser
15729bb66a * Increased size of Get-New-Resolvers dialog. 2011-11-23 23:12:01 +01:00
Christian Muehlhaeuser
41f46aaeea * Cleanup scanner if there were no new and no obsolete tracks found. 2011-11-23 23:11:53 +01:00
Christian Muehlhaeuser
9e0d884f80 * Merge musicscanner changes into stable. 2011-11-23 23:11:16 +01:00
Christian Muehlhaeuser
d34491b85f * Re-enable grouping of dynamic playlist revisions. 2011-11-23 23:10:34 +01:00
Christian Muehlhaeuser
45070fb4e1 * Remove bottom label of steering controls. Changes now take effect on clicking the apply button. 2011-11-23 23:10:27 +01:00
Christian Muehlhaeuser
18612b48d3 * Don't remove current index when restarting a track by activating it directly.
* Don't create new playlist revisions for a list that doesn't belong to you.
2011-11-23 23:10:18 +01:00
Christian Muehlhaeuser
a38c0a544d * Fixed crashing on playing from queue. 2011-11-23 23:10:06 +01:00
Christian Muehlhaeuser
d38c9730fb * Merge into stable. 2011-11-23 23:09:32 +01:00
Christian Muehlhaeuser
d25320833c * Merged into stable. 2011-11-23 23:06:02 +01:00
Christian Muehlhaeuser
d38600dd6a * Don't overwrite friendlyname with an empty one. 2011-11-23 23:05:23 +01:00
Christian Muehlhaeuser
6fa48587e1 * Assert on empty friendlynames. 2011-11-23 23:05:12 +01:00
Leo Franchi
8da0f3e9a3 * Merged into stable. 2011-11-23 23:04:58 +01:00
Kilian Lackhove
ab402c0867 fix xspf import QFileDialog filter 2011-11-23 23:00:43 +01:00
Kuba Serafinowski
545a915439 fix TWK-583 for jabber too 2011-11-23 23:00:31 +01:00
Kuba Serafinowski
d026902d91 fix for TWK-583 2011-11-23 23:00:25 +01:00
Hugo Lindström
ff72157c5f Fix for broken compile 2011-11-23 23:00:05 +01:00
Christian Muehlhaeuser
faab306dbe * Merged friendlyname fixes. 2011-11-23 22:59:57 +01:00
Christian Muehlhaeuser
57fef9f3f2 * Fixed WelcomeWidget. 2011-11-23 22:57:44 +01:00
Leo Franchi
89fac77951 Fix one compile error 2011-11-23 22:57:36 +01:00
Christian Muehlhaeuser
ef02e9b4ac * Refactored Track-, Collection-, PlaylistModel. 2011-11-23 22:57:24 +01:00
Leo Franchi
99b09c1faa Increment job count when creating a new xspf job 2011-11-23 22:55:17 +01:00
Kuba Serafinowski
d66e86f5c6 make the string extract with lupdate 2011-11-23 22:54:59 +01:00
Kuba Serafinowski
9bd46984e0 match the text with buttons in the dialog 2011-11-23 22:54:51 +01:00
Hugo Lindström
3992392245 * Merge appending XSPFs. 2011-11-23 22:54:32 +01:00
Hugo Lindström
198e92bc2c Fix for local xspf dropjob, also allow remotes 2011-11-23 22:53:22 +01:00
Kuba Serafinowski
2f899eed2a fix misleading cmake message 2011-11-23 22:52:49 +01:00
Jeff Mitchell
8cdd4bdea3 Do the connection name fixing in a different way; always end up with a
QHostAddress.
2011-11-23 22:52:39 +01:00
Jeff Mitchell
3d53b0c251 Remove some debugging 2011-11-23 22:52:23 +01:00
Jeff Mitchell
0ac9512eb9 Lots of debug and half the fixes for fixing hostnames 2011-11-23 22:52:15 +01:00
Jeff Mitchell
3f0ac7c666 * Merge application proxy factory. 2011-11-23 22:52:13 +01:00
Christian Muehlhaeuser
faf7d00fdd * Fixed TWK-579: Proper default width for the sidebar. 2011-11-23 22:50:32 +01:00
Christian Muehlhaeuser
b31abb0979 * This should fix sources being stuck in 'Parsing'. 2011-11-23 22:50:25 +01:00
Thierry Göckel
f2009cf99b Fix returning of external IP address for some routers. 2011-11-23 22:49:29 +01:00
Hugo Lindström
0d97a47cc5 Add cache for all charts. Later on move spotify and hypem to charts api. 2011-11-23 22:49:17 +01:00
Hugo Lindström
7db6beb896 Adding cache for charts 2011-11-23 22:48:54 +01:00
Christian Muehlhaeuser
e56a629ad7 * Fixed negative time values showing up in GUI. 2011-11-23 22:48:28 +01:00
Christian Muehlhaeuser
ef918bbbcf * Make SetPlaylistRevision DBCmds groupable. 2011-11-23 22:48:13 +01:00
Christian Muehlhaeuser
60911ab887 * Set stats for the right collection. 2011-11-23 22:47:49 +01:00
Christian Muehlhaeuser
e10a96ecd5 * Merged groupable db-commands. 2011-11-23 22:47:17 +01:00
Christian Muehlhaeuser
e99973925a * Merged improved collection syncing. 2011-11-23 22:45:52 +01:00
Dominik Schmidt
949c6f6341 Unbreak FindCLucene for Fedora 16 and openSUSE Factory. 2011-11-23 06:35:39 +01:00
Dominik Schmidt
e041723ffc Install CrashReporter 2011-11-23 06:07:54 +01:00
Christian Muehlhaeuser
89919928da * Look for CrashReporter in local and global dirs. 2011-11-23 05:49:34 +01:00
Leo Franchi
d4fc504f3d Add a 0.3.2 changelog 2011-11-20 22:52:11 -05:00
Leo Franchi
05924b8deb TWK-531: Show (-) on new item after deleting an item 2011-11-20 22:43:20 -05:00
Leo Franchi
6d4aa50596 Clear upcoming station tracks when steering, and re-fetch two 2011-11-20 22:43:08 -05:00
Leo Franchi
7ee2755617 use QFileSystemModel instead of deprecated QDirModel, and show /Volumes on mac 2011-11-20 22:43:00 -05:00
Leo Franchi
35406ceb5a Use plugins/ instead of PlugIns/ as vlc hard-codes it internally. 2011-11-20 22:42:52 -05:00
Leo Franchi
9efb536e55 Show tooltip with full text in job view 2011-11-20 22:42:30 -05:00
Leo Franchi
b8d27f1811 Make clicking back to current track work on dashboard, charts, and artist/album pages 2011-11-20 22:42:23 -05:00
Leo Franchi
0939ba0705 Don't show speaker next to a playlist if not paused or playing 2011-11-20 22:42:03 -05:00
Leo Franchi
3788bc7cbf Always clear spinner when no albums found to load in albumview 2011-11-20 22:41:52 -05:00
Leo Franchi
54723abc07 Only show JS errors in tomahawk debug builds 2011-11-20 22:41:36 -05:00
Leo Franchi
900f57437f Put delcaration in ifdef 2011-11-20 22:40:51 -05:00
Leo Franchi
300c9d5d68 Automatically upgrade resolvers 2011-11-20 22:40:44 -05:00
Leo Franchi
96c9996284 Set the timer with track duration calculated in 2011-11-17 09:49:43 -05:00
Leo Franchi
8a15bcaa66 fix rdio track loading 2011-11-17 09:49:16 -05:00
Leo Franchi
d17d67869c Add an "apply steering" button to make it clearer how to steer
Remove some super spammy debug
2011-11-17 09:49:11 -05:00
Leo Franchi
c491f33ce4 Manually replace + with " " as QUrl::queryItems doesn't do it for us... 2011-11-17 09:49:06 -05:00
Leo Franchi
1dee5c809c Don't hook up signals twice for loading xspf 2011-11-17 09:49:00 -05:00
Leo Franchi
924ede61b4 Make surer to show playlist once loaded 2011-11-17 09:48:52 -05:00
Leo Franchi
0d64d9c42d Don't show drop indicator for playlists in sidebar and always create new ones 2011-11-17 09:48:44 -05:00
Leo Franchi
6b6fb909cd Make source visible in audiocontrols on os x 2011-11-17 09:48:35 -05:00
Leo Franchi
b51ff46085 Don't create QNRs for null urls, let audioengine handle it properly 2011-11-17 09:48:07 -05:00
Leo Franchi
46ec23990f Revert "Skip to next track if we have a QNR and it emits a failed signal"
This reverts commit 9418fd0fb8.
2011-11-17 09:47:59 -05:00
Jeff Mitchell
eb46feac2c Handle the worker/cache threads better in InfoSystem, and re-enable
deletion on shutdown, so we can test in windows nightlies.
2011-11-16 20:19:13 -05:00
Leo Franchi
2c206f4193 Shrink font for playlist author 2011-11-14 18:07:56 -05:00
Leo Franchi
c1bd19b35b Don't accept button press events as well as release when handling latches 2011-11-14 18:06:58 -05:00
Jeff Mitchell
370154cc46 hacky fix for Jreen needing the application proxy set. Really we need to
get them to accept their own QNAM
2011-11-14 18:06:50 -05:00
Leo Franchi
9a81ce8b89 Add 0.3.1 fixes to Changelog 2011-11-13 14:07:37 -05:00
Christian Muehlhaeuser
c805d283d4 * Updated ChangeLog and bumped version to 0.3.1. 2011-11-13 19:25:53 +01:00
Christian Muehlhaeuser
03379f361c * Force an index update after 0.3.1 upgrade. 2011-11-13 19:19:36 +01:00
Christian Muehlhaeuser
c671c0e898 * 'Fixed' Windows shutdown crash. 2011-11-13 19:19:25 +01:00
Christian Muehlhaeuser
edaf49b4c5 * Fixed creating index when there is only a local source. 2011-11-13 19:19:02 +01:00
Christian Muehlhaeuser
682903b0cb * Prevent watch for changes interfering with running scan. 2011-11-13 19:18:49 +01:00
Dominik Schmidt
53f7f599d5 Update ChangeLog 2011-11-13 17:31:16 +01:00
Dominik Schmidt
cc669fc20f Remove unneccessary toString conversion 2011-11-13 17:26:43 +01:00
Dominik Schmidt
4e7496a38a Search for *_tomahawkresolver in CMAKE_INSTALL_LIBEXECDIR 2011-11-13 15:40:39 +01:00
Leo Franchi
5842cdceee Only do setenv on linux, that's theonly time we'll have unity anyway
(cherry picked from commit 09a7d790ad)
2011-11-12 10:04:31 -05:00
Leo Franchi
b7e0be8d9d Hide red latch headphones on local source if the source you are latched on to goes offline
(cherry picked from commit d49a43709d)
2011-11-12 10:04:25 -05:00
Leo Franchi
a203b60cbb Add Unity systray hack from Clementine.
(cherry picked from commit 96fe10cc9f)
2011-11-12 10:04:20 -05:00
Leo Franchi
2be08af321 Draw the author name as well as avatar in recent playlists
(cherry picked from commit 2a27cbde0d)
2011-11-12 10:04:12 -05:00
Leo Franchi
ad4c229a6b Don't show in global menu in unity. Thanks davidsansome :)
(cherry picked from commit 1f10444d5c)
2011-11-12 10:04:06 -05:00
Leo Franchi
b2e0206e34 Be a bit more resilient in setting the playlist to rename after creating
(cherry picked from commit 1bb8ff97d4)
2011-11-12 10:04:00 -05:00
Leo Franchi
743ae013ea Don't select a temp item when deleting it
(cherry picked from commit 518546b525)
2011-11-12 10:03:54 -05:00
Leo Franchi
767cf7c1b9 Hide warning
(cherry picked from commit 17e1003714)
2011-11-12 10:03:47 -05:00
Leo Franchi
6be94ab81c Stop the timer on new track starting
(cherry picked from commit 3c024ab7ac)
2011-11-12 10:02:03 -05:00
Leo Franchi
b1ed304a61 Fix crash on Sparkle update when binary is replaced.
(cherry picked from commit f9b5bda925)
2011-11-11 11:04:30 -05:00
217 changed files with 15400 additions and 2579 deletions

View File

@@ -16,7 +16,7 @@ SET( TOMAHAWK_DESCRIPTION_SUMMARY "The social media player" )
SET( TOMAHAWK_VERSION_MAJOR 0 ) SET( TOMAHAWK_VERSION_MAJOR 0 )
SET( TOMAHAWK_VERSION_MINOR 3 ) SET( TOMAHAWK_VERSION_MINOR 3 )
SET( TOMAHAWK_VERSION_PATCH 0 ) SET( TOMAHAWK_VERSION_PATCH 3 )
#SET( TOMAHAWK_VERSION_RC 0 ) #SET( TOMAHAWK_VERSION_RC 0 )
@@ -108,7 +108,7 @@ macro_optional_find_package(LibAttica)
macro_log_feature(LIBATTICA_FOUND "libattica" "Provides support for automatic fetching and managing of resolvers from the tomahawk website" "https://projects.kde.org/projects/kdesupport/attica" FALSE "" "") macro_log_feature(LIBATTICA_FOUND "libattica" "Provides support for automatic fetching and managing of resolvers from the tomahawk website" "https://projects.kde.org/projects/kdesupport/attica" FALSE "" "")
macro_optional_find_package(QuaZip) macro_optional_find_package(QuaZip)
macro_log_feature(QuaZip_FOUND "QuaZip" "Provides support for extracting downloaded resolvers autmatically. Will build internal copy instead." "http://quazip.sourceforge.net/" FALSE "" "") macro_log_feature(QuaZip_FOUND "QuaZip" "Provides support for extracting downloaded resolvers automatically." "http://quazip.sourceforge.net/" FALSE "" "")
IF( NOT QuaZip_FOUND ) IF( NOT QuaZip_FOUND )
add_subdirectory( ${CMAKE_SOURCE_DIR}/src/libtomahawk/thirdparty/quazip ) add_subdirectory( ${CMAKE_SOURCE_DIR}/src/libtomahawk/thirdparty/quazip )
@@ -116,6 +116,7 @@ IF( NOT QuaZip_FOUND )
SET( QuaZip_LIBRARY quazip ) SET( QuaZip_LIBRARY quazip )
SET( QuaZip_LIBRARIES ${QuaZip_LIBRARY} ) SET( QuaZip_LIBRARIES ${QuaZip_LIBRARY} )
SET( QuaZip_FOUND true ) SET( QuaZip_FOUND true )
macro_log_feature(QuaZip_FOUND "QuaZip" "Provides support for extracting downloaded resolvers automatically. Building internal copy" "http://quazip.sourceforge.net/" FALSE "" "")
# copy headers to build/quazip so we can use proper includes inside the code # copy headers to build/quazip so we can use proper includes inside the code
FILE( COPY ${CMAKE_SOURCE_DIR}/src/libtomahawk/thirdparty/quazip/quazip/ DESTINATION ${CMAKE_BINARY_DIR}/libtomahawk/thirdparty/quazip ) FILE( COPY ${CMAKE_SOURCE_DIR}/src/libtomahawk/thirdparty/quazip/quazip/ DESTINATION ${CMAKE_BINARY_DIR}/libtomahawk/thirdparty/quazip )
@@ -211,4 +212,7 @@ ADD_SUBDIRECTORY( src/libtomahawk )
SET( TOMAHAWK_LIBRARIES tomahawklib ) SET( TOMAHAWK_LIBRARIES tomahawklib )
ADD_SUBDIRECTORY( src ) ADD_SUBDIRECTORY( src )
ADD_SUBDIRECTORY( admin ) ADD_SUBDIRECTORY( admin )
ADD_SUBDIRECTORY( src/breakpad/CrashReporter )
IF( NOT DISABLE_CRASHREPORTER )
ADD_SUBDIRECTORY( src/breakpad/CrashReporter )
ENDIF()

View File

@@ -2,6 +2,7 @@
# This module looks for clucene (http://clucene.sf.net) support # This module looks for clucene (http://clucene.sf.net) support
# It will define the following values # It will define the following values
# #
# CLUCENE_INCLUDE_DIRS = CLUCENE_INCLUDE_DIR + CLUCENE_LIBRARY_DIR
# CLUCENE_INCLUDE_DIR = where CLucene/StdHeader.h can be found # CLUCENE_INCLUDE_DIR = where CLucene/StdHeader.h can be found
# CLUCENE_LIBRARY_DIR = where CLucene/clucene-config.h can be found # CLUCENE_LIBRARY_DIR = where CLucene/clucene-config.h can be found
# CLUCENE_LIBRARIES = the libraries to link against CLucene # CLUCENE_LIBRARIES = the libraries to link against CLucene
@@ -17,6 +18,7 @@ FIND_PACKAGE(CLuceneUnstable)
IF(CLUCENEUNSTABLE_FOUND) IF(CLUCENEUNSTABLE_FOUND)
SET(CLucene_FOUND TRUE) SET(CLucene_FOUND TRUE)
SET(CLUCENE_INCLUDE_DIR ${CLUCENE_UNSTABLE_INCLUDE_DIRS}) SET(CLUCENE_INCLUDE_DIR ${CLUCENE_UNSTABLE_INCLUDE_DIRS})
SET(CLUCENE_INCLUDE_DIRS ${CLUCENE_INCLUDE_DIR})
SET(CLUCENE_LIBRARIES ${CLUCENE_UNSTABLE_LIBS}) SET(CLUCENE_LIBRARIES ${CLUCENE_UNSTABLE_LIBS})
#MESSAGE(FATAL_ERROR NARF) #MESSAGE(FATAL_ERROR NARF)
@@ -106,7 +108,9 @@ ENDIF (CLUCENE_LIBRARY_DIR)
IF(CLUCENE_INCLUDE_DIR AND CLUCENE_LIBRARIES AND CLUCENE_LIBRARY_DIR AND CLUCENE_GOOD_VERSION) IF(CLUCENE_INCLUDE_DIR AND CLUCENE_LIBRARIES AND CLUCENE_LIBRARY_DIR AND CLUCENE_GOOD_VERSION)
SET(CLucene_FOUND TRUE) SET(CLucene_FOUND TRUE)
SET(CLUCENE_INCLUDE_DIRS ${CLUCENE_LIBRARY_DIR} ${CLUCENE_INCLUDE_DIR})
ENDIF(CLUCENE_INCLUDE_DIR AND CLUCENE_LIBRARIES AND CLUCENE_LIBRARY_DIR AND CLUCENE_GOOD_VERSION) ENDIF(CLUCENE_INCLUDE_DIR AND CLUCENE_LIBRARIES AND CLUCENE_LIBRARY_DIR AND CLUCENE_GOOD_VERSION)
ENDIF(CLUCENEUNSTABLE_FOUND) ENDIF(CLUCENEUNSTABLE_FOUND)
IF(CLucene_FOUND) IF(CLucene_FOUND)
@@ -120,7 +124,8 @@ ELSE(CLucene_FOUND)
ENDIF(CLucene_FOUND) ENDIF(CLucene_FOUND)
MARK_AS_ADVANCED( MARK_AS_ADVANCED(
CLUCENE_INCLUDE_DIR CLUCENE_INCLUDE_DIRS
CLUCENE_LIBRARY_DIR CLUCENE_INCLUDE_DIR
CLUCENE_LIBRARY_DIR
CLUCENE_LIBRARIES CLUCENE_LIBRARIES
) )

View File

@@ -0,0 +1,182 @@
# - Define GNU standard installation directories
# Provides install directory variables as defined for GNU software:
# http://www.gnu.org/prep/standards/html_node/Directory-Variables.html
# Inclusion of this module defines the following variables:
# CMAKE_INSTALL_<dir> - destination for files of a given type
# CMAKE_INSTALL_FULL_<dir> - corresponding absolute path
# where <dir> is one of:
# BINDIR - user executables (bin)
# SBINDIR - system admin executables (sbin)
# LIBEXECDIR - program executables (libexec)
# SYSCONFDIR - read-only single-machine data (etc)
# SHAREDSTATEDIR - modifiable architecture-independent data (com)
# LOCALSTATEDIR - modifiable single-machine data (var)
# LIBDIR - object code libraries (lib or lib64)
# INCLUDEDIR - C header files (include)
# OLDINCLUDEDIR - C header files for non-gcc (/usr/include)
# DATAROOTDIR - read-only architecture-independent data root (share)
# DATADIR - read-only architecture-independent data (DATAROOTDIR)
# INFODIR - info documentation (DATAROOTDIR/info)
# LOCALEDIR - locale-dependent data (DATAROOTDIR/locale)
# MANDIR - man documentation (DATAROOTDIR/man)
# DOCDIR - documentation root (DATAROOTDIR/doc/PROJECT_NAME)
# Each CMAKE_INSTALL_<dir> value may be passed to the DESTINATION options of
# install() commands for the corresponding file type. If the includer does
# not define a value the above-shown default will be used and the value will
# appear in the cache for editing by the user.
# Each CMAKE_INSTALL_FULL_<dir> value contains an absolute path constructed
# from the corresponding destination by prepending (if necessary) the value
# of CMAKE_INSTALL_PREFIX.
#=============================================================================
# Copyright 2011 Nikita Krupen'ko <krnekit@gmail.com>
# Copyright 2011 Kitware, Inc.
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
# Installation directories
#
if(NOT DEFINED CMAKE_INSTALL_BINDIR)
set(CMAKE_INSTALL_BINDIR "bin" CACHE PATH "user executables (bin)")
endif()
if(NOT DEFINED CMAKE_INSTALL_SBINDIR)
set(CMAKE_INSTALL_SBINDIR "sbin" CACHE PATH "system admin executables (sbin)")
endif()
if(NOT DEFINED CMAKE_INSTALL_LIBEXECDIR)
set(CMAKE_INSTALL_LIBEXECDIR "libexec" CACHE PATH "program executables (libexec)")
endif()
if(NOT DEFINED CMAKE_INSTALL_SYSCONFDIR)
set(CMAKE_INSTALL_SYSCONFDIR "etc" CACHE PATH "read-only single-machine data (etc)")
endif()
if(NOT DEFINED CMAKE_INSTALL_SHAREDSTATEDIR)
set(CMAKE_INSTALL_SHAREDSTATEDIR "com" CACHE PATH "modifiable architecture-independent data (com)")
endif()
if(NOT DEFINED CMAKE_INSTALL_LOCALSTATEDIR)
set(CMAKE_INSTALL_LOCALSTATEDIR "var" CACHE PATH "modifiable single-machine data (var)")
endif()
if(NOT DEFINED CMAKE_INSTALL_LIBDIR)
set(_LIBDIR_DEFAULT "lib")
# Override this default 'lib' with 'lib64' iff:
# - we are on Linux system but NOT cross-compiling
# - we are NOT on debian
# - we are on a 64 bits system
# reason is: amd64 ABI: http://www.x86-64.org/documentation/abi.pdf
# Note that the future of multi-arch handling may be even
# more complicated than that: http://wiki.debian.org/Multiarch
if(CMAKE_SYSTEM_NAME MATCHES "Linux"
AND NOT CMAKE_CROSSCOMPILING
AND NOT EXISTS "/etc/debian_version")
if(NOT DEFINED CMAKE_SIZEOF_VOID_P)
message(AUTHOR_WARNING
"Unable to determine default CMAKE_INSTALL_LIBDIR directory because no target architecture is known. "
"Please enable at least one language before including GNUInstallDirs.")
else()
if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
set(_LIBDIR_DEFAULT "lib64")
endif()
endif()
endif()
set(CMAKE_INSTALL_LIBDIR "${_LIBDIR_DEFAULT}" CACHE PATH "object code libraries (${_LIBDIR_DEFAULT})")
endif()
if(NOT DEFINED CMAKE_INSTALL_INCLUDEDIR)
set(CMAKE_INSTALL_INCLUDEDIR "include" CACHE PATH "C header files (include)")
endif()
if(NOT DEFINED CMAKE_INSTALL_OLDINCLUDEDIR)
set(CMAKE_INSTALL_OLDINCLUDEDIR "/usr/include" CACHE PATH "C header files for non-gcc (/usr/include)")
endif()
if(NOT DEFINED CMAKE_INSTALL_DATAROOTDIR)
set(CMAKE_INSTALL_DATAROOTDIR "share" CACHE PATH "read-only architecture-independent data root (share)")
endif()
#-----------------------------------------------------------------------------
# Values whose defaults are relative to DATAROOTDIR. Store empty values in
# the cache and store the defaults in local variables if the cache values are
# not set explicitly. This auto-updates the defaults as DATAROOTDIR changes.
if(NOT CMAKE_INSTALL_DATADIR)
set(CMAKE_INSTALL_DATADIR "" CACHE PATH "read-only architecture-independent data (DATAROOTDIR)")
set(CMAKE_INSTALL_DATADIR "${CMAKE_INSTALL_DATAROOTDIR}")
endif()
if(NOT CMAKE_INSTALL_INFODIR)
set(CMAKE_INSTALL_INFODIR "" CACHE PATH "info documentation (DATAROOTDIR/info)")
set(CMAKE_INSTALL_INFODIR "${CMAKE_INSTALL_DATAROOTDIR}/info")
endif()
if(NOT CMAKE_INSTALL_LOCALEDIR)
set(CMAKE_INSTALL_LOCALEDIR "" CACHE PATH "locale-dependent data (DATAROOTDIR/locale)")
set(CMAKE_INSTALL_LOCALEDIR "${CMAKE_INSTALL_DATAROOTDIR}/locale")
endif()
if(NOT CMAKE_INSTALL_MANDIR)
set(CMAKE_INSTALL_MANDIR "" CACHE PATH "man documentation (DATAROOTDIR/man)")
set(CMAKE_INSTALL_MANDIR "${CMAKE_INSTALL_DATAROOTDIR}/man")
endif()
if(NOT CMAKE_INSTALL_DOCDIR)
set(CMAKE_INSTALL_DOCDIR "" CACHE PATH "documentation root (DATAROOTDIR/doc/PROJECT_NAME)")
set(CMAKE_INSTALL_DOCDIR "${CMAKE_INSTALL_DATAROOTDIR}/doc/${PROJECT_NAME}")
endif()
#-----------------------------------------------------------------------------
mark_as_advanced(
CMAKE_INSTALL_BINDIR
CMAKE_INSTALL_SBINDIR
CMAKE_INSTALL_LIBEXECDIR
CMAKE_INSTALL_SYSCONFDIR
CMAKE_INSTALL_SHAREDSTATEDIR
CMAKE_INSTALL_LOCALSTATEDIR
CMAKE_INSTALL_LIBDIR
CMAKE_INSTALL_INCLUDEDIR
CMAKE_INSTALL_OLDINCLUDEDIR
CMAKE_INSTALL_DATAROOTDIR
CMAKE_INSTALL_DATADIR
CMAKE_INSTALL_INFODIR
CMAKE_INSTALL_LOCALEDIR
CMAKE_INSTALL_MANDIR
CMAKE_INSTALL_DOCDIR
)
# Result directories
#
foreach(dir
BINDIR
SBINDIR
LIBEXECDIR
SYSCONFDIR
SHAREDSTATEDIR
LOCALSTATEDIR
LIBDIR
INCLUDEDIR
OLDINCLUDEDIR
DATAROOTDIR
DATADIR
INFODIR
LOCALEDIR
MANDIR
DOCDIR
)
if(NOT IS_ABSOLUTE ${CMAKE_INSTALL_${dir}})
set(CMAKE_INSTALL_FULL_${dir} "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_${dir}}")
else()
set(CMAKE_INSTALL_FULL_${dir} "${CMAKE_INSTALL_${dir}}")
endif()
endforeach()

View File

@@ -273,7 +273,7 @@ Section "Tomahawk Player" SEC_TOMAHAWK_PLAYER
;Main executable. ;Main executable.
File "${INSTALL_PATH}\bin\tomahawk.exe" File "${INSTALL_PATH}\bin\tomahawk.exe"
File "${INSTALL_PATH}\bin\CrashReporter.exe" File "${INSTALL_PATH}\bin\tomahawk_crash_reporter.exe"
File "${INSTALL_PATH}\bin\libtomahawk_breakpad.dll" File "${INSTALL_PATH}\bin\libtomahawk_breakpad.dll"
File "${INSTALL_PATH}\bin\libqxtweb-standalone.dll" File "${INSTALL_PATH}\bin\libqxtweb-standalone.dll"
@@ -287,7 +287,7 @@ Section "Tomahawk Player" SEC_TOMAHAWK_PLAYER
;Main executable. ;Main executable.
File "${BUILD_PATH}\tomahawk.exe" File "${BUILD_PATH}\tomahawk.exe"
File "${BUILD_PATH}\CrashReporter.exe" File "${BUILD_PATH}\tomahawk_crash_reporter.exe"
File "${BUILD_PATH}\libtomahawk_breakpad.dll" File "${BUILD_PATH}\libtomahawk_breakpad.dll"
File "${BUILD_PATH}\libtomahawklib.dll" File "${BUILD_PATH}\libtomahawklib.dll"
@@ -329,12 +329,6 @@ Section "Tomahawk Player" SEC_TOMAHAWK_PLAYER
File "${MING_BIN}\libstdc++-6.dll" File "${MING_BIN}\libstdc++-6.dll"
;Phonon stuff ;Phonon stuff
;Fix the phonon build to not use Dbus
File "${QT_DLL_PATH}\QtDbus4.dll"
File "${MING_BIN}\libdbus-1-3.dll"
File "${MING_BIN}\dbus-daemon.exe"
File "${VLC_BIN}\libphonon.dll" File "${VLC_BIN}\libphonon.dll"
SetOutPath "$INSTDIR\phonon_backend" SetOutPath "$INSTDIR\phonon_backend"
File "${VLC_BIN}\phonon_backend\phonon_vlc.dll" File "${VLC_BIN}\phonon_backend\phonon_vlc.dll"
@@ -347,12 +341,6 @@ Section "Tomahawk Player" SEC_TOMAHAWK_PLAYER
SetOutPath "$INSTDIR\plugins" SetOutPath "$INSTDIR\plugins"
File /r "${VLC_PLUGIN_PATH}\*.dll" File /r "${VLC_PLUGIN_PATH}\*.dll"
SetOutPath "$INSTDIR" SetOutPath "$INSTDIR"
File "${MING_BIN}\libmad-0.dll" ; MP3
File "${MING_BIN}\libFLAC-8.dll" ; FLAC
File "${MING_BIN}\libogg-0.dll" ; OGG, FLAC
File "${MING_BIN}\libvorbis-0.dll" ; OGG
File "${MING_BIN}\libvorbisenc-2.dll" ; OGG
; Other ; Other
File "${MING_BIN}\libqjson.dll" File "${MING_BIN}\libqjson.dll"
@@ -467,7 +455,8 @@ Section -post
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Tomahawk" "NoRepair" "1" WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Tomahawk" "NoRepair" "1"
; Register tomahawk:// protocol handler ; Register tomahawk:// protocol handler
WriteRegStr HKCR "tomahawk" "" "URL: Tomahawk Protocol" WriteRegStr HKCR "tomahawk" "" "URL:Tomahawk Protocol"
WriteRegStr HKCR "tomahawk" "URL Protocol" ""
WriteRegStr HKCR "tomahawk\DefaultIcon" "" $INSTDIR\tomahawk.exe,1 WriteRegStr HKCR "tomahawk\DefaultIcon" "" $INSTDIR\tomahawk.exe,1
WriteRegStr HKCR "tomahawk\shell" "" "open" WriteRegStr HKCR "tomahawk\shell" "" "open"
WriteRegStr HKCR "tomahawk\shell\open\command" "" '"$INSTDIR\tomahawk.exe" "%1"' WriteRegStr HKCR "tomahawk\shell\open\command" "" '"$INSTDIR\tomahawk.exe" "%1"'

View File

@@ -1,3 +1,54 @@
Version 0.3.3:
* Automatically load Super Collection tracks when no official release
information is available.
* Fixed stations not fetching new tracks under certain circumstances.
* Fixed Footnotes not always updating when selecting a new track.
* Added support for ow.ly, fb.me, itun.es and tinyurl.com URL shorteners.
* Fixed playback issues with non-latin filenames on Windows.
* Fixed tomahawk:// protocol not working properly on Windows.
* Fixed dupe menu entry appearing on OS X.
* Fixed invisible sidebar items on Linux.
Version 0.3.2:
* Improved syncing process, it's faster and more reliable now.
* Fixed UPnP issues.
* Fixed not updating collections and views after a collection changes.
* Fixed not showing a source's proper name at all times.
* Improved music scanner reliability.
* Fixed various labels not being painted in the right color when selected.
* Support .oga (ogg mimetype) files.
* Fixed stuck Now Playing indicator icon.
* Fixed sidebar width of settings dialog on Windows.
* Fixed not always showing delete icon on hovered temporary pages.
* Fixed inability to select externally mounted drives.
* Fixed bug where speaker would be stuck next to a playlist.
* Fixed bug where first startup would show a loading spinner in the
Dashboard's "Recent Additions" forever.
* Automatically upgrade resolvers when an update is found.
* Fixed last played track of a friend never expiring.
* Fixed parsing of rdio tracks.
* Changed steering mechanism in stations to be user-friendlier.
* Fixed loading biographies of artist names with special characters.
* Fixed behaviour of dropping Spotify playlists on the sidebar.
* Fixed hard to read source-name in the audio control area on OS X.
* Fixed crashes when playing Grooveshark tracks.
* Fixed bug where clicking the latch button would flicker and unlatch.
* Fixed Jabber accounts not connecting properly when proxy is in use.
Version 0.3.1:
* Fixed not resolving to local files.
* Fixed shutdown crash on Windows.
* Support more widget types in Javascript resolver configs.
* Fixed bug where red headphone would be visible on My Collection
when listened along to source went offline.
* Draw author name as well as avatar in recently played playlists.
* Fixed Tomahawk integration in Unity.
* Fixed incorrect item selected in source tree when deleting temporary
pages.
* Fixed currently played label disappearing after 10 minutes regardless
of length of track.
* Fixed crash on Sparkle upgrade on OS X.
Version 0.3.0: Version 0.3.0:
* Make artist names in the album view clickable. * Make artist names in the album view clickable.
* Don't start playing if a tomahawk:// link was clicked while Tomahawk * Don't start playing if a tomahawk:// link was clicked while Tomahawk
@@ -12,7 +63,7 @@ Version 0.3.0:
* Added YouTube resolver. * Added YouTube resolver.
* Fixed bug where going offline then online would not re-connect to many * Fixed bug where going offline then online would not re-connect to many
peers. peers.
* Added support for auto-updating live XSPF playlists. * Added support for auto-updating live XSPF playlists.
* Don't show an age of 41 years for tracks that have no age information. * Don't show an age of 41 years for tracks that have no age information.
* Show config UI for resolvers that have them as soon as you add them. * Show config UI for resolvers that have them as soon as you add them.
* Add support for Echo Nest Personal Catalogs and User Radio. Synchronize * Add support for Echo Nest Personal Catalogs and User Radio. Synchronize
@@ -28,7 +79,7 @@ Version 0.3.0:
* Added new job status view in the bottom of the source list that displays * Added new job status view in the bottom of the source list that displays
current jobs such as resolving, parsing playlists, and loading from current jobs such as resolving, parsing playlists, and loading from
database. database.
* Parse and convert a Spotify playlist url when dropped anywhere on the * Parse and convert a Spotify playlist URL when dropped anywhere on the
sidebar. sidebar.
* Convert resolvers to use asynchronous calls to avoid blocking Tomahawk's * Convert resolvers to use asynchronous calls to avoid blocking Tomahawk's
UI, greatly increasing responsiveness of Tomahawk while resolving. UI, greatly increasing responsiveness of Tomahawk while resolving.

View File

@@ -250,7 +250,7 @@ frameworks_dir = os.path.join(bundle_dir, 'Contents', 'Frameworks')
commands.append(['mkdir', '-p', frameworks_dir]) commands.append(['mkdir', '-p', frameworks_dir])
resources_dir = os.path.join(bundle_dir, 'Contents', 'Resources') resources_dir = os.path.join(bundle_dir, 'Contents', 'Resources')
commands.append(['mkdir', '-p', resources_dir]) commands.append(['mkdir', '-p', resources_dir])
plugins_dir = os.path.join(bundle_dir, 'Contents', 'PlugIns') plugins_dir = os.path.join(bundle_dir, 'Contents', 'plugins')
binary = os.path.join(bundle_dir, 'Contents', 'MacOS', bundle_name) binary = os.path.join(bundle_dir, 'Contents', 'MacOS', bundle_name)
fixed_libraries = [] fixed_libraries = []
@@ -502,9 +502,9 @@ except:
print 'Failed to find spotify resolver' print 'Failed to find spotify resolver'
try: try:
FixPlugin('CrashReporter', '../MacOS') FixPlugin('tomahawk_crash_reporter', '../MacOS')
except: except:
print 'Failed to find CrashReporter' print 'Failed to find tomahawk_crash_reporter'
for plugin in QT_PLUGINS: for plugin in QT_PLUGINS:
FixPlugin(FindQtPlugin(plugin), os.path.dirname(plugin)) FixPlugin(FindQtPlugin(plugin), os.path.dirname(plugin))

View File

@@ -4,8 +4,9 @@ Version=1.0
Name=Tomahawk Name=Tomahawk
GenericName=Music Player GenericName=Music Player
TryExec=tomahawk TryExec=tomahawk
Exec=tomahawk Exec=tomahawk %u
Comment=Tomahawk - Social Music Player Comment=Tomahawk - Social Music Player
Icon=tomahawk Icon=tomahawk
Terminal=false Terminal=false
Categories=Qt;AudioVideo;Audio;Player; Categories=Qt;AudioVideo;Audio;Player;
MimeType=x-scheme-handler/tomahawk;

View File

@@ -1,22 +1,31 @@
#!/bin/bash #!/bin/bash
echo "Remove old vlc dir..."
mkdir -p vlc/ mkdir -p vlc/
if [ "$1" = "-c" ] ; then
echo "Continuing last download.."
rm -rvf vlc/prefix/
else
echo "Remove old vlc dir..."
rm -rvf vlc/*
fi
cd vlc/ cd vlc/
#rm -vf vlc-*.7z echo "Download phonon archive..."
#rm -rf vlc/
echo "Download specified binary..."
#wget -c "http://downloads.sourceforge.net/project/vlc/1.1.9/win32/vlc-1.1.9-win32.7z?r=http%3A%2F%2Fwww.videolan.org%2Fvlc%2Fdownload-windows.html&ts=1306272584&use_mirror=leaseweb" #wget -c "http://downloads.sourceforge.net/project/vlc/1.1.9/win32/vlc-1.1.9-win32.7z?r=http%3A%2F%2Fwww.videolan.org%2Fvlc%2Fdownload-windows.html&ts=1306272584&use_mirror=leaseweb"
#wget -c "http://download.tomahawk-player.org/tomahawk-vlc-0.1.zip" #wget -c "http://download.tomahawk-player.org/tomahawk-vlc-0.1.zip"
wget -c http://people.videolan.org/~jb/phonon/phonon-vlc-last.7z #wget -c http://people.videolan.org/~jb/phonon/phonon-vlc-last.7z
wget -c http://people.videolan.org/~jb/phonon/phonon_phonon-vlc_20111128.7z
echo "Extract binary..." echo "Extract binary..."
7z x phonon-vlc-last.7z 7z x phonon*.7z
#mv -v vlc-*/ vlc/ #mv -v vlc-*/ vlc/
#unzip tomahawk-vlc-0.1.zip #unzip tomahawk-vlc-0.1.zip
echo "Download phonon_vlc_no_video.dll..."
wget -c http://people.videolan.org/~jb/phonon/phonon_vlc_no_video.dll
cp -v phonon_vlc_no_video.dll prefix/bin/phonon_backend/phonon_vlc.dll
echo "Strip unneeded plugins from vlc/plugins..." echo "Strip unneeded plugins from vlc/plugins..."
cd prefix/bin/plugins cd prefix/bin/plugins
rm -rvf libold* libvcd* libdvd* liblibass* libx264* libschroe* liblibmpeg2* \ rm -rvf libold* libvcd* libdvd* liblibass* libx264* libschroe* liblibmpeg2* \

BIN
data/images/apply-check.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

File diff suppressed because it is too large Load Diff

3180
lang/tomahawk_en.ts Normal file

File diff suppressed because it is too large Load Diff

3017
lang/tomahawk_es.ts Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,8 @@
<!DOCTYPE RCC><RCC version="1.0"> <!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/lang"> <qresource prefix="/lang">
<file>tomahawk_en.qm</file>
<file>tomahawk_es.qm</file>
<file>tomahawk_de.qm</file> <file>tomahawk_de.qm</file>
<file>tomahawk_pl.qm</file>
</qresource> </qresource>
</RCC> </RCC>

3218
lang/tomahawk_pl.ts Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -98,6 +98,7 @@
<file>data/images/track-icon-22x22.png</file> <file>data/images/track-icon-22x22.png</file>
<file>data/images/track-icon-32x32.png</file> <file>data/images/track-icon-32x32.png</file>
<file>data/images/track-icon-16x16.png</file> <file>data/images/track-icon-16x16.png</file>
<file>data/images/apply-check.png</file>
<file>data/stylesheets/topbar-radiobuttons.css</file> <file>data/stylesheets/topbar-radiobuttons.css</file>
<file>data/icons/tomahawk-icon-16x16.png</file> <file>data/icons/tomahawk-icon-16x16.png</file>
<file>data/icons/tomahawk-icon-32x32.png</file> <file>data/icons/tomahawk-icon-32x32.png</file>

View File

@@ -40,6 +40,7 @@ SET( tomahawkSources ${tomahawkSources}
musicscanner.cpp musicscanner.cpp
shortcuthandler.cpp shortcuthandler.cpp
scanmanager.cpp scanmanager.cpp
ubuntuunityhack.cpp
tomahawkapp.cpp tomahawkapp.cpp
main.cpp main.cpp
) )
@@ -85,6 +86,7 @@ SET( tomahawkHeaders ${tomahawkHeaders}
musicscanner.h musicscanner.h
scanmanager.h scanmanager.h
ubuntuunityhack.h
shortcuthandler.h shortcuthandler.h
) )

View File

@@ -22,7 +22,7 @@
#include "GetNewStuffDelegate.h" #include "GetNewStuffDelegate.h"
#include "GetNewStuffModel.h" #include "GetNewStuffModel.h"
GetNewStuffDialog::GetNewStuffDialog( QWidget *parent, Qt::WindowFlags f ) GetNewStuffDialog::GetNewStuffDialog( QWidget* parent, Qt::WindowFlags f )
: QDialog( parent, f ) : QDialog( parent, f )
, ui( new Ui::GetNewStuffDialog ) , ui( new Ui::GetNewStuffDialog )
, m_model( new GetNewStuffModel( this ) ) , m_model( new GetNewStuffModel( this ) )
@@ -37,16 +37,17 @@ GetNewStuffDialog::GetNewStuffDialog( QWidget *parent, Qt::WindowFlags f )
ui->listView->setMouseTracking( true ); ui->listView->setMouseTracking( true );
setMinimumSize( 560, 350 );
#ifdef Q_WS_MAC #ifdef Q_WS_MAC
setMinimumSize( 510, 350 ); setMaximumSize( 560, 350 );
setMaximumSize( 510, 350 );
setSizeGripEnabled( false ); setSizeGripEnabled( false );
ui->listView->setAttribute( Qt::WA_MacShowFocusRect, false ); ui->listView->setAttribute( Qt::WA_MacShowFocusRect, false );
#endif #endif
} }
GetNewStuffDialog::~GetNewStuffDialog() GetNewStuffDialog::~GetNewStuffDialog()
{ {
delete ui; delete ui;

View File

@@ -34,9 +34,6 @@ LoadXSPFDialog::LoadXSPFDialog( QWidget* parent, Qt::WindowFlags f )
m_ui->verticalLayout->setSpacing( 0 ); m_ui->verticalLayout->setSpacing( 0 );
#endif #endif
connect( m_ui->buttonBox, SIGNAL( accepted() ), SLOT( accept() ) );
connect( m_ui->buttonBox, SIGNAL( rejected() ), SLOT( reject() ) );
connect( m_ui->navigateButton, SIGNAL( clicked( bool ) ), this, SLOT( getLocalFile() ) ); connect( m_ui->navigateButton, SIGNAL( clicked( bool ) ), this, SLOT( getLocalFile() ) );
} }
@@ -47,7 +44,7 @@ LoadXSPFDialog::~LoadXSPFDialog()
void void
LoadXSPFDialog::getLocalFile() LoadXSPFDialog::getLocalFile()
{ {
QString url = QFileDialog::getOpenFileName( this, tr( "Load XSPF File" ), QDir::homePath(), ".xspf" ); QString url = QFileDialog::getOpenFileName( this, tr( "Load XSPF File" ), QDir::homePath(), tr( "XSPF Files (*.xspf)" ) );
m_ui->lineEdit->setText( url ); m_ui->lineEdit->setText( url );
} }

View File

@@ -19,9 +19,9 @@
#include "audiocontrols.h" #include "audiocontrols.h"
#include "ui_audiocontrols.h" #include "ui_audiocontrols.h"
#include <QNetworkReply> #include <QtNetwork/QNetworkReply>
#include <QDropEvent> #include <QtGui/QDropEvent>
#include <QMouseEvent> #include <QtGui/QMouseEvent>
#include "audio/audioengine.h" #include "audio/audioengine.h"
#include "playlist/playlistview.h" #include "playlist/playlistview.h"
@@ -45,6 +45,7 @@ AudioControls::AudioControls( QWidget* parent )
, ui( new Ui::AudioControls ) , ui( new Ui::AudioControls )
, m_repeatMode( PlaylistInterface::NoRepeat ) , m_repeatMode( PlaylistInterface::NoRepeat )
, m_shuffled( false ) , m_shuffled( false )
, m_lastSliderCheck( 0 )
{ {
ui->setupUi( this ); ui->setupUi( this );
setAcceptDrops( true ); setAcceptDrops( true );
@@ -86,7 +87,11 @@ AudioControls::AudioControls( QWidget* parent )
ui->loveButton->setPixmap( RESPATH "images/not-loved.png" ); ui->loveButton->setPixmap( RESPATH "images/not-loved.png" );
ui->loveButton->setCheckable( true ); ui->loveButton->setCheckable( true );
#ifdef Q_WS_MAC
ui->ownerLabel->setForegroundRole( QPalette::Text );
#else
ui->ownerLabel->setForegroundRole( QPalette::Dark ); ui->ownerLabel->setForegroundRole( QPalette::Dark );
#endif
ui->metaDataArea->setStyleSheet( "QWidget#metaDataArea {\nborder-width: 4px;\nborder-image: url(" RESPATH "images/now-playing-panel.png) 4 4 4 4 stretch stretch; }" ); ui->metaDataArea->setStyleSheet( "QWidget#metaDataArea {\nborder-width: 4px;\nborder-image: url(" RESPATH "images/now-playing-panel.png) 4 4 4 4 stretch stretch; }" );
ui->seekSlider->setEnabled( true ); ui->seekSlider->setEnabled( true );
@@ -107,8 +112,8 @@ AudioControls::AudioControls( QWidget* parent )
connect( ui->volumeLowButton, SIGNAL( clicked() ), AudioEngine::instance(), SLOT( lowerVolume() ) ); connect( ui->volumeLowButton, SIGNAL( clicked() ), AudioEngine::instance(), SLOT( lowerVolume() ) );
connect( ui->volumeHighButton, SIGNAL( clicked() ), AudioEngine::instance(), SLOT( raiseVolume() ) ); connect( ui->volumeHighButton, SIGNAL( clicked() ), AudioEngine::instance(), SLOT( raiseVolume() ) );
connect( ui->playPauseButton, SIGNAL( clicked() ), this, SIGNAL( playPressed() ) ); connect( ui->playPauseButton, SIGNAL( clicked() ), SIGNAL( playPressed() ) );
connect( ui->pauseButton, SIGNAL( clicked() ), this, SIGNAL( pausePressed() ) ); connect( ui->pauseButton, SIGNAL( clicked() ), SIGNAL( pausePressed() ) );
connect( ui->repeatButton, SIGNAL( clicked() ), SLOT( onRepeatClicked() ) ); connect( ui->repeatButton, SIGNAL( clicked() ), SLOT( onRepeatClicked() ) );
connect( ui->shuffleButton, SIGNAL( clicked() ), SLOT( onShuffleClicked() ) ); connect( ui->shuffleButton, SIGNAL( clicked() ), SLOT( onShuffleClicked() ) );
@@ -207,6 +212,9 @@ AudioControls::onPlaybackStarted( const Tomahawk::result_ptr& result )
ui->seekSlider->setVisible( true ); ui->seekSlider->setVisible( true );
m_noTimeChange = false;
m_lastSliderCheck = 0;
Tomahawk::InfoSystem::InfoStringHash trackInfo; Tomahawk::InfoSystem::InfoStringHash trackInfo;
trackInfo["artist"] = result->artist()->name(); trackInfo["artist"] = result->artist()->name();
trackInfo["album"] = result->album()->name(); trackInfo["album"] = result->album()->name();
@@ -285,9 +293,10 @@ AudioControls::onPlaybackLoading( const Tomahawk::result_ptr& result )
result->loadSocialActions(); result->loadSocialActions();
connect( result.data(), SIGNAL( socialActionsLoaded() ), this, SLOT( socialActionsLoaded() ) ); connect( result.data(), SIGNAL( socialActionsLoaded() ), SLOT( socialActionsLoaded() ) );
} }
void void
AudioControls::socialActionsLoaded() AudioControls::socialActionsLoaded()
{ {
@@ -318,6 +327,7 @@ AudioControls::onPlaybackPaused()
m_sliderTimeLine.setPaused( true ); m_sliderTimeLine.setPaused( true );
} }
void void
AudioControls::onPlaybackResumed() AudioControls::onPlaybackResumed()
{ {
@@ -363,7 +373,11 @@ AudioControls::onPlaybackStopped()
void void
AudioControls::onPlaybackTimer( qint64 msElapsed ) AudioControls::onPlaybackTimer( qint64 msElapsed )
{ {
//tDebug( LOGEXTRA ) << Q_FUNC_INFO << " msElapsed = " << msElapsed << " and timer current time = " << m_sliderTimeLine.currentTime() << " and m_seekMsecs = " << m_seekMsecs; // tDebug( LOGEXTRA ) << Q_FUNC_INFO << "msElapsed =" << msElapsed << "and timer current time =" << m_sliderTimeLine.currentTime() << "and m_seekMsecs =" << m_seekMsecs;
if ( msElapsed > 0 && msElapsed - 500 < m_lastSliderCheck )
return;
m_lastSliderCheck = msElapsed;
if ( m_currentTrack.isNull() ) if ( m_currentTrack.isNull() )
return; return;
@@ -373,9 +387,22 @@ AudioControls::onPlaybackTimer( qint64 msElapsed )
ui->timeLabel->setText( TomahawkUtils::timeToString( seconds ) ); ui->timeLabel->setText( TomahawkUtils::timeToString( seconds ) );
ui->timeLeftLabel->setText( "-" + TomahawkUtils::timeToString( m_currentTrack->duration() - seconds ) ); ui->timeLeftLabel->setText( "-" + TomahawkUtils::timeToString( m_currentTrack->duration() - seconds ) );
if ( m_sliderTimeLine.currentTime() > msElapsed || m_seekMsecs != -1 ) if ( m_noTimeChange )
{
if ( m_sliderTimeLine.currentTime() != msElapsed )
{
m_noTimeChange = false;
m_sliderTimeLine.resume();
}
}
else if ( m_sliderTimeLine.currentTime() >= msElapsed || m_seekMsecs != -1 )
{ {
m_sliderTimeLine.setPaused( true ); m_sliderTimeLine.setPaused( true );
m_noTimeChange = false;
if ( m_sliderTimeLine.currentTime() == msElapsed )
m_noTimeChange = true;
m_sliderTimeLine.setCurrentTime( msElapsed ); m_sliderTimeLine.setCurrentTime( msElapsed );
m_seekMsecs = -1; m_seekMsecs = -1;
if ( AudioEngine::instance()->state() != AudioEngine::Paused ) if ( AudioEngine::instance()->state() != AudioEngine::Paused )
@@ -384,7 +411,7 @@ AudioControls::onPlaybackTimer( qint64 msElapsed )
else if ( m_sliderTimeLine.duration() > msElapsed && m_sliderTimeLine.state() == QTimeLine::NotRunning ) else if ( m_sliderTimeLine.duration() > msElapsed && m_sliderTimeLine.state() == QTimeLine::NotRunning )
{ {
ui->seekSlider->setEnabled( AudioEngine::instance()->canSeek() ); ui->seekSlider->setEnabled( AudioEngine::instance()->canSeek() );
m_sliderTimeLine.resume(); m_sliderTimeLine.start();
} }
else if ( m_sliderTimeLine.state() == QTimeLine::Paused && AudioEngine::instance()->state() != AudioEngine::Paused ) else if ( m_sliderTimeLine.state() == QTimeLine::Paused && AudioEngine::instance()->state() != AudioEngine::Paused )
{ {

View File

@@ -19,8 +19,8 @@
#ifndef AUDIOCONTROLS_H #ifndef AUDIOCONTROLS_H
#define AUDIOCONTROLS_H #define AUDIOCONTROLS_H
#include <QWidget> #include <QtGui/QWidget>
#include <QTimeLine> #include <QtCore/QTimeLine>
#include "result.h" #include "result.h"
#include "playlistinterface.h" #include "playlistinterface.h"
@@ -95,6 +95,8 @@ private:
QTimeLine m_sliderTimeLine; QTimeLine m_sliderTimeLine;
qint64 m_seekMsecs; qint64 m_seekMsecs;
qint64 m_lastSliderCheck;
bool m_noTimeChange;
}; };
#endif // AUDIOCONTROLS_H #endif // AUDIOCONTROLS_H

View File

@@ -28,9 +28,6 @@
<height>80</height> <height>80</height>
</size> </size>
</property> </property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4"> <layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="topMargin"> <property name="topMargin">
<number>0</number> <number>0</number>
@@ -164,9 +161,6 @@
<height>58</height> <height>58</height>
</size> </size>
</property> </property>
<property name="text">
<string>TextLabel</string>
</property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignCenter</set> <set>Qt::AlignCenter</set>
</property> </property>

View File

@@ -18,11 +18,17 @@
#include "BreakPad.h" #include "BreakPad.h"
#include "config.h"
#include "utils/logger.h"
#include <QCoreApplication> #include <QCoreApplication>
#include <QString> #include <QString>
#include <QFileInfo>
#include <string.h> #include <string.h>
#define CRASH_REPORTER_BINARY "CrashReporter" #define CRASH_REPORTER_BINARY "tomahawk_crash_reporter"
bool s_active = true;
#ifndef WIN32 #ifndef WIN32
#include <unistd.h> #include <unistd.h>
@@ -38,8 +44,10 @@ LaunchUploader( const char* dump_dir, const char* minidump_id, void* that, bool
return false; return false;
const char* crashReporter = static_cast<BreakPad*>(that)->crashReporter(); const char* crashReporter = static_cast<BreakPad*>(that)->crashReporter();
pid_t pid = fork(); if ( !s_active || strlen( crashReporter ) == 0 )
return false;
pid_t pid = fork();
if ( pid == -1 ) // fork failed if ( pid == -1 ) // fork failed
return false; return false;
if ( pid == 0 ) if ( pid == 0 )
@@ -63,14 +71,25 @@ LaunchUploader( const char* dump_dir, const char* minidump_id, void* that, bool
} }
BreakPad::BreakPad( const QString& path ) BreakPad::BreakPad( const QString& path, bool active )
#ifdef Q_OS_LINUX #ifdef Q_OS_LINUX
: google_breakpad::ExceptionHandler( path.toStdString(), 0, LaunchUploader, this, true ) : google_breakpad::ExceptionHandler( path.toStdString(), 0, LaunchUploader, this, true )
#else #else
: google_breakpad::ExceptionHandler( path.toStdString(), 0, LaunchUploader, this, true, 0 ) : google_breakpad::ExceptionHandler( path.toStdString(), 0, LaunchUploader, this, true, 0 )
#endif #endif
{ {
QString reporter = QString( "%1/%2" ).arg( qApp->applicationDirPath() ).arg( CRASH_REPORTER_BINARY ); s_active = active;
QString reporter;
QString localReporter = QString( "%1/%2" ).arg( qApp->applicationDirPath() ).arg( CRASH_REPORTER_BINARY );
QString globalReporter = QString( "%1/%2" ).arg( CMAKE_INSTALL_PREFIX "/" CMAKE_INSTALL_LIBEXECDIR ).arg( CRASH_REPORTER_BINARY );
if ( QFileInfo( localReporter ).exists() )
reporter = localReporter;
else if ( QFileInfo( globalReporter ).exists() )
reporter = globalReporter;
else
tLog() << "Could not find \"" CRASH_REPORTER_BINARY "\" in \"" CMAKE_INSTALL_PREFIX "/" CMAKE_INSTALL_LIBEXECDIR "\" or application path";
char* creporter; char* creporter;
std::string sreporter = reporter.toStdString(); std::string sreporter = reporter.toStdString();
@@ -126,7 +145,7 @@ LaunchUploader( const wchar_t* dump_dir, const wchar_t* minidump_id, void* that,
si.wShowWindow = SW_SHOWNORMAL; si.wShowWindow = SW_SHOWNORMAL;
ZeroMemory( &pi, sizeof(pi) ); ZeroMemory( &pi, sizeof(pi) );
if (CreateProcess( NULL, command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) if ( CreateProcess( NULL, command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi ) )
{ {
CloseHandle( pi.hProcess ); CloseHandle( pi.hProcess );
CloseHandle( pi.hThread ); CloseHandle( pi.hThread );
@@ -137,9 +156,24 @@ LaunchUploader( const wchar_t* dump_dir, const wchar_t* minidump_id, void* that,
} }
BreakPad::BreakPad( const QString& path ) BreakPad::BreakPad( const QString& path, bool active )
: google_breakpad::ExceptionHandler( path.toStdWString(), 0, LaunchUploader, this, true ) : google_breakpad::ExceptionHandler( path.toStdWString(), 0, LaunchUploader, this, true )
{ {
s_active = active;
} }
#endif // WIN32 #endif // WIN32
void
BreakPad::setActive( bool enabled )
{
s_active = enabled;
}
bool
BreakPad::isActive()
{
return s_active;
}

View File

@@ -32,11 +32,14 @@ class BreakPad : public google_breakpad::ExceptionHandler
const char* m_crashReporter; // again, const char[] const char* m_crashReporter; // again, const char[]
public: public:
BreakPad( const QString &dump_write_dirpath ); BreakPad( const QString& dump_write_dirpath, bool active );
~BreakPad() ~BreakPad()
{} {}
static void setActive( bool enabled );
static bool isActive();
void setProductName( const char* s ) { m_productName = s; }; void setProductName( const char* s ) { m_productName = s; };
const char* productName() const { return m_productName; } const char* productName() const { return m_productName; }

View File

@@ -1,8 +1,10 @@
PROJECT( CrashReporter ) PROJECT( CrashReporter )
FIND_PACKAGE( Qt4 REQUIRED ) FIND_PACKAGE( Qt4 REQUIRED )
SET( QT_USE_QTNETWORK TRUE ) SET( QT_USE_QTNETWORK TRUE )
SET( crashreporter_SOURCES main.cpp CrashReporter.cpp ) SET( crashreporter_SOURCES main.cpp CrashReporter.cpp )
SET( crashreporter_HEADERS CrashReporter.h ) SET( crashreporter_HEADERS CrashReporter.h )
SET( crashreporter_UI CrashReporter.ui ) SET( crashreporter_UI CrashReporter.ui )
@@ -16,5 +18,8 @@ INCLUDE( ${QT_USE_FILE} )
INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/src ../../libtomahawk ) INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/src ../../libtomahawk )
ADD_DEFINITIONS( ${QT_DEFINITIONS} ) ADD_DEFINITIONS( ${QT_DEFINITIONS} )
ADD_EXECUTABLE( CrashReporter WIN32 ${crashreporter_SOURCES} ${crashreporter_HEADERS_MOC} ${crashreporter_UI_HEADERS} ${crashreporter_RC_RCC} ) ADD_EXECUTABLE( tomahawk_crash_reporter WIN32 ${crashreporter_SOURCES} ${crashreporter_HEADERS_MOC} ${crashreporter_UI_HEADERS} ${crashreporter_RC_RCC} )
TARGET_LINK_LIBRARIES( CrashReporter ${QT_LIBRARIES} tomahawklib ) TARGET_LINK_LIBRARIES( tomahawk_crash_reporter ${QT_LIBRARIES} tomahawklib )
INCLUDE(GNUInstallDirs)
install(TARGETS tomahawk_crash_reporter RUNTIME DESTINATION ${CMAKE_INSTALL_LIBEXECDIR})

View File

@@ -9,6 +9,7 @@
#cmakedefine DEBUG_BUILD #cmakedefine DEBUG_BUILD
#define CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" #define CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}"
#define CMAKE_INSTALL_LIBEXECDIR "${CMAKE_INSTALL_LIBEXECDIR}"
#define CMAKE_SYSTEM "${CMAKE_SYSTEM}" #define CMAKE_SYSTEM "${CMAKE_SYSTEM}"
#cmakedefine LION #cmakedefine LION

View File

@@ -44,7 +44,9 @@ AtticaManager::AtticaManager( QObject* parent )
connect( &m_manager, SIGNAL( providerAdded( Attica::Provider ) ), this, SLOT( providerAdded( Attica::Provider ) ) ); connect( &m_manager, SIGNAL( providerAdded( Attica::Provider ) ), this, SLOT( providerAdded( Attica::Provider ) ) );
// resolvers // resolvers
m_manager.addProviderFile( QUrl( "http://bakery.tomahawk-player.org:10480/resolvers/providers.xml" ) ); m_manager.addProviderFile( QUrl( "http://bakery.tomahawk-player.org/resolvers/providers.xml" ) );
qRegisterMetaType< Attica::Content >( "Attica::Content" );
} }
@@ -149,6 +151,7 @@ AtticaManager::pathFromId( const QString& resolverId ) const
return m_resolverStates.value( resolverId ).scriptPath; return m_resolverStates.value( resolverId ).scriptPath;
} }
void void
AtticaManager::uploadRating( const Content& c ) AtticaManager::uploadRating( const Content& c )
{ {
@@ -175,6 +178,7 @@ AtticaManager::uploadRating( const Content& c )
emit resolverStateChanged( c.id() ); emit resolverStateChanged( c.id() );
} }
bool bool
AtticaManager::userHasRated( const Content& c ) const AtticaManager::userHasRated( const Content& c ) const
{ {
@@ -245,6 +249,7 @@ AtticaManager::resolverIconFetched()
m_resolverStates[ resolverId ].pixmap = icon; m_resolverStates[ resolverId ].pixmap = icon;
} }
void void
AtticaManager::syncServerData() AtticaManager::syncServerData()
{ {
@@ -271,62 +276,16 @@ AtticaManager::syncServerData()
if ( ( r.state == Installed || r.state == NeedsUpgrade ) && if ( ( r.state == Installed || r.state == NeedsUpgrade ) &&
!upstream.version().isEmpty() ) !upstream.version().isEmpty() )
{ {
if ( newerVersion( r.version, upstream.version() ) ) if ( TomahawkUtils::newerVersion( r.version, upstream.version() ) )
{ {
m_resolverStates[ id ].state = NeedsUpgrade; m_resolverStates[ id ].state = NeedsUpgrade;
QMetaObject::invokeMethod( this, "upgradeResolver", Qt::QueuedConnection, Q_ARG( Attica::Content, upstream ) );
} }
} }
} }
} }
} }
bool
AtticaManager::newerVersion( const QString& older, const QString& newer ) const
{
// Dumb version comparison. Expects two strings, X.Y and Z.V. Returns true if Z > v || Z == V && V > Y
// DOES NOT support X.Y.Z version strings
if ( older.isEmpty() || newer.isEmpty() )
return false;
QPair<int, int> oldVer, newVer;
QStringList parts = older.split( "." );
if ( parts.size() == 1 )
{
oldVer.first = parts[ 0 ].toInt();
oldVer.second = 0;
}
else if ( parts.size() == 2 )
{
oldVer.first = parts[ 0 ].toInt();
oldVer.second = parts[ 1 ].toInt();;
}
else
return false;
parts = newer.split( "." );
if ( parts.size() == 1 )
{
newVer.first = parts[ 0 ].toInt();
newVer.second = 0;
}
else if ( parts.size() == 2 )
{
newVer.first = parts[ 0 ].toInt();
newVer.second = parts[ 1 ].toInt();;
}
else
return false;
// Do the comparison
if ( newVer.first > oldVer.first )
return true;
if ( newVer.first == oldVer.first &&
newVer.second > oldVer.second )
return true;
return false;
}
void void
AtticaManager::installResolver( const Content& resolver ) AtticaManager::installResolver( const Content& resolver )
@@ -347,6 +306,7 @@ AtticaManager::installResolver( const Content& resolver )
job->start(); job->start();
} }
void void
AtticaManager::upgradeResolver( const Content& resolver ) AtticaManager::upgradeResolver( const Content& resolver )
{ {

View File

@@ -83,8 +83,6 @@ public:
ResolverState resolverState( const Attica::Content& resolver ) const; ResolverState resolverState( const Attica::Content& resolver ) const;
QPixmap iconForResolver( const Attica::Content& id ); // Looks up in icon cache QPixmap iconForResolver( const Attica::Content& id ); // Looks up in icon cache
void installResolver( const Attica::Content& resolver );
void upgradeResolver( const Attica::Content& resolver );
void uninstallResolver( const Attica::Content& resolver ); void uninstallResolver( const Attica::Content& resolver );
void uninstallResolver( const QString& pathToResolver ); void uninstallResolver( const QString& pathToResolver );
QString pathFromId( const QString& resolverId ) const; QString pathFromId( const QString& resolverId ) const;
@@ -92,6 +90,9 @@ public:
void uploadRating( const Attica::Content& c ); void uploadRating( const Attica::Content& c );
bool userHasRated( const Attica::Content& c ) const; bool userHasRated( const Attica::Content& c ) const;
public slots:
void installResolver( const Attica::Content& resolver );
void upgradeResolver( const Attica::Content& resolver );
signals: signals:
void resolversReloaded( const Attica::Content::List& resolvers ); void resolversReloaded( const Attica::Content::List& resolvers );
@@ -111,7 +112,6 @@ private slots:
void resolverIconFetched(); void resolverIconFetched();
void syncServerData(); void syncServerData();
bool newerVersion( const QString& older, const QString& newer ) const;
private: private:
QString extractPayload( const QString& filename, const QString& resolverId ) const; QString extractPayload( const QString& filename, const QString& resolverId ) const;
@@ -127,4 +127,8 @@ private:
static AtticaManager* s_instance; static AtticaManager* s_instance;
}; };
#ifdef LIBATTICA_FOUND
Q_DECLARE_METATYPE( Attica::Content );
#endif
#endif // ATTICAMANAGER_H #endif // ATTICAMANAGER_H

View File

@@ -440,6 +440,7 @@ set( libHeaders
widgets/playlisttypeselectordlg.h widgets/playlisttypeselectordlg.h
widgets/welcomewidget.h widgets/welcomewidget.h
widgets/whatshotwidget.h widgets/whatshotwidget.h
widgets/whatshotwidget_p.h
widgets/RecentlyPlayedPlaylistsModel.h widgets/RecentlyPlayedPlaylistsModel.h
widgets/RecentPlaylistsModel.h widgets/RecentPlaylistsModel.h
widgets/OverlayButton.h widgets/OverlayButton.h
@@ -501,7 +502,7 @@ include_directories( . ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/.
${QJSON_INCLUDE_DIR} ${QJSON_INCLUDE_DIR}
${LIBECHONEST_INCLUDE_DIR} ${LIBECHONEST_INCLUDE_DIR}
${LIBECHONEST_INCLUDE_DIR}/.. ${LIBECHONEST_INCLUDE_DIR}/..
${CLUCENE_INCLUDE_DIR} ${CLUCENE_INCLUDE_DIRS}
${PHONON_INCLUDES} ${PHONON_INCLUDES}
${CMAKE_BINARY_DIR}/thirdparty/liblastfm2/src ${CMAKE_BINARY_DIR}/thirdparty/liblastfm2/src

View File

@@ -342,7 +342,6 @@ EchonestCatalogSynchronizer::tracksRemoved( const QList< unsigned int >& trackId
foreach ( unsigned int id, trackIds ) foreach ( unsigned int id, trackIds )
{ {
tDebug() << "Deleting item with id:" << id;
Echonest::CatalogUpdateEntry e( Echonest::CatalogTypes::Delete ); Echonest::CatalogUpdateEntry e( Echonest::CatalogTypes::Delete );
e.setItemId( QString::number( id ).toLatin1() ); e.setItemId( QString::number( id ).toLatin1() );
entries.append( e ); entries.append( e );

View File

@@ -42,7 +42,7 @@ ActionCollection::initActions()
m_actionCollection[ "latchOff" ] = new QAction( tr( "&Stop Listening Along" ), this ); m_actionCollection[ "latchOff" ] = new QAction( tr( "&Stop Listening Along" ), this );
bool isPublic = TomahawkSettings::instance()->privateListeningMode() == TomahawkSettings::PublicListening; bool isPublic = TomahawkSettings::instance()->privateListeningMode() == TomahawkSettings::PublicListening;
QAction *privacyToggle = new QAction( tr( QString( isPublic ? "&Listen Privately" : "&Listen Publicly" ).toAscii().constData() ), this ); QAction *privacyToggle = new QAction( ( isPublic ? tr( "&Listen Privately" ) : tr( "&Listen Publicly" ) ), this );
privacyToggle->setIcon( QIcon( RESPATH "images/private-listening.png" ) ); privacyToggle->setIcon( QIcon( RESPATH "images/private-listening.png" ) );
privacyToggle->setIconVisibleInMenu( isPublic ); privacyToggle->setIconVisibleInMenu( isPublic );
m_actionCollection[ "togglePrivacy" ] = privacyToggle; m_actionCollection[ "togglePrivacy" ] = privacyToggle;

View File

@@ -167,6 +167,8 @@ void
AudioEngine::stop() AudioEngine::stop()
{ {
tDebug( LOGEXTRA ) << Q_FUNC_INFO; tDebug( LOGEXTRA ) << Q_FUNC_INFO;
emit stopped();
if ( isStopped() ) if ( isStopped() )
return; return;
@@ -178,7 +180,6 @@ AudioEngine::stop()
if ( !m_currentTrack.isNull() ) if ( !m_currentTrack.isNull() )
emit timerPercentage( ( (double)m_timeElapsed / (double)m_currentTrack->duration() ) * 100.0 ); emit timerPercentage( ( (double)m_timeElapsed / (double)m_currentTrack->duration() ) * 100.0 );
emit stopped();
setCurrentTrack( Tomahawk::result_ptr() ); setCurrentTrack( Tomahawk::result_ptr() );
Tomahawk::InfoSystem::InfoTypeMap map; Tomahawk::InfoSystem::InfoTypeMap map;
@@ -191,7 +192,7 @@ AudioEngine::stop()
else if ( TomahawkSettings::instance()->verboseNotifications() ) else if ( TomahawkSettings::instance()->verboseNotifications() )
{ {
QVariantMap stopInfo; QVariantMap stopInfo;
stopInfo["message"] = QString( "Tomahawk is stopped." ); stopInfo["message"] = tr( "Tomahawk is stopped." );
map[ Tomahawk::InfoSystem::InfoNotifyUser ] = QVariant::fromValue< QVariantMap >( stopInfo ); map[ Tomahawk::InfoSystem::InfoNotifyUser ] = QVariant::fromValue< QVariantMap >( stopInfo );
} }
@@ -413,7 +414,7 @@ AudioEngine::togglePrivateListeningMode()
#ifndef TOMAHAWK_HEADLESS #ifndef TOMAHAWK_HEADLESS
QAction *privacyToggle = ActionCollection::instance()->getAction( "togglePrivacy" ); QAction *privacyToggle = ActionCollection::instance()->getAction( "togglePrivacy" );
bool isPublic = TomahawkSettings::instance()->privateListeningMode() == TomahawkSettings::PublicListening; bool isPublic = TomahawkSettings::instance()->privateListeningMode() == TomahawkSettings::PublicListening;
privacyToggle->setText( tr( QString( isPublic ? "&Listen Privately" : "&Listen Publicly" ).toAscii().constData() ) ); privacyToggle->setText( ( isPublic ? tr( "&Listen Privately" ) : tr( "&Listen Publicly" ) ) );
privacyToggle->setIconVisibleInMenu( isPublic ); privacyToggle->setIconVisibleInMenu( isPublic );
#endif #endif
} }
@@ -450,9 +451,6 @@ AudioEngine::loadTrack( const Tomahawk::result_ptr& result )
tLog() << "Starting new song:" << m_currentTrack->url(); tLog() << "Starting new song:" << m_currentTrack->url();
emit loading( m_currentTrack ); emit loading( m_currentTrack );
if ( QNetworkReply* qnr_io = qobject_cast< QNetworkReply* >( io.data() ) )
connect( qnr_io, SIGNAL( error( QNetworkReply::NetworkError ) ), this, SLOT( ioStreamError( QNetworkReply::NetworkError ) ) );
if ( !isHttpResult( m_currentTrack->url() ) && !isLocalResult( m_currentTrack->url() ) ) if ( !isHttpResult( m_currentTrack->url() ) && !isLocalResult( m_currentTrack->url() ) )
{ {
if ( QNetworkReply* qnr_io = qobject_cast< QNetworkReply* >( io.data() ) ) if ( QNetworkReply* qnr_io = qobject_cast< QNetworkReply* >( io.data() ) )
@@ -498,8 +496,8 @@ AudioEngine::loadTrack( const Tomahawk::result_ptr& result )
emit started( m_currentTrack ); emit started( m_currentTrack );
if ( TomahawkSettings::instance()->verboseNotifications() ) if ( TomahawkSettings::instance()->verboseNotifications() )
sendNowPlayingNotification(); sendNowPlayingNotification();
if ( TomahawkSettings::instance()->privateListeningMode() != TomahawkSettings::FullyPrivate ) if ( TomahawkSettings::instance()->privateListeningMode() != TomahawkSettings::FullyPrivate )
{ {
DatabaseCommand_LogPlayback* cmd = new DatabaseCommand_LogPlayback( m_currentTrack, DatabaseCommand_LogPlayback::Started ); DatabaseCommand_LogPlayback* cmd = new DatabaseCommand_LogPlayback( m_currentTrack, DatabaseCommand_LogPlayback::Started );
@@ -605,16 +603,6 @@ AudioEngine::playItem( Tomahawk::PlaylistInterface* playlist, const Tomahawk::re
} }
} }
void
AudioEngine::ioStreamError( QNetworkReply::NetworkError error )
{
if ( error != QNetworkReply::NoError )
{
if ( canGoNext() )
loadNextTrack();
}
}
void void
AudioEngine::playlistNextTrackReady() AudioEngine::playlistNextTrackReady()
@@ -643,6 +631,9 @@ AudioEngine::onStateChanged( Phonon::State newState, Phonon::State oldState )
if ( newState == Phonon::ErrorState ) if ( newState == Phonon::ErrorState )
{ {
tLog() << "Phonon Error:" << m_mediaObject->errorString() << m_mediaObject->errorType(); tLog() << "Phonon Error:" << m_mediaObject->errorString() << m_mediaObject->errorType();
emit error( UnknownError );
stop();
return; return;
} }
if ( newState == Phonon::PlayingState ) if ( newState == Phonon::PlayingState )

View File

@@ -21,7 +21,6 @@
#include <QObject> #include <QObject>
#include <QTimer> #include <QTimer>
#include <QNetworkReply>
#include <phonon/MediaObject> #include <phonon/MediaObject>
#include <phonon/AudioOutput> #include <phonon/AudioOutput>
@@ -46,7 +45,7 @@ class DLLEXPORT AudioEngine : public QObject
Q_OBJECT Q_OBJECT
public: public:
enum AudioErrorCode { StreamReadError, AudioDeviceError, DecodeError }; enum AudioErrorCode { StreamReadError, AudioDeviceError, DecodeError, UnknownError };
enum AudioState { Stopped, Playing, Paused }; enum AudioState { Stopped, Playing, Paused };
static AudioEngine* instance(); static AudioEngine* instance();
@@ -124,7 +123,7 @@ signals:
void playlistChanged( Tomahawk::PlaylistInterface* playlist ); void playlistChanged( Tomahawk::PlaylistInterface* playlist );
void error( AudioErrorCode errorCode ); void error( AudioEngine::AudioErrorCode errorCode );
private slots: private slots:
bool loadTrack( const Tomahawk::result_ptr& result ); bool loadTrack( const Tomahawk::result_ptr& result );
@@ -137,7 +136,6 @@ private slots:
void setCurrentTrack( const Tomahawk::result_ptr& result ); void setCurrentTrack( const Tomahawk::result_ptr& result );
void ioStreamError( QNetworkReply::NetworkError );
private: private:
void setState( AudioState state ); void setState( AudioState state );

View File

@@ -33,10 +33,12 @@ Collection::Collection( const source_ptr& source, const QString& name, QObject*
: QObject( parent ) : QObject( parent )
, m_name( name ) , m_name( name )
, m_lastmodified( 0 ) , m_lastmodified( 0 )
, m_isLoaded( false ) , m_changed( false )
, m_source( source ) , m_source( source )
{ {
qDebug() << Q_FUNC_INFO << name << source->friendlyName(); qDebug() << Q_FUNC_INFO << name << source->friendlyName();
connect( source.data(), SIGNAL( synced() ), SLOT( onSynced() ) );
} }
@@ -209,20 +211,32 @@ Collection::setStations( const QList< dynplaylist_ptr >& stations )
void void
Collection::setTracks( const QList<unsigned int>& ids ) Collection::setTracks( const QList<unsigned int>& ids )
{ {
qDebug() << Q_FUNC_INFO << ids.count() << name(); tDebug() << Q_FUNC_INFO << ids.count() << name();
m_changed = true;
emit tracksAdded( ids ); emit tracksAdded( ids );
emit changed();
} }
void void
Collection::delTracks( const QList<unsigned int>& ids ) Collection::delTracks( const QList<unsigned int>& ids )
{ {
qDebug() << Q_FUNC_INFO << ids.count() << name(); tDebug() << Q_FUNC_INFO << ids.count() << name();
m_changed = true;
emit tracksRemoved( ids ); emit tracksRemoved( ids );
emit changed(); }
void
Collection::onSynced()
{
tDebug() << Q_FUNC_INFO << m_changed;
if ( m_changed )
{
m_changed = false;
emit changed();
}
} }

View File

@@ -49,8 +49,6 @@ public:
Collection( const source_ptr& source, const QString& name, QObject* parent = 0 ); Collection( const source_ptr& source, const QString& name, QObject* parent = 0 );
virtual ~Collection(); virtual ~Collection();
virtual void setLoaded() { m_isLoaded = true; }
virtual bool isLoaded() const { return m_isLoaded; }
virtual QString name() const; virtual QString name() const;
virtual void loadPlaylists() { qDebug() << Q_FUNC_INFO; } virtual void loadPlaylists() { qDebug() << Q_FUNC_INFO; }
@@ -107,8 +105,11 @@ protected:
QString m_name; QString m_name;
unsigned int m_lastmodified; // unix time of last change to collection unsigned int m_lastmodified; // unix time of last change to collection
private slots:
void onSynced();
private: private:
bool m_isLoaded; bool m_changed;
source_ptr m_source; source_ptr m_source;
QHash< QString, Tomahawk::playlist_ptr > m_playlists; QHash< QString, Tomahawk::playlist_ptr > m_playlists;

View File

@@ -52,7 +52,9 @@ public:
virtual bool jumpToCurrentTrack() = 0; virtual bool jumpToCurrentTrack() = 0;
public slots: public slots:
virtual void setQuery( const Tomahawk::query_ptr& query ) = 0; virtual void setArtist( const Tomahawk::artist_ptr& artist ) { Q_UNUSED( artist ); }
virtual void setAlbum( const Tomahawk::album_ptr& album ) { Q_UNUSED( album ); }
virtual void setQuery( const Tomahawk::query_ptr& query ) { Q_UNUSED( query ); }
signals: signals:
void nameChanged( const QString& ); void nameChanged( const QString& );

View File

@@ -93,6 +93,7 @@ ContextWidget::ContextWidget( QWidget* parent )
setAutoFillBackground( true ); setAutoFillBackground( true );
setFixedHeight( m_minHeight ); setFixedHeight( m_minHeight );
ensurePolished();
QPalette pal = palette(); QPalette pal = palette();
pal.setBrush( QPalette::Window, StyleHelper::headerLowerColor() ); pal.setBrush( QPalette::Window, StyleHelper::headerLowerColor() );
setPalette( pal ); setPalette( pal );
@@ -113,6 +114,22 @@ ContextWidget::~ContextWidget()
} }
void
ContextWidget::changeEvent( QEvent* e )
{
QWidget::changeEvent( e );
switch ( e->type() )
{
case QEvent::LanguageChange:
ui->retranslateUi( this );
break;
default:
break;
}
}
void void
ContextWidget::layoutViews( bool animate ) ContextWidget::layoutViews( bool animate )
{ {
@@ -212,6 +229,44 @@ ContextWidget::fadeOut( bool animate )
} }
void
ContextWidget::setArtist( const Tomahawk::artist_ptr& artist )
{
if ( artist.isNull() )
return;
m_artist = artist;
if ( height() > m_minHeight )
{
foreach ( ContextProxyPage* proxy, m_pages )
{
proxy->page()->setArtist( artist );
}
layoutViews( true );
}
}
void
ContextWidget::setAlbum( const Tomahawk::album_ptr& album )
{
if ( album.isNull() )
return;
m_album = album;
if ( height() > m_minHeight )
{
foreach ( ContextProxyPage* proxy, m_pages )
{
proxy->page()->setAlbum( album );
}
layoutViews( true );
}
}
void void
ContextWidget::setQuery( const Tomahawk::query_ptr& query, bool force ) ContextWidget::setQuery( const Tomahawk::query_ptr& query, bool force )
{ {
@@ -275,6 +330,8 @@ ContextWidget::onAnimationFinished()
fadeOut( false ); fadeOut( false );
m_scene->setSceneRect( ui->contextView->viewport()->rect() ); m_scene->setSceneRect( ui->contextView->viewport()->rect() );
layoutViews( false ); layoutViews( false );
setArtist( m_artist );
setAlbum( m_album );
setQuery( m_query, true ); setQuery( m_query, true );
ui->toggleButton->setText( tr( "Hide Footnotes" ) ); ui->toggleButton->setText( tr( "Hide Footnotes" ) );

View File

@@ -50,6 +50,8 @@ public:
~ContextWidget(); ~ContextWidget();
public slots: public slots:
void setArtist( const Tomahawk::artist_ptr& artist );
void setAlbum( const Tomahawk::album_ptr& album );
void setQuery( const Tomahawk::query_ptr& query, bool force = false ); void setQuery( const Tomahawk::query_ptr& query, bool force = false );
void toggleSize(); void toggleSize();
@@ -63,6 +65,7 @@ private slots:
protected: protected:
void paintEvent( QPaintEvent* e ); void paintEvent( QPaintEvent* e );
void resizeEvent( QResizeEvent* e ); void resizeEvent( QResizeEvent* e );
void changeEvent( QEvent* e );
private: private:
void fadeOut( bool animate ); void fadeOut( bool animate );
@@ -81,6 +84,8 @@ private:
int m_currentView; int m_currentView;
Tomahawk::artist_ptr m_artist;
Tomahawk::album_ptr m_album;
Tomahawk::query_ptr m_query; Tomahawk::query_ptr m_query;
bool m_visible; bool m_visible;
}; };

View File

@@ -32,6 +32,7 @@ RelatedArtistsContext::RelatedArtistsContext()
{ {
m_relatedView = new ArtistView(); m_relatedView = new ArtistView();
m_relatedView->setGuid( "RelatedArtistsContext" ); m_relatedView->setGuid( "RelatedArtistsContext" );
m_relatedView->setUpdatesContextView( false );
m_relatedModel = new TreeModel( m_relatedView ); m_relatedModel = new TreeModel( m_relatedView );
m_relatedModel->setColumnStyle( TreeModel::TrackOnly ); m_relatedModel->setColumnStyle( TreeModel::TrackOnly );
m_relatedView->setTreeModel( m_relatedModel ); m_relatedView->setTreeModel( m_relatedModel );
@@ -58,15 +59,17 @@ RelatedArtistsContext::~RelatedArtistsContext()
void void
RelatedArtistsContext::setQuery( const Tomahawk::query_ptr& query ) RelatedArtistsContext::setArtist( const Tomahawk::artist_ptr& artist )
{ {
if ( !m_query.isNull() && query->artist() == m_query->artist() ) if ( artist.isNull() )
return;
if ( !m_artist.isNull() && m_artist->name() == artist->name() )
return; return;
m_query = query; m_artist = artist;
Tomahawk::InfoSystem::InfoStringHash artistInfo; Tomahawk::InfoSystem::InfoStringHash artistInfo;
artistInfo["artist"] = query->artist(); artistInfo["artist"] = artist->name();
Tomahawk::InfoSystem::InfoRequestData requestData; Tomahawk::InfoSystem::InfoRequestData requestData;
requestData.caller = m_infoId; requestData.caller = m_infoId;
@@ -78,6 +81,26 @@ RelatedArtistsContext::setQuery( const Tomahawk::query_ptr& query )
} }
void
RelatedArtistsContext::setQuery( const Tomahawk::query_ptr& query )
{
if ( query.isNull() )
return;
setArtist( Artist::get( query->artist(), false ) );
}
void
RelatedArtistsContext::setAlbum( const Tomahawk::album_ptr& album )
{
if ( album.isNull() )
return;
setArtist( album->artist() );
}
void void
RelatedArtistsContext::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output ) RelatedArtistsContext::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output )
{ {
@@ -89,9 +112,9 @@ RelatedArtistsContext::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData req
if ( output.canConvert< QVariantMap >() ) if ( output.canConvert< QVariantMap >() )
{ {
if ( trackInfo["artist"] != m_query->artist() ) if ( trackInfo["artist"] != m_artist->name() )
{ {
qDebug() << "Returned info was for:" << trackInfo["artist"] << "- was looking for:" << m_query->artist(); qDebug() << "Returned info was for:" << trackInfo["artist"] << "- was looking for:" << m_artist->name();
return; return;
} }
} }

View File

@@ -23,6 +23,8 @@
#include "dllmacro.h" #include "dllmacro.h"
#include "artist.h"
#include "album.h"
#include "query.h" #include "query.h"
#include "context/ContextPage.h" #include "context/ContextPage.h"
#include "infosystem/infosystem.h" #include "infosystem/infosystem.h"
@@ -48,6 +50,8 @@ public:
virtual bool jumpToCurrentTrack() { return false; } virtual bool jumpToCurrentTrack() { return false; }
public slots: public slots:
virtual void setArtist( const Tomahawk::artist_ptr& artist );
virtual void setAlbum( const Tomahawk::album_ptr& album );
virtual void setQuery( const Tomahawk::query_ptr& query ); virtual void setQuery( const Tomahawk::query_ptr& query );
private slots: private slots:
@@ -61,7 +65,7 @@ private:
QGraphicsProxyWidget* m_proxy; QGraphicsProxyWidget* m_proxy;
QString m_infoId; QString m_infoId;
Tomahawk::query_ptr m_query; Tomahawk::artist_ptr m_artist;
}; };
#endif // RELATEDARTISTSCONTEXT_H #endif // RELATEDARTISTSCONTEXT_H

View File

@@ -58,15 +58,17 @@ TopTracksContext::~TopTracksContext()
void void
TopTracksContext::setQuery( const Tomahawk::query_ptr& query ) TopTracksContext::setArtist( const Tomahawk::artist_ptr& artist )
{ {
if ( !m_query.isNull() && query->artist() == m_query->artist() ) if ( artist.isNull() )
return;
if ( !m_artist.isNull() && m_artist->name() == artist->name() )
return; return;
m_query = query; m_artist = artist;
Tomahawk::InfoSystem::InfoStringHash artistInfo; Tomahawk::InfoSystem::InfoStringHash artistInfo;
artistInfo["artist"] = query->artist(); artistInfo["artist"] = artist->name();
Tomahawk::InfoSystem::InfoRequestData requestData; Tomahawk::InfoSystem::InfoRequestData requestData;
requestData.caller = m_infoId; requestData.caller = m_infoId;
@@ -78,6 +80,26 @@ TopTracksContext::setQuery( const Tomahawk::query_ptr& query )
} }
void
TopTracksContext::setAlbum( const Tomahawk::album_ptr& album )
{
if ( album.isNull() )
return;
setArtist( album->artist() );
}
void
TopTracksContext::setQuery( const Tomahawk::query_ptr& query )
{
if ( query.isNull() )
return;
setArtist( Artist::get( query->artist(), false ) );
}
void void
TopTracksContext::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output ) TopTracksContext::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output )
{ {
@@ -89,9 +111,9 @@ TopTracksContext::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestD
if ( output.canConvert< QVariantMap >() ) if ( output.canConvert< QVariantMap >() )
{ {
if ( trackInfo["artist"] != m_query->artist() ) if ( trackInfo["artist"] != m_artist->name() )
{ {
qDebug() << "Returned info was for:" << trackInfo["artist"] << "- was looking for:" << m_query->artist(); qDebug() << "Returned info was for:" << trackInfo["artist"] << "- was looking for:" << m_artist->name();
return; return;
} }
} }
@@ -107,7 +129,7 @@ TopTracksContext::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestD
int i = 0; int i = 0;
foreach ( const QString& track, tracks ) foreach ( const QString& track, tracks )
{ {
query_ptr query = Query::get( m_query->artist(), track, QString(), uuid() ); query_ptr query = Query::get( m_artist->name(), track, QString(), uuid() );
m_topHitsModel->append( query ); m_topHitsModel->append( query );
if ( ++i == 15 ) if ( ++i == 15 )

View File

@@ -23,6 +23,8 @@
#include "dllmacro.h" #include "dllmacro.h"
#include "artist.h"
#include "album.h"
#include "query.h" #include "query.h"
#include "context/ContextPage.h" #include "context/ContextPage.h"
#include "infosystem/infosystem.h" #include "infosystem/infosystem.h"
@@ -48,6 +50,8 @@ public:
virtual bool jumpToCurrentTrack() { return false; } virtual bool jumpToCurrentTrack() { return false; }
public slots: public slots:
virtual void setArtist( const Tomahawk::artist_ptr& artist );
virtual void setAlbum( const Tomahawk::album_ptr& album );
virtual void setQuery( const Tomahawk::query_ptr& query ); virtual void setQuery( const Tomahawk::query_ptr& query );
private slots: private slots:
@@ -61,7 +65,7 @@ private:
QGraphicsProxyWidget* m_proxy; QGraphicsProxyWidget* m_proxy;
QString m_infoId; QString m_infoId;
Tomahawk::query_ptr m_query; Tomahawk::artist_ptr m_artist;
}; };
#endif // TOPTRACKSCONTEXT_H #endif // TOPTRACKSCONTEXT_H

View File

@@ -22,22 +22,68 @@ using namespace Tomahawk;
void void
WikipediaContext::setQuery( const Tomahawk::query_ptr& query ) WikipediaContext::setArtist( const Tomahawk::artist_ptr& artist )
{ {
if ( !m_query.isNull() && query->artist() == m_query->artist() ) if ( artist.isNull() )
return;
if ( !m_artist.isNull() && m_artist->name() == artist->name() )
return; return;
m_query = query; m_artist = artist;
webView()->load( QString( "http://en.wikipedia.org/w/index.php?useformat=mobile&title=%1" ).arg( query->artist() ) );
webView()->load( QString( "http://en.wikipedia.org/w/index.php?useformat=mobile&title=%1" ).arg( m_artist->name() ) );
}
void
WikipediaContext::setAlbum( const Tomahawk::album_ptr& album )
{
if ( album.isNull() )
return;
setArtist( album->artist() );
}
void
WikipediaContext::setQuery( const Tomahawk::query_ptr& query )
{
if ( query.isNull() )
return;
setArtist( Artist::get( query->artist(), false ) );
}
void
LastfmContext::setArtist( const Tomahawk::artist_ptr& artist )
{
if ( artist.isNull() )
return;
if ( !m_artist.isNull() && m_artist->name() == artist->name() )
return;
m_artist = artist;
webView()->load( QString( "http://last.fm/music/%1" ).arg( m_artist->name() ) );
}
void
LastfmContext::setAlbum( const Tomahawk::album_ptr& album )
{
if ( album.isNull() )
return;
setArtist( album->artist() );
} }
void void
LastfmContext::setQuery( const Tomahawk::query_ptr& query ) LastfmContext::setQuery( const Tomahawk::query_ptr& query )
{ {
if ( !m_query.isNull() && query->artist() == m_query->artist() ) if ( query.isNull() )
return; return;
m_query = query; setArtist( Artist::get( query->artist(), false ) );
webView()->load( QString( "http://last.fm/music/%1" ).arg( query->artist() ) );
} }

View File

@@ -23,6 +23,8 @@
#include "dllmacro.h" #include "dllmacro.h"
#include "artist.h"
#include "album.h"
#include "query.h" #include "query.h"
#include "WebContext.h" #include "WebContext.h"
@@ -42,10 +44,12 @@ public:
virtual bool jumpToCurrentTrack() { return false; } virtual bool jumpToCurrentTrack() { return false; }
public slots: public slots:
virtual void setArtist( const Tomahawk::artist_ptr& artist );
virtual void setAlbum( const Tomahawk::album_ptr& album );
virtual void setQuery( const Tomahawk::query_ptr& query ); virtual void setQuery( const Tomahawk::query_ptr& query );
private: private:
Tomahawk::query_ptr m_query; Tomahawk::artist_ptr m_artist;
}; };
@@ -65,10 +69,12 @@ public:
virtual bool jumpToCurrentTrack() { return false; } virtual bool jumpToCurrentTrack() { return false; }
public slots: public slots:
virtual void setArtist( const Tomahawk::artist_ptr& artist );
virtual void setAlbum( const Tomahawk::album_ptr& album );
virtual void setQuery( const Tomahawk::query_ptr& query ); virtual void setQuery( const Tomahawk::query_ptr& query );
private: private:
Tomahawk::query_ptr m_query; Tomahawk::artist_ptr m_artist;
}; };
#endif // WIKIPEDIACONTEXT_H #endif // WIKIPEDIACONTEXT_H

View File

@@ -39,8 +39,11 @@ ContextMenu::ContextMenu( QWidget* parent )
m_supportedActions = ActionPlay | ActionQueue | ActionCopyLink; m_supportedActions = ActionPlay | ActionQueue | ActionCopyLink;
} }
ContextMenu::~ContextMenu() ContextMenu::~ContextMenu()
{} {
}
void void
ContextMenu::clear() ContextMenu::clear()
@@ -50,23 +53,22 @@ ContextMenu::clear()
m_queries.clear(); m_queries.clear();
m_albums.clear(); m_albums.clear();
m_artists.clear(); m_artists.clear();
} }
unsigned int unsigned int
ContextMenu::itemCount() const ContextMenu::itemCount() const
{ {
return m_queries.count() + m_artists.count() + m_albums.count(); return m_queries.count() + m_artists.count() + m_albums.count();
} }
void void
ContextMenu::setQueries( const QList<Tomahawk::query_ptr>& queries ) ContextMenu::setQueries( const QList<Tomahawk::query_ptr>& queries )
{ {
if ( queries.isEmpty() ) if ( queries.isEmpty() )
return; return;
QMenu::clear(); QMenu::clear();
m_queries.clear(); m_queries.clear();
m_queries << queries; m_queries << queries;
@@ -87,11 +89,8 @@ ContextMenu::setQueries( const QList<Tomahawk::query_ptr>& queries )
if ( m_supportedActions & ActionDelete ) if ( m_supportedActions & ActionDelete )
m_sigmap->setMapping( addAction( queries.count() > 1 ? tr( "&Delete Items" ) : tr( "&Delete Item" ) ), ActionDelete ); m_sigmap->setMapping( addAction( queries.count() > 1 ? tr( "&Delete Items" ) : tr( "&Delete Item" ) ), ActionDelete );
foreach ( QAction* action, actions() ) foreach ( QAction* action, actions() )
{ {
connect( action, SIGNAL( triggered() ), m_sigmap, SLOT( map() ) ); connect( action, SIGNAL( triggered() ), m_sigmap, SLOT( map() ) );
} }
} }
@@ -107,7 +106,6 @@ ContextMenu::setQuery( const Tomahawk::query_ptr& query )
} }
void void
ContextMenu::setAlbums( const QList<Tomahawk::album_ptr>& albums ) ContextMenu::setAlbums( const QList<Tomahawk::album_ptr>& albums )
{ {
@@ -185,6 +183,7 @@ ContextMenu::setArtist( const Tomahawk::artist_ptr& artist )
setArtists( artists ); setArtists( artists );
} }
void void
ContextMenu::onTriggered( int action ) ContextMenu::onTriggered( int action )
{ {
@@ -205,7 +204,8 @@ ContextMenu::onTriggered( int action )
void ContextMenu::addToQueue() void
ContextMenu::addToQueue()
{ {
foreach ( const query_ptr& query, m_queries ) foreach ( const query_ptr& query, m_queries )
{ {

View File

@@ -39,7 +39,6 @@ public:
ActionQueue = 2, ActionQueue = 2,
ActionDelete = 4, ActionDelete = 4,
ActionCopyLink = 8 ActionCopyLink = 8
}; };
explicit ContextMenu( QWidget* parent = 0 ); explicit ContextMenu( QWidget* parent = 0 );

View File

@@ -73,7 +73,15 @@ Database::loadIndex()
void void
Database::enqueue( QSharedPointer<DatabaseCommand> lc ) Database::enqueue( const QList< QSharedPointer<DatabaseCommand> >& lc )
{
qDebug() << "Enqueueing" << lc.count() << "commands to rw thread";
m_workerRW->enqueue( lc );
}
void
Database::enqueue( const QSharedPointer<DatabaseCommand>& lc )
{ {
if ( lc->doesMutates() ) if ( lc->doesMutates() )
{ {

View File

@@ -66,7 +66,8 @@ signals:
void newJobRW( QSharedPointer<DatabaseCommand> ); void newJobRW( QSharedPointer<DatabaseCommand> );
public slots: public slots:
void enqueue( QSharedPointer<DatabaseCommand> lc ); void enqueue( const QSharedPointer<DatabaseCommand>& lc );
void enqueue( const QList< QSharedPointer<DatabaseCommand> >& lc );
private slots: private slots:
void setIsReadyTrue() { m_ready = true; } void setIsReadyTrue() { m_ready = true; }

View File

@@ -69,22 +69,8 @@ DatabaseCollection::loadStations()
connect( cmd, SIGNAL( stationLoaded( Tomahawk::source_ptr, QVariantList ) ), connect( cmd, SIGNAL( stationLoaded( Tomahawk::source_ptr, QVariantList ) ),
SLOT( stationCreated( const Tomahawk::source_ptr&, const QVariantList& ) ) ); SLOT( stationCreated( const Tomahawk::source_ptr&, const QVariantList& ) ) );
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );}
/*void
DatabaseCollection::loadTracks()
{
qDebug() << Q_FUNC_INFO << source()->userName();
setLoaded();
DatabaseCommand_AllTracks* cmd = new DatabaseCommand_AllTracks( source()->collection() );
connect( cmd, SIGNAL( tracks( QList<Tomahawk::query_ptr>, QVariant ) ),
SLOT( setTracks( QList<Tomahawk::query_ptr> ) ) );
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) ); Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
}*/ }
void void
@@ -143,19 +129,8 @@ DatabaseCollection::stations()
} }
/*QList< Tomahawk::query_ptr > void
DatabaseCollection::tracks() DatabaseCollection::autoPlaylistCreated( const source_ptr& source, const QVariantList& data )
{
if ( !isLoaded() )
{
loadTracks();
}
return Collection::tracks();
}*/
void DatabaseCollection::autoPlaylistCreated( const source_ptr& source, const QVariantList& data )
{ {
dynplaylist_ptr p( new DynamicPlaylist( source, //src dynplaylist_ptr p( new DynamicPlaylist( source, //src
data[0].toString(), //current rev data[0].toString(), //current rev
@@ -172,7 +147,8 @@ void DatabaseCollection::autoPlaylistCreated( const source_ptr& source, const QV
} }
void DatabaseCollection::stationCreated( const source_ptr& source, const QVariantList& data ) void
DatabaseCollection::stationCreated( const source_ptr& source, const QVariantList& data )
{ {
dynplaylist_ptr p( new DynamicPlaylist( source, //src dynplaylist_ptr p( new DynamicPlaylist( source, //src
data[0].toString(), //current rev data[0].toString(), //current rev

View File

@@ -80,12 +80,14 @@ DatabaseCommand::setSource( const Tomahawk::source_ptr& s )
m_source = s; m_source = s;
} }
const Tomahawk::source_ptr& const Tomahawk::source_ptr&
DatabaseCommand::source() const DatabaseCommand::source() const
{ {
return m_source; return m_source;
} }
DatabaseCommand* DatabaseCommand*
DatabaseCommand::factory( const QVariant& op, const source_ptr& source ) DatabaseCommand::factory( const QVariant& op, const source_ptr& source )
{ {
@@ -139,7 +141,8 @@ DatabaseCommand::factory( const QVariant& op, const source_ptr& source )
cmd->setSource( source ); cmd->setSource( source );
QJson::QObjectHelper::qvariant2qobject( op.toMap(), cmd ); QJson::QObjectHelper::qvariant2qobject( op.toMap(), cmd );
return cmd; return cmd;
} else if( name == "createdynamicplaylist" ) }
else if( name == "createdynamicplaylist" )
{ {
DatabaseCommand_CreateDynamicPlaylist * cmd = new DatabaseCommand_CreateDynamicPlaylist; DatabaseCommand_CreateDynamicPlaylist * cmd = new DatabaseCommand_CreateDynamicPlaylist;
cmd->setSource( source ); cmd->setSource( source );
@@ -183,7 +186,7 @@ DatabaseCommand::factory( const QVariant& op, const source_ptr& source )
return cmd; return cmd;
} }
qDebug() << "ERROR in" << Q_FUNC_INFO << name; qDebug() << "Unknown database command" << name;
// Q_ASSERT( false ); // Q_ASSERT( false );
return NULL; return NULL;
} }

View File

@@ -70,6 +70,7 @@ public:
const Tomahawk::source_ptr& source() const; const Tomahawk::source_ptr& source() const;
virtual bool loggable() const { return false; } virtual bool loggable() const { return false; }
virtual bool groupable() const { return false; }
virtual bool singletonCmd() const { return false; } virtual bool singletonCmd() const { return false; }
virtual bool localOnly() const { return false; } virtual bool localOnly() const { return false; }

View File

@@ -24,7 +24,6 @@
#include "album.h" #include "album.h"
#include "collection.h" #include "collection.h"
#include "database/database.h" #include "database/database.h"
#include "databasecommand_collectionstats.h"
#include "databaseimpl.h" #include "databaseimpl.h"
#include "network/dbsyncconnection.h" #include "network/dbsyncconnection.h"
#include "network/servent.h" #include "network/servent.h"
@@ -56,32 +55,17 @@ DatabaseCommand_AddFiles::files() const
void void
DatabaseCommand_AddFiles::postCommitHook() DatabaseCommand_AddFiles::postCommitHook()
{ {
if ( source().isNull() || source()->collection().isNull() )
{
qDebug() << "Source has gone offline, not emitting to GUI.";
return;
}
// make the collection object emit its tracksAdded signal, so the // make the collection object emit its tracksAdded signal, so the
// collection browser will update/fade in etc. // collection browser will update/fade in etc.
Collection* coll = source()->collection().data(); Collection* coll = source()->collection().data();
connect( this, SIGNAL( notify( QList<unsigned int> ) ), connect( this, SIGNAL( notify( QList<unsigned int> ) ),
coll, SLOT( setTracks( QList<unsigned int> ) ), coll, SLOT( setTracks( QList<unsigned int> ) ), Qt::QueuedConnection );
Qt::QueuedConnection );
emit notify( m_ids ); emit notify( m_ids );
if ( source()->isLocal() ) if ( source()->isLocal() )
{
Servent::instance()->triggerDBSync(); Servent::instance()->triggerDBSync();
// Re-calculate local db stats
DatabaseCommand_CollectionStats* cmd = new DatabaseCommand_CollectionStats( SourceList::instance()->getLocal() );
connect( cmd, SIGNAL( done( QVariantMap ) ),
SourceList::instance()->getLocal().data(), SLOT( setStats( QVariantMap ) ), Qt::QueuedConnection );
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
}
} }
@@ -94,23 +78,21 @@ DatabaseCommand_AddFiles::exec( DatabaseImpl* dbi )
TomahawkSqlQuery query_file = dbi->newquery(); TomahawkSqlQuery query_file = dbi->newquery();
TomahawkSqlQuery query_filejoin = dbi->newquery(); TomahawkSqlQuery query_filejoin = dbi->newquery();
TomahawkSqlQuery query_trackattr = dbi->newquery(); TomahawkSqlQuery query_trackattr = dbi->newquery();
TomahawkSqlQuery query_file_del = dbi->newquery();
query_file.prepare( "INSERT INTO file(source, url, size, mtime, md5, mimetype, duration, bitrate) VALUES (?, ?, ?, ?, ?, ?, ?, ?)" ); query_file.prepare( "INSERT INTO file(source, url, size, mtime, md5, mimetype, duration, bitrate) VALUES (?, ?, ?, ?, ?, ?, ?, ?)" );
query_filejoin.prepare( "INSERT INTO file_join(file, artist, album, track, albumpos) VALUES (?, ?, ?, ?, ?)" ); query_filejoin.prepare( "INSERT INTO file_join(file, artist, album, track, albumpos) VALUES (?, ?, ?, ?, ?)" );
query_trackattr.prepare( "INSERT INTO track_attributes(id, k, v) VALUES (?, ?, ?)" ); query_trackattr.prepare( "INSERT INTO track_attributes(id, k, v) VALUES (?, ?, ?)" );
query_file_del.prepare( QString( "DELETE FROM file WHERE source %1 AND url = ?" )
.arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) ) );
int added = 0; int added = 0;
QVariant srcid = source()->isLocal() ? QVariant( QVariant::Int ) : source()->id(); QVariant srcid = source()->isLocal() ? QVariant( QVariant::Int ) : source()->id();
qDebug() << "Adding" << m_files.length() << "files to db for source" << srcid; qDebug() << "Adding" << m_files.length() << "files to db for source" << srcid;
QList<QVariant>::iterator it; QList<QVariant>::iterator it;
for( it = m_files.begin(); it != m_files.end(); ++it ) for ( it = m_files.begin(); it != m_files.end(); ++it )
{ {
QVariant& v = *it; QVariant& v = *it;
QVariantMap m = v.toMap(); QVariantMap m = v.toMap();
int fileid = 0, artistid = 0, albumid = 0, trackid = 0;
QString url = m.value( "url" ).toString(); QString url = m.value( "url" ).toString();
int mtime = m.value( "mtime" ).toInt(); int mtime = m.value( "mtime" ).toInt();
@@ -125,10 +107,6 @@ DatabaseCommand_AddFiles::exec( DatabaseImpl* dbi )
uint albumpos = m.value( "albumpos" ).toUInt(); uint albumpos = m.value( "albumpos" ).toUInt();
int year = m.value( "year" ).toInt(); int year = m.value( "year" ).toInt();
int fileid = 0, artistid = 0, albumid = 0, trackid = 0;
query_file_del.bindValue( 0, url );
query_file_del.exec();
query_file.bindValue( 0, srcid ); query_file.bindValue( 0, srcid );
query_file.bindValue( 1, url ); query_file.bindValue( 1, url );
query_file.bindValue( 2, size ); query_file.bindValue( 2, size );
@@ -137,28 +115,17 @@ DatabaseCommand_AddFiles::exec( DatabaseImpl* dbi )
query_file.bindValue( 5, mimetype ); query_file.bindValue( 5, mimetype );
query_file.bindValue( 6, duration ); query_file.bindValue( 6, duration );
query_file.bindValue( 7, bitrate ); query_file.bindValue( 7, bitrate );
if( !query_file.exec() ) query_file.exec();
{
qDebug() << "Failed to insert to file:" if ( added % 1000 == 0 )
<< query_file.lastError().databaseText() qDebug() << "Inserted" << added;
<< query_file.lastError().driverText()
<< query_file.boundValues();
continue;
}
else
{
if( added % 1000 == 0 )
qDebug() << "Inserted" << added;
}
// get internal IDs for art/alb/trk // get internal IDs for art/alb/trk
fileid = query_file.lastInsertId().toInt(); fileid = query_file.lastInsertId().toInt();
m.insert( "id", fileid ); m.insert( "id", fileid );
// this is the qvariant(map) the remote will get // this is the qvariant(map) the remote will get
v = m; v = m;
if( !source()->isLocal() )
url = QString( "servent://%1\t%2" ).arg( source()->userName() ).arg( url );
artistid = dbi->artistId( artist, true ); artistid = dbi->artistId( artist, true );
if ( artistid < 1 ) if ( artistid < 1 )
continue; continue;
@@ -173,44 +140,13 @@ DatabaseCommand_AddFiles::exec( DatabaseImpl* dbi )
query_filejoin.bindValue( 2, albumid > 0 ? albumid : QVariant( QVariant::Int ) ); query_filejoin.bindValue( 2, albumid > 0 ? albumid : QVariant( QVariant::Int ) );
query_filejoin.bindValue( 3, trackid ); query_filejoin.bindValue( 3, trackid );
query_filejoin.bindValue( 4, albumpos ); query_filejoin.bindValue( 4, albumpos );
if ( !query_filejoin.exec() ) query_filejoin.exec();
{
qDebug() << "Error inserting into file_join table";
continue;
}
query_trackattr.bindValue( 0, trackid ); query_trackattr.bindValue( 0, trackid );
query_trackattr.bindValue( 1, "releaseyear" ); query_trackattr.bindValue( 1, "releaseyear" );
query_trackattr.bindValue( 2, year ); query_trackattr.bindValue( 2, year );
query_trackattr.exec(); query_trackattr.exec();
/* QVariantMap attr;
Tomahawk::query_ptr query = Tomahawk::Query::get( artist, track, album );
attr["releaseyear"] = m.value( "year" );
Tomahawk::artist_ptr artistptr = Tomahawk::Artist::get( artistid, artist );
Tomahawk::album_ptr albumptr = Tomahawk::Album::get( albumid, album, artistptr );
Tomahawk::result_ptr result = Tomahawk::Result::get( url );
result->setModificationTime( mtime );
result->setSize( size );
result->setMimetype( mimetype );
result->setDuration( duration );
result->setBitrate( bitrate );
result->setArtist( artistptr );
result->setAlbum( albumptr );
result->setTrack( track );
result->setAlbumPos( albumpos );
result->setAttributes( attr );
result->setCollection( source()->collection() );
result->setScore( 1.0 );
result->setId( trackid );
QList<Tomahawk::result_ptr> results;
results << result;
query->addResults( results );
m_queries << query;*/
m_ids << fileid; m_ids << fileid;
added++; added++;
} }
@@ -219,6 +155,6 @@ DatabaseCommand_AddFiles::exec( DatabaseImpl* dbi )
if ( added ) if ( added )
source()->updateIndexWhenSynced(); source()->updateIndexWhenSynced();
qDebug() << "Committing" << added << "tracks..."; tDebug() << "Committing" << added << "tracks...";
emit done( m_files, source()->collection() ); emit done( m_files, source()->collection() );
} }

View File

@@ -35,20 +35,21 @@ DatabaseCommand_addSource::DatabaseCommand_addSource( const QString& username, c
void void
DatabaseCommand_addSource::exec( DatabaseImpl* dbi ) DatabaseCommand_addSource::exec( DatabaseImpl* dbi )
{ {
Q_ASSERT( !m_fname.isEmpty() );
TomahawkSqlQuery query = dbi->newquery(); TomahawkSqlQuery query = dbi->newquery();
query.prepare( "SELECT id, friendlyname FROM source WHERE name = ?" ); query.prepare( "SELECT id FROM source WHERE name = ?" );
query.addBindValue( m_username ); query.addBindValue( m_username );
query.exec(); query.exec();
if ( query.next() ) if ( query.next() )
{ {
unsigned int id = query.value( 0 ).toInt(); unsigned int id = query.value( 0 ).toInt();
QString fname = query.value( 1 ).toString();
query.prepare( "UPDATE source SET isonline = 'true', friendlyname = ? WHERE id = ?" ); query.prepare( "UPDATE source SET isonline = 'true', friendlyname = ? WHERE id = ?" );
query.addBindValue( m_fname ); query.addBindValue( m_fname );
query.addBindValue( id ); query.addBindValue( id );
query.exec(); query.exec();
emit done( id, fname ); emit done( id, m_fname );
return; return;
} }

View File

@@ -23,6 +23,7 @@
#include <QVariantMap> #include <QVariantMap>
#include "artist.h" #include "artist.h"
#include "collection.h"
#include "typedefs.h" #include "typedefs.h"
#include "databasecommand.h" #include "databasecommand.h"

View File

@@ -25,7 +25,6 @@
#include "collection.h" #include "collection.h"
#include "source.h" #include "source.h"
#include "database/database.h" #include "database/database.h"
#include "databasecommand_collectionstats.h"
#include "databaseimpl.h" #include "databaseimpl.h"
#include "network/servent.h" #include "network/servent.h"
#include "utils/logger.h" #include "utils/logger.h"
@@ -38,7 +37,7 @@ using namespace Tomahawk;
void void
DatabaseCommand_DeleteFiles::postCommitHook() DatabaseCommand_DeleteFiles::postCommitHook()
{ {
if ( !m_files.count() ) if ( !m_idList.count() )
return; return;
// make the collection object emit its tracksAdded signal, so the // make the collection object emit its tracksAdded signal, so the
@@ -48,13 +47,10 @@ DatabaseCommand_DeleteFiles::postCommitHook()
connect( this, SIGNAL( notify( QList<unsigned int> ) ), connect( this, SIGNAL( notify( QList<unsigned int> ) ),
coll, SLOT( delTracks( QList<unsigned int> ) ), Qt::QueuedConnection ); coll, SLOT( delTracks( QList<unsigned int> ) ), Qt::QueuedConnection );
tDebug() << "Notifying of deleted tracks:" << m_ids.size() << "from source" << source()->id(); tDebug() << "Notifying of deleted tracks:" << m_idList.size() << "from source" << source()->id();
QList<unsigned int> ids; emit notify( m_idList );
foreach ( QVariant id, m_ids )
ids << id.toUInt();
emit notify( ids );
if( source()->isLocal() ) if ( source()->isLocal() )
Servent::instance()->triggerDBSync(); Servent::instance()->triggerDBSync();
} }
@@ -66,111 +62,78 @@ DatabaseCommand_DeleteFiles::exec( DatabaseImpl* dbi )
QVariant srcid = source()->isLocal() ? QVariant( QVariant::Int ) : source()->id(); QVariant srcid = source()->isLocal() ? QVariant( QVariant::Int ) : source()->id();
TomahawkSqlQuery delquery = dbi->newquery(); TomahawkSqlQuery delquery = dbi->newquery();
QString lastPath;
if ( source()->isLocal() ) if ( m_deleteAll )
{
TomahawkSqlQuery dirquery = dbi->newquery();
dirquery.prepare( QString( "SELECT id FROM file WHERE source %1" )
.arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) ) );
dirquery.exec();
while ( dirquery.next() )
m_idList << dirquery.value( 0 ).toUInt();
}
else if ( source()->isLocal() )
{ {
if ( m_dir.path() != QString( "." ) ) if ( m_dir.path() != QString( "." ) )
{ {
tDebug() << "Deleting" << m_dir.path() << "from db for localsource" << srcid; tDebug() << "Deleting" << m_dir.path() << "from db for localsource" << srcid;
TomahawkSqlQuery dirquery = dbi->newquery(); TomahawkSqlQuery dirquery = dbi->newquery();
QString path( "file://" + m_dir.canonicalPath() + "/%" ); QString path( "file://" + m_dir.canonicalPath() + "/%" );
dirquery.prepare( QString( "SELECT id, url FROM file WHERE source IS NULL AND url LIKE '%1'" ).arg( TomahawkUtils::sqlEscape( path ) ) ); dirquery.prepare( QString( "SELECT id FROM file WHERE source IS NULL AND url LIKE '%1'" ).arg( TomahawkUtils::sqlEscape( path ) ) );
dirquery.exec(); dirquery.exec();
while ( dirquery.next() ) while ( dirquery.next() )
{ {
QFileInfo fi( dirquery.value( 1 ).toString().mid( 7 ) ); // remove file:// m_ids << dirquery.value( 0 );
if ( fi.canonicalPath() != m_dir.canonicalPath() ) m_idList << dirquery.value( 0 ).toUInt();
{
if ( lastPath != fi.canonicalPath() )
tDebug() << "Skipping subdir:" << fi.canonicalPath();
lastPath = fi.canonicalPath();
continue;
}
m_files << dirquery.value( 1 ).toString();
m_ids << dirquery.value( 0 ).toUInt();
} }
} }
else if ( !m_ids.isEmpty() ) else if ( !m_ids.isEmpty() )
{ {
tDebug() << Q_FUNC_INFO << "deleting given ids"; tDebug() << Q_FUNC_INFO << "deleting given ids";
TomahawkSqlQuery dirquery = dbi->newquery(); foreach ( const QVariant& id, m_ids )
m_idList << id.toUInt();
QString idstring;
foreach( const QVariant& id, m_ids )
idstring.append( id.toString() + ", " );
idstring.chop( 2 ); //remove the trailing ", "
dirquery.prepare( QString( "SELECT id, url FROM file WHERE source IS NULL AND id IN ( %1 )" ).arg( idstring ) );
dirquery.exec();
while ( dirquery.next() )
{
m_files << dirquery.value( 1 ).toString();
}
} }
else if ( m_deleteAll )
{
TomahawkSqlQuery dirquery = dbi->newquery();
dirquery.prepare( QString( "SELECT id, url FROM file WHERE source IS NULL" ) );
dirquery.exec();
while ( dirquery.next() )
{
m_ids << dirquery.value( 0 ).toString();
m_files << dirquery.value( 1 ).toString();
}
}
}
else
{
if ( m_deleteAll )
{
TomahawkSqlQuery dirquery = dbi->newquery();
dirquery.prepare( QString( "SELECT url FROM file WHERE source = %1" ).arg( source()->id() ) );
dirquery.exec();
while ( dirquery.next() )
m_ids << dirquery.value( 0 ).toString();
}
foreach( const QVariant& id, m_ids )
m_files << QString( "servent://%1\t%2" ).arg( source()->userName() ).arg( id.toString() );
} }
if ( m_deleteAll ) if ( m_deleteAll )
{ {
if ( !m_ids.isEmpty() ) delquery.prepare( QString( "DELETE FROM file WHERE source %1" )
{ .arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) ) );
delquery.prepare( QString( "DELETE FROM file WHERE source %1" ) delquery.exec();
.arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) ) );
delquery.exec();
}
} }
else if ( !m_ids.isEmpty() ) else if ( !m_ids.isEmpty() )
{ {
delquery.prepare( QString( "DELETE FROM file WHERE source %1 AND %2 IN ( ? )" )
.arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) )
.arg( source()->isLocal() ? "id" : "url" ) );
QString idstring; QString idstring;
foreach( const QVariant& id, m_ids ) foreach ( const QVariant& id, m_ids )
idstring.append( id.toString() + ", " ); idstring.append( id.toString() + ", " );
idstring.chop( 2 ); //remove the trailing ", " idstring.chop( 2 ); //remove the trailing ", "
delquery.prepare( QString( "DELETE FROM file WHERE source %1 AND %2 IN ( %3 )" ) if ( !source()->isLocal() )
{
delquery.prepare( QString( "SELECT id FROM file WHERE source = %1 AND url IN ( %2 )" )
.arg( source()->id() )
.arg( idstring ) );
idstring = QString();
while ( delquery.next() )
{
idstring.append( delquery.value( 0 ).toString() + ", " );
m_idList << delquery.value( 0 ).toUInt();
}
idstring.chop( 2 ); //remove the trailing ", "
}
delquery.prepare( QString( "DELETE FROM file WHERE source %1 AND id IN ( %2 )" )
.arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) ) .arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) )
.arg( source()->isLocal() ? "id" : "url" )
.arg( idstring ) ); .arg( idstring ) );
delquery.exec(); delquery.exec();
} }
emit done( m_files, source()->collection() ); if ( m_idList.count() )
source()->updateIndexWhenSynced();
emit done( m_idList, source()->collection() );
} }

View File

@@ -64,6 +64,7 @@ public:
virtual void exec( DatabaseImpl* ); virtual void exec( DatabaseImpl* );
virtual bool doesMutates() const { return true; } virtual bool doesMutates() const { return true; }
virtual bool localOnly() const { return false; } virtual bool localOnly() const { return false; }
virtual bool groupable() const { return true; }
virtual void postCommitHook(); virtual void postCommitHook();
QVariantList ids() const { return m_ids; } QVariantList ids() const { return m_ids; }
@@ -73,13 +74,13 @@ public:
void setDeleteAll( const bool deleteAll ) { m_deleteAll = deleteAll; } void setDeleteAll( const bool deleteAll ) { m_deleteAll = deleteAll; }
signals: signals:
void done( const QStringList&, const Tomahawk::collection_ptr& ); void done( const QList<unsigned int>&, const Tomahawk::collection_ptr& );
void notify( const QList<unsigned int>& ids ); void notify( const QList<unsigned int>& ids );
private: private:
QStringList m_files;
QDir m_dir; QDir m_dir;
QVariantList m_ids; QVariantList m_ids;
QList<unsigned int> m_idList;
bool m_deleteAll; bool m_deleteAll;
}; };

View File

@@ -40,8 +40,8 @@ DatabaseCommand_FileMtimes::execSelect( DatabaseImpl* dbi )
TomahawkSqlQuery query = dbi->newquery(); TomahawkSqlQuery query = dbi->newquery();
if( m_prefix.isEmpty() && m_prefixes.isEmpty() ) if( m_prefix.isEmpty() && m_prefixes.isEmpty() )
{ {
QString limit( m_checkonly ? QString( " LIMIT 1" ) : QString() ); QString limit( m_checkonly ? QString( "LIMIT 1" ) : QString() );
query.exec( QString( "SELECT url, id, mtime FROM file WHERE source IS NULL%1" ).arg( limit ) ); query.exec( QString( "SELECT url, id, mtime FROM file WHERE source IS NULL %1" ).arg( limit ) );
while( query.next() ) while( query.next() )
{ {
QMap< unsigned int, unsigned int > map; QMap< unsigned int, unsigned int > map;

View File

@@ -19,10 +19,11 @@
#include "databasecommand_genericselect.h" #include "databasecommand_genericselect.h"
#include "databaseimpl.h" #include "databaseimpl.h"
#include "sourcelist.h"
#include "artist.h"
#include "album.h"
#include "pipeline.h"
#include "utils/logger.h" #include "utils/logger.h"
#include <sourcelist.h>
#include <artist.h>
#include <album.h>
using namespace Tomahawk; using namespace Tomahawk;
@@ -63,7 +64,6 @@ DatabaseCommand_GenericSelect::exec( DatabaseImpl* dbi )
while( query.next() ) while( query.next() )
{ {
QStringList rawRow; QStringList rawRow;
int count = 0; int count = 0;
while ( query.value( count ).isValid() ) while ( query.value( count ).isValid() )
@@ -90,15 +90,16 @@ DatabaseCommand_GenericSelect::exec( DatabaseImpl* dbi )
track = query.value( 0 ).toString(); track = query.value( 0 ).toString();
artist = query.value( 1 ).toString(); artist = query.value( 1 ).toString();
qry = Tomahawk::Query::get( artist, track, QString() );
qry = Tomahawk::Query::get( artist, track, QString(), uuid(), true ); // Only auto-resolve non-local results }
} else if ( m_queryType == Artist ) else if ( m_queryType == Artist )
{ {
int artistId = query.value( 0 ).toInt(); int artistId = query.value( 0 ).toInt();
QString artistName = query.value( 1 ).toString(); QString artistName = query.value( 1 ).toString();
artist = Tomahawk::Artist::get( artistId, artistName ); artist = Tomahawk::Artist::get( artistId, artistName );
} else if ( m_queryType == Album ) }
else if ( m_queryType == Album )
{ {
int albumId = query.value( 0 ).toInt(); int albumId = query.value( 0 ).toInt();
QString albumName = query.value( 1 ).toString(); QString albumName = query.value( 1 ).toString();
@@ -122,12 +123,14 @@ DatabaseCommand_GenericSelect::exec( DatabaseImpl* dbi )
if ( !extraData.isEmpty() ) if ( !extraData.isEmpty() )
qry->setProperty( "data", extraData ); qry->setProperty( "data", extraData );
queries << qry; queries << qry;
} else if ( m_queryType == Artist ) }
else if ( m_queryType == Artist )
{ {
if ( !extraData.isEmpty() ) if ( !extraData.isEmpty() )
artist->setProperty( "data", extraData ); artist->setProperty( "data", extraData );
arts << artist; arts << artist;
} else if ( m_queryType == Album ) }
else if ( m_queryType == Album )
{ {
if ( !extraData.isEmpty() ) if ( !extraData.isEmpty() )
album->setProperty( "data", extraData ); album->setProperty( "data", extraData );

View File

@@ -94,23 +94,13 @@ DatabaseCommand_LoadDynamicPlaylistEntries::exec( DatabaseImpl* dbi )
} }
else else
{ {
// No controls, lets load the info we need directly from the playlist table // No controls or plguid is null, but that's okay. We'll get a setdynrevision command with a proper revision some point later
TomahawkSqlQuery info = dbi->newquery(); return;
info.prepare( QString( "SELECT dynamic_playlist.pltype, dynamic_playlist.plmode FROM playlist, dynamic_playlist WHERE playlist.guid = \"%1\" AND playlist.guid = dynamic_playlist.guid" ).arg( playlist_guid ) );
if( !info.exec() ) {
qWarning() << "Failed to load dynplaylist info..";
return;
} else if( !info.first() ) {
qWarning() << "Noo results for queryL:" << info.lastQuery();
return;
}
type = info.value( 0 ).toString();
mode = static_cast<GeneratorMode>( info.value( 1 ).toInt() );
} }
if( mode == OnDemand ) if( mode == OnDemand )
{ {
Q_ASSERT( m_entrymap.isEmpty() ); // ondemand should have no entry // Q_ASSERT( m_entrymap.isEmpty() ); // ondemand should have no entry
emit done( revisionGuid(), m_islatest, type, controls, true ); emit done( revisionGuid(), m_islatest, type, controls, true );
} }

View File

@@ -31,7 +31,6 @@ using namespace Tomahawk;
void void
DatabaseCommand_LoadPlaylistEntries::exec( DatabaseImpl* dbi ) DatabaseCommand_LoadPlaylistEntries::exec( DatabaseImpl* dbi )
{ {
// qDebug() << "Loading playlist entries for revision" << m_revguid;
generateEntries( dbi ); generateEntries( dbi );
emit done( m_revguid, m_guids, m_oldentries, m_islatest, m_entrymap, true ); emit done( m_revguid, m_guids, m_oldentries, m_islatest, m_entrymap, true );
@@ -42,40 +41,38 @@ void
DatabaseCommand_LoadPlaylistEntries::generateEntries( DatabaseImpl* dbi ) DatabaseCommand_LoadPlaylistEntries::generateEntries( DatabaseImpl* dbi )
{ {
TomahawkSqlQuery query_entries = dbi->newquery(); TomahawkSqlQuery query_entries = dbi->newquery();
query_entries.prepare("SELECT entries, playlist, author, timestamp, previous_revision " query_entries.prepare( "SELECT entries, playlist, author, timestamp, previous_revision "
"FROM playlist_revision " "FROM playlist_revision "
"WHERE guid = :guid"); "WHERE guid = :guid" );
query_entries.bindValue( ":guid", m_revguid ); query_entries.bindValue( ":guid", m_revguid );
query_entries.exec(); query_entries.exec();
// qDebug() << "trying to load entries:" << m_revguid; tLog( LOGVERBOSE ) << "trying to load playlist entries for guid:" << m_revguid;
QString prevrev; QString prevrev;
QJson::Parser parser; bool ok; QJson::Parser parser; bool ok;
if( query_entries.next() ) if ( query_entries.next() )
{ {
// entries should be a list of strings: // entries should be a list of strings:
QVariant v = parser.parse( query_entries.value(0).toByteArray(), &ok ); QVariant v = parser.parse( query_entries.value( 0 ).toByteArray(), &ok );
Q_ASSERT( ok && v.type() == QVariant::List ); //TODO Q_ASSERT( ok && v.type() == QVariant::List ); //TODO
m_guids = v.toStringList(); m_guids = v.toStringList();
QString inclause = QString( "('%1')" ).arg( m_guids.join( "', '" ) );
QString inclause = QString("('%1')").arg(m_guids.join("', '"));
TomahawkSqlQuery query = dbi->newquery(); TomahawkSqlQuery query = dbi->newquery();
QString sql = QString("SELECT guid, trackname, artistname, albumname, annotation, " QString sql = QString( "SELECT guid, trackname, artistname, albumname, annotation, "
"duration, addedon, addedby, result_hint " "duration, addedon, addedby, result_hint "
"FROM playlist_item " "FROM playlist_item "
"WHERE guid IN %1").arg( inclause ); "WHERE guid IN %1" ).arg( inclause );
//qDebug() << sql;
query.exec( sql ); query.exec( sql );
while( query.next() ) while ( query.next() )
{ {
plentry_ptr e( new PlaylistEntry ); plentry_ptr e( new PlaylistEntry );
e->setGuid( query.value( 0 ).toString() ); e->setGuid( query.value( 0 ).toString() );
e->setAnnotation( query.value( 4 ).toString() ); e->setAnnotation( query.value( 4 ).toString() );
e->setDuration( query.value( 5 ).toUInt() ); e->setDuration( query.value( 5 ).toUInt() );
e->setLastmodified( 0 ); // TODO e->lastmodified = query.value(6).toInt(); e->setLastmodified( 0 ); // TODO e->lastmodified = query.value( 6 ).toInt();
e->setResultHint( query.value( 8 ).toString() ); e->setResultHint( query.value( 8 ).toString() );
Tomahawk::query_ptr q = Tomahawk::Query::get( query.value( 2 ).toString(), query.value( 1 ).toString(), query.value( 3 ).toString() ); Tomahawk::query_ptr q = Tomahawk::Query::get( query.value( 2 ).toString(), query.value( 1 ).toString(), query.value( 3 ).toString() );
@@ -86,14 +83,13 @@ DatabaseCommand_LoadPlaylistEntries::generateEntries( DatabaseImpl* dbi )
} }
prevrev = query_entries.value( 4 ).toString(); prevrev = query_entries.value( 4 ).toString();
} }
else else
{ {
// qDebug() << "Playlist has no current revision data"; // qDebug() << "Playlist has no current revision data";
} }
if( prevrev.length() ) if ( prevrev.length() )
{ {
TomahawkSqlQuery query_entries_old = dbi->newquery(); TomahawkSqlQuery query_entries_old = dbi->newquery();
query_entries_old.prepare( "SELECT entries, " query_entries_old.prepare( "SELECT entries, "
@@ -105,7 +101,7 @@ DatabaseCommand_LoadPlaylistEntries::generateEntries( DatabaseImpl* dbi )
query_entries_old.addBindValue( prevrev ); query_entries_old.addBindValue( prevrev );
query_entries_old.exec(); query_entries_old.exec();
if( !query_entries_old.next() ) if ( !query_entries_old.next() )
{ {
return; return;
Q_ASSERT( false ); Q_ASSERT( false );

View File

@@ -36,8 +36,8 @@ using namespace Tomahawk;
void void
DatabaseCommand_LogPlayback::postCommitHook() DatabaseCommand_LogPlayback::postCommitHook()
{ {
connect( this, SIGNAL( trackPlaying( Tomahawk::query_ptr ) ), connect( this, SIGNAL( trackPlaying( Tomahawk::query_ptr, unsigned int ) ),
source().data(), SLOT( onPlaybackStarted( Tomahawk::query_ptr ) ), Qt::QueuedConnection ); source().data(), SLOT( onPlaybackStarted( Tomahawk::query_ptr, unsigned int ) ), Qt::QueuedConnection );
connect( this, SIGNAL( trackPlayed( Tomahawk::query_ptr ) ), connect( this, SIGNAL( trackPlayed( Tomahawk::query_ptr ) ),
source().data(), SLOT( onPlaybackFinished( Tomahawk::query_ptr ) ), Qt::QueuedConnection ); source().data(), SLOT( onPlaybackFinished( Tomahawk::query_ptr ) ), Qt::QueuedConnection );
@@ -60,7 +60,7 @@ DatabaseCommand_LogPlayback::postCommitHook()
// if the play time is more than 10 minutes in the past, ignore // if the play time is more than 10 minutes in the past, ignore
else if ( m_action == Started && QDateTime::fromTime_t( playtime() ).secsTo( QDateTime::currentDateTime() ) < STARTED_THRESHOLD ) else if ( m_action == Started && QDateTime::fromTime_t( playtime() ).secsTo( QDateTime::currentDateTime() ) < STARTED_THRESHOLD )
{ {
emit trackPlaying( q ); emit trackPlaying( q, m_trackDuration );
} }
if ( source()->isLocal() ) if ( source()->isLocal() )

View File

@@ -37,6 +37,7 @@ Q_PROPERTY( QString artist READ artist WRITE setArtist )
Q_PROPERTY( QString track READ track WRITE setTrack ) Q_PROPERTY( QString track READ track WRITE setTrack )
Q_PROPERTY( unsigned int playtime READ playtime WRITE setPlaytime ) Q_PROPERTY( unsigned int playtime READ playtime WRITE setPlaytime )
Q_PROPERTY( unsigned int secsPlayed READ secsPlayed WRITE setSecsPlayed ) Q_PROPERTY( unsigned int secsPlayed READ secsPlayed WRITE setSecsPlayed )
Q_PROPERTY( unsigned int trackDuration READ trackDuration WRITE setTrackDuration )
Q_PROPERTY( int action READ action WRITE setAction ) Q_PROPERTY( int action READ action WRITE setAction )
public: public:
@@ -47,13 +48,14 @@ public:
}; };
explicit DatabaseCommand_LogPlayback( QObject* parent = 0 ) explicit DatabaseCommand_LogPlayback( QObject* parent = 0 )
: DatabaseCommandLoggable( parent ) : DatabaseCommandLoggable( parent ), m_playtime( 0 ), m_secsPlayed( 0 ), m_trackDuration( 0 )
{} {}
explicit DatabaseCommand_LogPlayback( const Tomahawk::result_ptr& result, Action action, unsigned int secsPlayed = 0, QObject* parent = 0 ) explicit DatabaseCommand_LogPlayback( const Tomahawk::result_ptr& result, Action action, unsigned int secsPlayed = 0, QObject* parent = 0 )
: DatabaseCommandLoggable( parent ), m_result( result ), m_secsPlayed( secsPlayed ), m_action( action ) : DatabaseCommandLoggable( parent ), m_result( result ), m_secsPlayed( secsPlayed ), m_action( action )
{ {
m_playtime = QDateTime::currentDateTimeUtc().toTime_t(); m_playtime = QDateTime::currentDateTimeUtc().toTime_t();
m_trackDuration = result->duration();
setSource( SourceList::instance()->getLocal() ); setSource( SourceList::instance()->getLocal() );
setArtist( result->artist()->name() ); setArtist( result->artist()->name() );
@@ -68,6 +70,7 @@ public:
virtual bool doesMutates() const { return true; } virtual bool doesMutates() const { return true; }
virtual bool singletonCmd() const { return ( m_action == Started ); } virtual bool singletonCmd() const { return ( m_action == Started ); }
virtual bool localOnly() const; virtual bool localOnly() const;
virtual bool groupable() const { return true; }
QString artist() const { return m_artist; } QString artist() const { return m_artist; }
void setArtist( const QString& s ) { m_artist = s; } void setArtist( const QString& s ) { m_artist = s; }
@@ -81,11 +84,14 @@ public:
unsigned int secsPlayed() const { return m_secsPlayed; } unsigned int secsPlayed() const { return m_secsPlayed; }
void setSecsPlayed( unsigned int i ) { m_secsPlayed = i; } void setSecsPlayed( unsigned int i ) { m_secsPlayed = i; }
unsigned int trackDuration() const { return m_trackDuration; }
void setTrackDuration( unsigned int trackDuration ) { m_trackDuration = trackDuration; }
int action() const { return m_action; } int action() const { return m_action; }
void setAction( int a ) { m_action = (Action)a; } void setAction( int a ) { m_action = (Action)a; }
signals: signals:
void trackPlaying( const Tomahawk::query_ptr& query ); void trackPlaying( const Tomahawk::query_ptr& query, unsigned int duration );
void trackPlayed( const Tomahawk::query_ptr& query ); void trackPlayed( const Tomahawk::query_ptr& query );
private: private:
@@ -95,6 +101,7 @@ private:
QString m_track; QString m_track;
unsigned int m_playtime; unsigned int m_playtime;
unsigned int m_secsPlayed; unsigned int m_secsPlayed;
unsigned int m_trackDuration;
Action m_action; Action m_action;
}; };

View File

@@ -65,7 +65,7 @@ DatabaseCommand_PlaybackHistory::exec( DatabaseImpl* dbi )
if ( query_track.next() ) if ( query_track.next() )
{ {
Tomahawk::query_ptr q = Tomahawk::Query::get( query_track.value( 1 ).toString(), query_track.value( 0 ).toString(), QString(), uuid() ); Tomahawk::query_ptr q = Tomahawk::Query::get( query_track.value( 1 ).toString(), query_track.value( 0 ).toString(), QString() );
if ( query.value( 3 ).toUInt() == 0 ) if ( query.value( 3 ).toUInt() == 0 )
{ {
@@ -80,8 +80,6 @@ DatabaseCommand_PlaybackHistory::exec( DatabaseImpl* dbi )
} }
} }
qDebug() << Q_FUNC_INFO << ql.length();
if ( ql.count() ) if ( ql.count() )
emit tracks( ql ); emit tracks( ql );
} }

View File

@@ -157,7 +157,6 @@ DatabaseCommand_Resolve::resolve( DatabaseImpl* lib )
result->setRID( uuid() ); result->setRID( uuid() );
result->setAlbumPos( files_query.value( 14 ).toUInt() ); result->setAlbumPos( files_query.value( 14 ).toUInt() );
result->setTrackId( files_query.value( 9 ).toUInt() ); result->setTrackId( files_query.value( 9 ).toUInt() );
result->setYear( files_query.value( 17 ).toUInt() );
TomahawkSqlQuery attrQuery = lib->newquery(); TomahawkSqlQuery attrQuery = lib->newquery();
QVariantMap attr; QVariantMap attr;

View File

@@ -249,8 +249,8 @@ DatabaseCommand_SetDynamicPlaylistRevision::exec( DatabaseImpl* lib )
controlsQuery.exec(); controlsQuery.exec();
} }
} }
if ( m_applied ) if ( m_applied )
{ {
tLog() << "updating dynamic playlist, optimistic locking okay"; tLog() << "updating dynamic playlist, optimistic locking okay";

View File

@@ -60,6 +60,7 @@ public:
virtual void exec( DatabaseImpl* lib ); virtual void exec( DatabaseImpl* lib );
virtual void postCommitHook(); virtual void postCommitHook();
virtual bool doesMutates() const { return true; } virtual bool doesMutates() const { return true; }
virtual bool groupable() const { return true; }
void setControlsV( const QVariantList& vlist ) void setControlsV( const QVariantList& vlist )
{ {

View File

@@ -104,6 +104,7 @@ DatabaseCommand_SetPlaylistRevision::exec( DatabaseImpl* lib )
} }
else else
{ {
tDebug() << "Playlist:" << m_playlistguid << m_currentRevision << source()->friendlyName() << source()->id();
throw "No such playlist, WTF?"; throw "No such playlist, WTF?";
return; return;
} }
@@ -212,6 +213,6 @@ DatabaseCommand_SetPlaylistRevision::exec( DatabaseImpl* lib )
else if ( !m_oldrev.isEmpty() ) else if ( !m_oldrev.isEmpty() )
{ {
tDebug() << "Not updating current revision, optimistic locking fail"; tDebug() << "Not updating current revision, optimistic locking fail";
Q_ASSERT( false ); // Q_ASSERT( false );
} }
} }

View File

@@ -58,6 +58,7 @@ public:
virtual bool doesMutates() const { return true; } virtual bool doesMutates() const { return true; }
virtual bool localOnly() const { return m_localOnly; } virtual bool localOnly() const { return m_localOnly; }
virtual bool groupable() const { return true; }
void setAddedentriesV( const QVariantList& vlist ) void setAddedentriesV( const QVariantList& vlist )
{ {

View File

@@ -170,6 +170,7 @@ public:
void setTimestamp( const int ts ) { m_timestamp = ts; } void setTimestamp( const int ts ) { m_timestamp = ts; }
virtual bool doesMutates() const { return true; } virtual bool doesMutates() const { return true; }
virtual bool groupable() const { return true; }
private: private:
Tomahawk::result_ptr m_result; Tomahawk::result_ptr m_result;

View File

@@ -26,6 +26,7 @@
DatabaseCommand_UpdateSearchIndex::DatabaseCommand_UpdateSearchIndex() DatabaseCommand_UpdateSearchIndex::DatabaseCommand_UpdateSearchIndex()
: DatabaseCommand() : DatabaseCommand()
{ {
tLog() << Q_FUNC_INFO << "Updating index.";
} }

View File

@@ -1,6 +1,7 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> === /* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
* *
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org> * Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
* *
* Tomahawk is free software: you can redistribute it and/or modify * Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by

View File

@@ -72,16 +72,21 @@ DatabaseWorker::run()
} }
void
DatabaseWorker::enqueue( const QList< QSharedPointer<DatabaseCommand> >& cmds )
{
QMutexLocker lock( &m_mut );
m_outstanding += cmds.count();
m_commands << cmds;
if ( m_outstanding == cmds.count() )
QTimer::singleShot( 0, this, SLOT( doWork() ) );
}
void void
DatabaseWorker::enqueue( const QSharedPointer<DatabaseCommand>& cmd ) DatabaseWorker::enqueue( const QSharedPointer<DatabaseCommand>& cmd )
{ {
if ( QThread::currentThread() != thread() )
{
// qDebug() << Q_FUNC_INFO << "Reinvoking in correct thread.";
QMetaObject::invokeMethod( this, "enqueue", Qt::QueuedConnection, Q_ARG( QSharedPointer<DatabaseCommand>, cmd ) );
return;
}
QMutexLocker lock( &m_mut ); QMutexLocker lock( &m_mut );
m_outstanding++; m_outstanding++;
m_commands << cmd; m_commands << cmd;
@@ -107,6 +112,7 @@ DatabaseWorker::doWork()
timer.start(); timer.start();
#endif #endif
QList< QSharedPointer<DatabaseCommand> > cmdGroup;
QSharedPointer<DatabaseCommand> cmd; QSharedPointer<DatabaseCommand> cmd;
{ {
QMutexLocker lock( &m_mut ); QMutexLocker lock( &m_mut );
@@ -119,47 +125,66 @@ DatabaseWorker::doWork()
Q_ASSERT( transok ); Q_ASSERT( transok );
Q_UNUSED( transok ); Q_UNUSED( transok );
} }
unsigned int completed = 0;
try try
{ {
bool finished = false;
{ {
// tDebug() << "Executing cmd:" << cmd->guid(); while ( !finished )
cmd->_exec( m_dbimpl ); // runs actual SQL stuff
if ( cmd->loggable() )
{ {
// We only save our own ops to the oplog, since incoming ops from peers completed++;
// are applied immediately. cmd->_exec( m_dbimpl ); // runs actual SQL stuff
//
// Crazy idea: if peers had keypairs and could sign ops/msgs, in theory it if ( cmd->loggable() )
// would be safe to sync ops for friend A from friend B's cache, if he saved them,
// which would mean you could get updates even if a peer was offline.
if ( cmd->source()->isLocal() && !cmd->localOnly() )
{ {
// save to op-log // We only save our own ops to the oplog, since incoming ops from peers
DatabaseCommandLoggable* command = (DatabaseCommandLoggable*)cmd.data(); // are applied immediately.
logOp( command );
}
else
{
// Make a note of the last guid we applied for this source
// so we can always request just the newer ops in future.
// //
if ( !cmd->singletonCmd() ) // Crazy idea: if peers had keypairs and could sign ops/msgs, in theory it
// would be safe to sync ops for friend A from friend B's cache, if he saved them,
// which would mean you could get updates even if a peer was offline.
if ( cmd->source()->isLocal() && !cmd->localOnly() )
{ {
// qDebug() << "Setting lastop for source" << cmd->source()->id() << "to" << cmd->guid(); // save to op-log
DatabaseCommandLoggable* command = (DatabaseCommandLoggable*)cmd.data();
TomahawkSqlQuery query = m_dbimpl->newquery(); logOp( command );
query.prepare( "UPDATE source SET lastop = ? WHERE id = ?" ); }
query.addBindValue( cmd->guid() ); else
query.addBindValue( cmd->source()->id() ); {
// Make a note of the last guid we applied for this source
if ( !query.exec() ) // so we can always request just the newer ops in future.
//
if ( !cmd->singletonCmd() )
{ {
qDebug() << "Failed to set lastop"; TomahawkSqlQuery query = m_dbimpl->newquery();
throw "Failed to set lastop"; query.prepare( "UPDATE source SET lastop = ? WHERE id = ?" );
query.addBindValue( cmd->guid() );
query.addBindValue( cmd->source()->id() );
if ( !query.exec() )
{
throw "Failed to set lastop";
}
} }
} }
} }
cmdGroup << cmd;
if ( cmd->groupable() && !m_commands.isEmpty() )
{
QMutexLocker lock( &m_mut );
if ( m_commands.first()->groupable() )
{
cmd = m_commands.takeFirst();
}
else
{
finished = true;
}
}
else
finished = true;
} }
if ( cmd->doesMutates() ) if ( cmd->doesMutates() )
@@ -167,8 +192,7 @@ DatabaseWorker::doWork()
qDebug() << "Committing" << cmd->commandname() << cmd->guid(); qDebug() << "Committing" << cmd->commandname() << cmd->guid();
if ( !m_dbimpl->database().commit() ) if ( !m_dbimpl->database().commit() )
{ {
tDebug() << "FAILED TO COMMIT TRANSACTION*";
qDebug() << "*FAILED TO COMMIT TRANSACTION*";
throw "commit failed"; throw "commit failed";
} }
} }
@@ -178,7 +202,8 @@ DatabaseWorker::doWork()
tDebug() << "DBCmd Duration:" << duration << "ms, now running postcommit for" << cmd->commandname(); tDebug() << "DBCmd Duration:" << duration << "ms, now running postcommit for" << cmd->commandname();
#endif #endif
cmd->postCommit(); foreach ( QSharedPointer<DatabaseCommand> c, cmdGroup )
c->postCommit();
#ifdef DEBUG_TIMING #ifdef DEBUG_TIMING
tDebug() << "Post commit finished in" << timer.elapsed() - duration << "ms for" << cmd->commandname(); tDebug() << "Post commit finished in" << timer.elapsed() - duration << "ms for" << cmd->commandname();
@@ -195,7 +220,7 @@ DatabaseWorker::doWork()
<< m_dbimpl->database().lastError().driverText() << m_dbimpl->database().lastError().driverText()
<< endl; << endl;
if( cmd->doesMutates() ) if ( cmd->doesMutates() )
m_dbimpl->database().rollback(); m_dbimpl->database().rollback();
Q_ASSERT( false ); Q_ASSERT( false );
@@ -203,17 +228,19 @@ DatabaseWorker::doWork()
catch(...) catch(...)
{ {
qDebug() << "Uncaught exception processing dbcmd"; qDebug() << "Uncaught exception processing dbcmd";
if( cmd->doesMutates() ) if ( cmd->doesMutates() )
m_dbimpl->database().rollback(); m_dbimpl->database().rollback();
Q_ASSERT( false ); Q_ASSERT( false );
throw; throw;
} }
cmd->emitFinished(); foreach ( QSharedPointer<DatabaseCommand> c, cmdGroup )
c->emitFinished();
QMutexLocker lock( &m_mut ); QMutexLocker lock( &m_mut );
if ( --m_outstanding > 0 ) m_outstanding -= completed;
if ( m_outstanding > 0 )
QTimer::singleShot( 0, this, SLOT( doWork() ) ); QTimer::singleShot( 0, this, SLOT( doWork() ) );
} }

View File

@@ -47,6 +47,7 @@ public:
public slots: public slots:
void enqueue( const QSharedPointer<DatabaseCommand>& ); void enqueue( const QSharedPointer<DatabaseCommand>& );
void enqueue( const QList< QSharedPointer<DatabaseCommand> >& );
protected: protected:
void run(); void run();

View File

@@ -266,6 +266,7 @@ CREATE TABLE IF NOT EXISTS playback_log (
playtime INTEGER NOT NULL, -- when playback finished (timestamp) playtime INTEGER NOT NULL, -- when playback finished (timestamp)
secs_played INTEGER NOT NULL secs_played INTEGER NOT NULL
); );
CREATE INDEX playback_log_source ON playback_log(source); CREATE INDEX playback_log_source ON playback_log(source);
CREATE INDEX playback_log_track ON playback_log(track); CREATE INDEX playback_log_track ON playback_log(track);

View File

@@ -1,5 +1,5 @@
/* /*
This file was automatically generated from schema.sql on Thu Sep 29 17:28:17 EDT 2011. This file was automatically generated from schema.sql on Wed Nov 16 22:47:16 EST 2011.
*/ */
static const char * tomahawk_schema_sql = static const char * tomahawk_schema_sql =

View File

@@ -34,10 +34,12 @@
#include "utils/xspfloader.h" #include "utils/xspfloader.h"
#include "jobview/JobStatusView.h" #include "jobview/JobStatusView.h"
#include "jobview/JobStatusModel.h" #include "jobview/JobStatusModel.h"
using namespace Tomahawk; using namespace Tomahawk;
bool DropJob::s_canParseSpotifyPlaylists = false; bool DropJob::s_canParseSpotifyPlaylists = false;
DropJob::DropJob( QObject *parent ) DropJob::DropJob( QObject *parent )
: QObject( parent ) : QObject( parent )
, m_queryCount( 0 ) , m_queryCount( 0 )
@@ -50,11 +52,13 @@ DropJob::DropJob( QObject *parent )
{ {
} }
DropJob::~DropJob() DropJob::~DropJob()
{ {
qDebug() << "destryong DropJob"; qDebug() << "destryong DropJob";
} }
/// QMIMEDATA HANDLING /// QMIMEDATA HANDLING
QStringList QStringList
@@ -68,15 +72,18 @@ DropJob::mimeTypes()
<< "application/tomahawk.metadata.artist" << "application/tomahawk.metadata.artist"
<< "application/tomahawk.metadata.album" << "application/tomahawk.metadata.album"
<< "application/tomahawk.mixed" << "application/tomahawk.mixed"
<< "text/plain"; << "text/plain"
<< "text/uri-list";
return mimeTypes; return mimeTypes;
} }
bool bool
DropJob::acceptsMimeData( const QMimeData* data, DropJob::DropTypes acceptedType, DropJob::DropAction acceptedAction ) DropJob::acceptsMimeData( const QMimeData* data, DropJob::DropTypes acceptedType, DropJob::DropAction acceptedAction )
{ {
Q_UNUSED( acceptedAction ); Q_UNUSED( acceptedAction );
if ( data->hasFormat( "application/tomahawk.query.list" ) if ( data->hasFormat( "application/tomahawk.query.list" )
|| data->hasFormat( "application/tomahawk.plentry.list" ) || data->hasFormat( "application/tomahawk.plentry.list" )
|| data->hasFormat( "application/tomahawk.result.list" ) || data->hasFormat( "application/tomahawk.result.list" )
@@ -90,7 +97,8 @@ DropJob::acceptsMimeData( const QMimeData* data, DropJob::DropTypes acceptedType
// check plain text url types // check plain text url types
if ( !data->hasFormat( "text/plain" ) ) if ( !data->hasFormat( "text/plain" ) )
return false; if ( !data->hasFormat( "text/uri-list" ) )
return false;
const QString url = data->data( "text/plain" ); const QString url = data->data( "text/plain" );
@@ -99,6 +107,9 @@ DropJob::acceptsMimeData( const QMimeData* data, DropJob::DropTypes acceptedType
if( url.contains( "xspf" ) ) if( url.contains( "xspf" ) )
return true; return true;
if( data->data( "text/uri-list" ).contains( "xspf" ) )
return true;
// Not the most elegant // Not the most elegant
if ( url.contains( "spotify" ) && url.contains( "playlist" ) && s_canParseSpotifyPlaylists ) if ( url.contains( "spotify" ) && url.contains( "playlist" ) && s_canParseSpotifyPlaylists )
return true; return true;
@@ -137,21 +148,22 @@ DropJob::acceptsMimeData( const QMimeData* data, DropJob::DropTypes acceptedType
return true; return true;
} }
// We whitelist t.co and bit.ly (and j.mp) since they do some link checking. Often playable (e.g. spotify..) links hide behind them, // We whitelist certain url-shorteners since they do some link checking. Often playable (e.g. spotify) links hide behind them,
// so we do an extra level of lookup // so we do an extra level of lookup
if ( url.contains( "bit.ly" ) || url.contains( "j.mp" ) || url.contains( "t.co" ) || url.contains( "rd.io" ) ) if ( ShortenedLinkParser::handlesUrl( url ) )
return true; return true;
return false; return false;
} }
bool bool
DropJob::isDropType( DropJob::DropType desired, const QMimeData* data ) DropJob::isDropType( DropJob::DropType desired, const QMimeData* data )
{ {
const QString url = data->data( "text/plain" ); const QString url = data->data( "text/plain" );
if ( desired == Playlist ) if ( desired == Playlist )
{ {
if( url.contains( "xspf" ) ) if( url.contains( "xspf" ) || data->data( "text/uri-list").contains( "xspf" ) )
return true; return true;
// Not the most elegant // Not the most elegant
@@ -161,11 +173,7 @@ DropJob::isDropType( DropJob::DropType desired, const QMimeData* data )
if ( url.contains( "rdio.com" ) && url.contains( "people" ) && url.contains( "playlist" ) ) if ( url.contains( "rdio.com" ) && url.contains( "people" ) && url.contains( "playlist" ) )
return true; return true;
// we don't know about these.. gotta say yes for now if ( ShortenedLinkParser::handlesUrl( url ) )
if ( url.contains( "bit.ly" ) ||
url.contains( "j.mp" ) ||
url.contains( "t.co" ) ||
url.contains( "rd.io" ) )
return true; return true;
} }
@@ -179,6 +187,7 @@ DropJob::setGetWholeArtists( bool getWholeArtists )
m_getWholeArtists = getWholeArtists; m_getWholeArtists = getWholeArtists;
} }
void void
DropJob::setGetWholeAlbums( bool getWholeAlbums ) DropJob::setGetWholeAlbums( bool getWholeAlbums )
{ {
@@ -208,10 +217,12 @@ DropJob::tracksFromMimeData( const QMimeData* data, bool allowDuplicates, bool o
} }
} }
void void
DropJob::parseMimeData( const QMimeData *data ) DropJob::parseMimeData( const QMimeData *data )
{ {
QList< query_ptr > results; QList< query_ptr > results;
if ( data->hasFormat( "application/tomahawk.query.list" ) ) if ( data->hasFormat( "application/tomahawk.query.list" ) )
results = tracksFromQueryList( data ); results = tracksFromQueryList( data );
else if ( data->hasFormat( "application/tomahawk.result.list" ) ) else if ( data->hasFormat( "application/tomahawk.result.list" ) )
@@ -222,15 +233,22 @@ DropJob::parseMimeData( const QMimeData *data )
results = tracksFromArtistMetaData( data ); results = tracksFromArtistMetaData( data );
else if ( data->hasFormat( "application/tomahawk.mixed" ) ) else if ( data->hasFormat( "application/tomahawk.mixed" ) )
tracksFromMixedData( data ); tracksFromMixedData( data );
else if ( data->hasFormat( "text/plain" ) ) else if ( data->hasFormat( "text/plain" ) && !data->data( "text/plain" ).isEmpty() )
{ {
const QString plainData = QString::fromUtf8( data->data( "text/plain" ) ); const QString plainData = QString::fromUtf8( data->data( "text/plain" ) );
handleAllUrls( plainData ); handleAllUrls( plainData );
}
else if ( data->hasFormat( "text/uri-list" ) )
{
const QString plainData = QString::fromUtf8( data->data( "text/uri-list" ).trimmed() );
handleAllUrls( plainData );
} }
m_resultList.append( results ); m_resultList.append( results );
} }
QList< query_ptr > QList< query_ptr >
DropJob::tracksFromQueryList( const QMimeData* data ) DropJob::tracksFromQueryList( const QMimeData* data )
{ {
@@ -270,6 +288,7 @@ DropJob::tracksFromQueryList( const QMimeData* data )
return queries; return queries;
} }
QList< query_ptr > QList< query_ptr >
DropJob::tracksFromResultList( const QMimeData* data ) DropJob::tracksFromResultList( const QMimeData* data )
{ {
@@ -311,6 +330,7 @@ DropJob::tracksFromResultList( const QMimeData* data )
return queries; return queries;
} }
QList< query_ptr > QList< query_ptr >
DropJob::tracksFromAlbumMetaData( const QMimeData *data ) DropJob::tracksFromAlbumMetaData( const QMimeData *data )
{ {
@@ -332,9 +352,11 @@ DropJob::tracksFromAlbumMetaData( const QMimeData *data )
else else
queries << getAlbum( artist, album ); queries << getAlbum( artist, album );
} }
return queries; return queries;
} }
QList< query_ptr > QList< query_ptr >
DropJob::tracksFromArtistMetaData( const QMimeData *data ) DropJob::tracksFromArtistMetaData( const QMimeData *data )
{ {
@@ -359,6 +381,7 @@ DropJob::tracksFromArtistMetaData( const QMimeData *data )
return queries; return queries;
} }
QList< query_ptr > QList< query_ptr >
DropJob::tracksFromMixedData( const QMimeData *data ) DropJob::tracksFromMixedData( const QMimeData *data )
{ {
@@ -404,40 +427,59 @@ DropJob::tracksFromMixedData( const QMimeData *data )
singleMimeData.setData( mimeType, singleData ); singleMimeData.setData( mimeType, singleData );
parseMimeData( &singleMimeData ); parseMimeData( &singleMimeData );
} }
return queries; return queries;
} }
void void
DropJob::handleXspfs( const QString& fileUrls ) DropJob::handleXspfs( const QString& fileUrls )
{ {
tDebug() << Q_FUNC_INFO << "Got xspf playlist!!" << fileUrls; tDebug() << Q_FUNC_INFO << "Got XSPF playlist!" << fileUrls;
bool error = false;
QStringList urls = fileUrls.split( QRegExp( "\\s+" ), QString::SkipEmptyParts ); QStringList urls = fileUrls.split( QRegExp( "\n" ), QString::SkipEmptyParts );
if ( dropAction() == Default ) if ( dropAction() == Default )
setDropAction( Create ); setDropAction( Create );
foreach ( const QString& url, urls ) foreach ( const QString& url, urls )
{ {
XSPFLoader* l = 0;
QFile xspfFile( QUrl::fromUserInput( url ).toLocalFile() ); QFile xspfFile( QUrl::fromUserInput( url ).toLocalFile() );
if ( xspfFile.exists() ) if ( xspfFile.exists() )
{ {
XSPFLoader* l = new XSPFLoader( true, this ); l = new XSPFLoader( dropAction() == Create, this );
tDebug( LOGINFO ) << "Loading local xspf " << xspfFile.fileName(); tDebug( LOGINFO ) << "Loading local XSPF" << xspfFile.fileName();
l->load( xspfFile ); l->load( xspfFile );
} }
else if ( QUrl( url ).isValid() )
{
l = new XSPFLoader( dropAction() == Create, this );
tDebug( LOGINFO ) << "Loading remote XSPF" << url;
l->load( QUrl( url ) );
}
else else
tLog( LOGINFO ) << "Error Loading local xspf " << xspfFile.fileName(); {
} error = true;
tLog() << "Failed to load or parse dropped XSPF";
}
if ( dropAction() == Append && !error && l )
{
qDebug() << Q_FUNC_INFO << "Trying to append XSPF";
connect( l, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SLOT( onTracksAdded( QList< Tomahawk::query_ptr > ) ) );
m_queryCount++;
}
}
} }
void void
DropJob::handleSpotifyUrls( const QString& urlsRaw ) DropJob::handleSpotifyUrls( const QString& urlsRaw )
{ {
QStringList urls = urlsRaw.split( QRegExp( "\\s+" ), QString::SkipEmptyParts ); QStringList urls = urlsRaw.split( QRegExp( "\\s+" ), QString::SkipEmptyParts );
qDebug() << "Got spotify browse uris!!" << urls; qDebug() << "Got spotify browse uris!" << urls;
/// Lets allow parsing all spotify uris here, if parse server is not available /// Lets allow parsing all spotify uris here, if parse server is not available
/// fallback to spotify metadata for tracks /hugo /// fallback to spotify metadata for tracks /hugo
@@ -458,11 +500,12 @@ DropJob::handleSpotifyUrls( const QString& urlsRaw )
m_queryCount++; m_queryCount++;
} }
void void
DropJob::handleRdioUrls( const QString& urlsRaw ) DropJob::handleRdioUrls( const QString& urlsRaw )
{ {
QStringList urls = urlsRaw.split( QRegExp( "\\s+" ), QString::SkipEmptyParts ); QStringList urls = urlsRaw.split( QRegExp( "\\s+" ), QString::SkipEmptyParts );
qDebug() << "Got Rdio urls!!" << urls; qDebug() << "Got Rdio urls!" << urls;
if ( dropAction() == Default ) if ( dropAction() == Default )
setDropAction( Create ); setDropAction( Create );
@@ -470,10 +513,10 @@ DropJob::handleRdioUrls( const QString& urlsRaw )
RdioParser* rdio = new RdioParser( this ); RdioParser* rdio = new RdioParser( this );
connect( rdio, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SLOT( onTracksAdded( QList< Tomahawk::query_ptr > ) ) ); connect( rdio, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SLOT( onTracksAdded( QList< Tomahawk::query_ptr > ) ) );
m_queryCount++;
rdio->setCreatePlaylist( dropAction() == Create ); rdio->setCreatePlaylist( dropAction() == Create );
rdio->parse( urls ); rdio->parse( urls );
m_queryCount++;
} }
@@ -524,10 +567,8 @@ DropJob::handleTrackUrls( const QString& urls )
m_queryCount++; m_queryCount++;
rdio->parse( tracks ); rdio->parse( tracks );
} else if ( urls.contains( "bit.ly" ) || }
urls.contains( "j.mp" ) || else if ( ShortenedLinkParser::handlesUrl( urls ) )
urls.contains( "t.co" ) ||
urls.contains( "rd.io" ) )
{ {
QStringList tracks = urls.split( QRegExp( "\\s+" ), QString::SkipEmptyParts ); QStringList tracks = urls.split( QRegExp( "\\s+" ), QString::SkipEmptyParts );
@@ -538,6 +579,7 @@ DropJob::handleTrackUrls( const QString& urls )
} }
} }
void void
DropJob::expandedUrls( QStringList urls ) DropJob::expandedUrls( QStringList urls )
{ {
@@ -545,6 +587,7 @@ DropJob::expandedUrls( QStringList urls )
handleAllUrls( urls.join( "\n" ) ); handleAllUrls( urls.join( "\n" ) );
} }
void void
DropJob::onTracksAdded( const QList<Tomahawk::query_ptr>& tracksList ) DropJob::onTracksAdded( const QList<Tomahawk::query_ptr>& tracksList )
{ {
@@ -569,6 +612,7 @@ DropJob::onTracksAdded( const QList<Tomahawk::query_ptr>& tracksList )
} }
} }
void void
DropJob::removeDuplicates() DropJob::removeDuplicates()
{ {
@@ -584,9 +628,11 @@ DropJob::removeDuplicates()
if ( !contains ) if ( !contains )
list.append( item ); list.append( item );
} }
m_resultList = list; m_resultList = list;
} }
void void
DropJob::removeRemoteSources() DropJob::removeRemoteSources()
{ {
@@ -605,6 +651,7 @@ DropJob::removeRemoteSources()
m_resultList = list; m_resultList = list;
} }
void void
DropJob::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output ) DropJob::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output )
{ {
@@ -634,6 +681,7 @@ DropJob::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVar
} }
} }
QList< query_ptr > QList< query_ptr >
DropJob::getArtist( const QString &artist ) DropJob::getArtist( const QString &artist )
{ {
@@ -649,6 +697,7 @@ DropJob::getArtist( const QString &artist )
return artistPtr->tracks(); return artistPtr->tracks();
} }
QList< query_ptr > QList< query_ptr >
DropJob::getAlbum(const QString &artist, const QString &album) DropJob::getAlbum(const QString &artist, const QString &album)
{ {
@@ -672,6 +721,7 @@ DropJob::getAlbum(const QString &artist, const QString &album)
return albumPtr->tracks(); return albumPtr->tracks();
} }
void void
DropJob::getTopTen( const QString &artist ) DropJob::getTopTen( const QString &artist )
{ {

View File

@@ -62,7 +62,8 @@ public:
enum DropAction { enum DropAction {
Default = 0, Default = 0,
Append, Append,
Create Create,
Move
}; };
/** /**
@@ -108,6 +109,7 @@ public:
static bool canParseSpotifyPlaylists() { return s_canParseSpotifyPlaylists; } static bool canParseSpotifyPlaylists() { return s_canParseSpotifyPlaylists; }
static void setCanParseSpotifyPlaylists( bool parseable ) { s_canParseSpotifyPlaylists = parseable; } static void setCanParseSpotifyPlaylists( bool parseable ) { s_canParseSpotifyPlaylists = parseable; }
signals: signals:
/// QMimeData parsing results /// QMimeData parsing results
void tracks( const QList< Tomahawk::query_ptr >& tracks ); void tracks( const QList< Tomahawk::query_ptr >& tracks );

View File

@@ -297,12 +297,12 @@ GlobalActionManager::handlePlaylistCommand( const QUrl& url )
tDebug() << "No xspf to load..."; tDebug() << "No xspf to load...";
return false; return false;
} }
QUrl xspf = QUrl( url.queryItemValue( "xspf" ) ); QUrl xspf = QUrl::fromUserInput( url.queryItemValue( "xspf" ) );
QString title = url.hasQueryItem( "title" ) ? url.queryItemValue( "title" ) : QString(); QString title = url.hasQueryItem( "title" ) ? url.queryItemValue( "title" ) : QString();
XSPFLoader* l= new XSPFLoader( true, this ); XSPFLoader* l= new XSPFLoader( true, this );
l->setOverrideTitle( title ); l->setOverrideTitle( title );
l->load( xspf ); l->load( xspf );
connect( l, SIGNAL( ok( Tomahawk::playlist_ptr ) ), ViewManager::instance(), SLOT( show( Tomahawk::playlist_ptr ) ) ); connect( l, SIGNAL( ok( Tomahawk::playlist_ptr ) ), this, SLOT( playlistCreatedToShow( Tomahawk::playlist_ptr) ) );
} else if( parts [ 0 ] == "new" ) { } else if( parts [ 0 ] == "new" ) {
if( !url.hasQueryItem( "title" ) ) { if( !url.hasQueryItem( "title" ) ) {
@@ -323,6 +323,22 @@ GlobalActionManager::handlePlaylistCommand( const QUrl& url )
return false; return false;
} }
void
GlobalActionManager::playlistCreatedToShow( const playlist_ptr& pl )
{
connect( pl.data(), SIGNAL( revisionLoaded( Tomahawk::PlaylistRevision ) ), this, SLOT( playlistReadyToShow() ) );
pl->setProperty( "sharedptr", QVariant::fromValue<Tomahawk::playlist_ptr>( pl ) );
}
void GlobalActionManager::playlistReadyToShow()
{
playlist_ptr pl = sender()->property( "sharedptr" ).value<Tomahawk::playlist_ptr>();
if ( !pl.isNull() )
ViewManager::instance()->show( pl );
disconnect( sender(), SIGNAL( revisionLoaded( Tomahawk::PlaylistRevision ) ), this, SLOT( playlistReadyToShow() ) );
}
bool bool
GlobalActionManager::handleCollectionCommand( const QUrl& url ) GlobalActionManager::handleCollectionCommand( const QUrl& url )
@@ -408,6 +424,7 @@ GlobalActionManager::doQueueAdd( const QStringList& parts, const QList< QPair< Q
QString title, artist, album, urlStr; QString title, artist, album, urlStr;
foreach( pair, queryItems ) { foreach( pair, queryItems ) {
pair.second = pair.second.replace( "+", " " ); // QUrl::queryItems doesn't decode + to a space :(
if( pair.first == "title" ) if( pair.first == "title" )
title = pair.second; title = pair.second;
else if( pair.first == "artist" ) else if( pair.first == "artist" )
@@ -431,7 +448,7 @@ GlobalActionManager::doQueueAdd( const QStringList& parts, const QList< QPair< Q
foreach( pair, queryItems ) { foreach( pair, queryItems ) {
if( pair.first != "url" ) if( pair.first != "url" )
continue; continue;
QUrl track = QUrl::fromUserInput( pair.second ); QUrl track = QUrl::fromUserInput( pair.second );
//FIXME: isLocalFile is Qt 4.8 //FIXME: isLocalFile is Qt 4.8
if( track.toString().startsWith( "file://" ) ) { // it's local, so we see if it's in the DB and load it if so if( track.toString().startsWith( "file://" ) ) { // it's local, so we see if it's in the DB and load it if so
// TODO // TODO

View File

@@ -81,6 +81,8 @@ private slots:
void playOrQueueNow( const Tomahawk::query_ptr& ); void playOrQueueNow( const Tomahawk::query_ptr& );
void playNow( const Tomahawk::query_ptr& ); void playNow( const Tomahawk::query_ptr& );
void playlistCreatedToShow( const Tomahawk::playlist_ptr& pl );
void playlistReadyToShow();
private: private:
explicit GlobalActionManager( QObject* parent = 0 ); explicit GlobalActionManager( QObject* parent = 0 );
void doBookmark( const Tomahawk::playlist_ptr& pl, const Tomahawk::query_ptr& q ); void doBookmark( const Tomahawk::playlist_ptr& pl, const Tomahawk::query_ptr& q );

View File

@@ -39,9 +39,6 @@
<height>64</height> <height>64</height>
</size> </size>
</property> </property>
<property name="text">
<string>TextLabel</string>
</property>
</widget> </widget>
</item> </item>
<item> <item>
@@ -76,9 +73,6 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="text">
<string>TextLabel</string>
</property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property> </property>
@@ -92,9 +86,6 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="text">
<string>TextLabel</string>
</property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property> </property>
@@ -143,9 +134,6 @@
<height>62</height> <height>62</height>
</size> </size>
</property> </property>
<property name="text">
<string>TextLabel</string>
</property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property> </property>

View File

@@ -19,12 +19,10 @@
#include "chartsplugin.h" #include "chartsplugin.h"
#include <QDir> #include <QtCore/QDir>
#include <QSettings> #include <QtCore/QSettings>
#include <QCryptographicHash> #include <QtNetwork/QNetworkConfiguration>
#include <QNetworkConfiguration> #include <QtNetwork/QNetworkReply>
#include <QNetworkReply>
#include <QDomElement>
#include "album.h" #include "album.h"
#include "chartsplugin_data_p.h" #include "chartsplugin_data_p.h"
@@ -34,7 +32,7 @@
#include "utils/tomahawkutils.h" #include "utils/tomahawkutils.h"
#include "utils/logger.h" #include "utils/logger.h"
#define CHART_URL "http://charts.tomahawk-player.org:10080/" #define CHART_URL "http://charts.tomahawk-player.org/"
//#define CHART_URL "http://localhost:8080/" //#define CHART_URL "http://localhost:8080/"
#include <qjson/parser.h> #include <qjson/parser.h>
#include <qjson/serializer.h> #include <qjson/serializer.h>
@@ -50,27 +48,12 @@ ChartsPlugin::ChartsPlugin()
m_chartResources << "billboard" << "itunes" << "rdio" << "wearehunted" << "ex.fm"; m_chartResources << "billboard" << "itunes" << "rdio" << "wearehunted" << "ex.fm";
m_supportedGetTypes << InfoChart << InfoChartCapabilities; m_supportedGetTypes << InfoChart << InfoChartCapabilities;
/// Then get each chart from resource
/// We want to prepopulate the breadcrumb to fetch them before they are asked for
if ( !m_chartResources.isEmpty() && m_allChartsMap.isEmpty() )
{
tDebug() << "ChartsPlugin: InfoChart fetching possible resources";
foreach ( QVariant resource, m_chartResources )
{
QUrl url = QUrl( QString( CHART_URL "source/%1" ).arg(resource.toString() ) );
QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
tDebug() << "fetching:" << url;
connect( reply, SIGNAL( finished() ), SLOT( chartTypes() ) );
m_chartsFetchJobs++;
}
}
} }
ChartsPlugin::~ChartsPlugin() ChartsPlugin::~ChartsPlugin()
{ {
qDebug() << Q_FUNC_INFO; tDebug( LOGVERBOSE ) << Q_FUNC_INFO;
} }
@@ -85,27 +68,27 @@ ChartsPlugin::dataError( Tomahawk::InfoSystem::InfoRequestData requestData )
void void
ChartsPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData ) ChartsPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
{ {
qDebug() << Q_FUNC_INFO << requestData.caller; //qDebug() << Q_FUNC_INFO << requestData.caller;
qDebug() << Q_FUNC_INFO << requestData.customData; //qDebug() << Q_FUNC_INFO << requestData.customData;
InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >(); InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
bool foundSource = false; bool foundSource = false;
switch ( requestData.type ) switch ( requestData.type )
{ {
case InfoChart: case InfoChart:
/// We need something to check if the request is actually ment to go to this plugin /// We need something to check if the request is actually ment to go to this plugin
if ( !hash.contains( "chart_source" ) ) if ( !hash.contains( "chart_source" ) )
{ {
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Hash did not contain required param!";
dataError( requestData ); dataError( requestData );
break; break;
} }
else else
{ {
foreach( QVariant resource, m_chartResources ) foreach( QString resource, m_chartResources )
{ {
if( resource.toString() == hash["chart_source"] ) if( resource == hash["chart_source"] )
{ {
foundSource = true; foundSource = true;
} }
@@ -130,15 +113,6 @@ ChartsPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
} }
void
ChartsPlugin::pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input )
{
Q_UNUSED( caller )
Q_UNUSED( type)
Q_UNUSED( input )
}
void void
ChartsPlugin::fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData ) ChartsPlugin::fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData )
{ {
@@ -155,6 +129,7 @@ ChartsPlugin::fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData )
/// Each request needs to contain both a id and source /// Each request needs to contain both a id and source
if ( !hash.contains( "chart_id" ) && !hash.contains( "chart_source" ) ) if ( !hash.contains( "chart_id" ) && !hash.contains( "chart_source" ) )
{ {
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Hash did not contain required params!";
dataError( requestData ); dataError( requestData );
return; return;
@@ -163,7 +138,7 @@ ChartsPlugin::fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData )
criteria["chart_id"] = hash["chart_id"]; criteria["chart_id"] = hash["chart_id"];
criteria["chart_source"] = hash["chart_source"]; criteria["chart_source"] = hash["chart_source"];
emit getCachedInfo( criteria, 0, requestData ); emit getCachedInfo( criteria, 86400000, requestData );
} }
void void
@@ -171,13 +146,14 @@ ChartsPlugin::fetchChartCapabilities( Tomahawk::InfoSystem::InfoRequestData requ
{ {
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() ) if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
{ {
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Could not convert requestData to InfoStringHash!";
dataError( requestData ); dataError( requestData );
return; return;
} }
Tomahawk::InfoSystem::InfoStringHash criteria; Tomahawk::InfoSystem::InfoStringHash criteria;
criteria[ "InfoChartCapabilities" ] = "chartsplugin";
emit getCachedInfo( criteria, 0, requestData ); emit getCachedInfo( criteria, 604800000, requestData );
} }
void void
@@ -187,9 +163,11 @@ ChartsPlugin::notInCacheSlot( QHash<QString, QString> criteria, Tomahawk::InfoSy
{ {
case InfoChart: case InfoChart:
{ {
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "InfoChart not in cache! Fetching...";
/// Fetch the chart, we need source and id /// Fetch the chart, we need source and id
QUrl url = QUrl( QString( CHART_URL "source/%1/chart/%2" ).arg( criteria["chart_source"] ).arg( criteria["chart_id"] ) ); QUrl url = QUrl( QString( CHART_URL "source/%1/chart/%2" ).arg( criteria["chart_source"] ).arg( criteria["chart_id"] ) );
qDebug() << Q_FUNC_INFO << "Getting chart url" << url; tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Getting chart url" << url;
QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) ); QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) ); reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
@@ -201,9 +179,33 @@ ChartsPlugin::notInCacheSlot( QHash<QString, QString> criteria, Tomahawk::InfoSy
case InfoChartCapabilities: case InfoChartCapabilities:
{ {
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "InfoChartCapabilities not in cache! Fetching...";
// we never need to re-fetch
if ( !m_allChartsMap.isEmpty() )
return;
/// Then get each chart from resource
if ( !m_chartResources.isEmpty() && m_allChartsMap.isEmpty() )
{
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "InfoChart fetching possible resources";
foreach ( QString resource, m_chartResources )
{
QUrl url = QUrl( QString( CHART_URL "source/%1" ).arg( resource ) );
QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
reply->setProperty( "chart_resource", resource);
tDebug() << "fetching:" << url;
connect( reply, SIGNAL( finished() ), SLOT( chartTypes() ) );
m_chartsFetchJobs++;
}
}
if ( m_chartsFetchJobs > 0 ) if ( m_chartsFetchJobs > 0 )
{ {
qDebug() << Q_FUNC_INFO << "InfoChartCapabilities still fetching!"; tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "InfoChartCapabilities still fetching!";
m_cachedRequests.append( requestData ); m_cachedRequests.append( requestData );
return; return;
} }
@@ -226,9 +228,10 @@ void
ChartsPlugin::chartTypes() ChartsPlugin::chartTypes()
{ {
/// Get possible chart type for specificChartsPlugin: InfoChart types returned chart source /// Get possible chart type for specificChartsPlugin: InfoChart types returned chart source
tDebug() << "Got chart type result"; tDebug( LOGVERBOSE ) << "Got chart type result";
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() ); QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
if ( reply->error() == QNetworkReply::NoError ) if ( reply->error() == QNetworkReply::NoError )
{ {
QJson::Parser p; QJson::Parser p;
@@ -262,7 +265,8 @@ ChartsPlugin::chartTypes()
QHash< QString, QVariantMap > extraType; QHash< QString, QVariantMap > extraType;
foreach( const QVariant& chartObj, chartObjs.values() ) foreach( const QVariant& chartObj, chartObjs.values() )
{ {
if( !chartObj.toMap().isEmpty() ){ if( !chartObj.toMap().isEmpty() )
{
const QVariantMap chart = chartObj.toMap(); const QVariantMap chart = chartObj.toMap();
const QString id = chart.value( "id" ).toString(); const QString id = chart.value( "id" ).toString();
const QString geo = chart.value( "geo" ).toString(); const QString geo = chart.value( "geo" ).toString();
@@ -271,7 +275,8 @@ ChartsPlugin::chartTypes()
const bool isDefault = ( chart.contains( "default" ) && chart[ "default" ].toInt() == 1 ); const bool isDefault = ( chart.contains( "default" ) && chart[ "default" ].toInt() == 1 );
QString extra; QString extra;
if( !geo.isEmpty() ){ if( !geo.isEmpty() )
{
if ( !m_cachedCountries.contains( geo ) ) if ( !m_cachedCountries.contains( geo ) )
{ {
@@ -289,10 +294,10 @@ ChartsPlugin::chartTypes()
m_cachedCountries[ geo ] = extra; m_cachedCountries[ geo ] = extra;
} }
else else
{
extra = m_cachedCountries[ geo ]; extra = m_cachedCountries[ geo ];
} }
}else extra = chart.value( "extra" ).toString(); else
extra = chart.value( "extra" ).toString();
if ( name.isEmpty() ) // not a specific chart, an all chart if ( name.isEmpty() ) // not a specific chart, an all chart
name = tr( "Top Overall" ); name = tr( "Top Overall" );
@@ -304,10 +309,10 @@ ChartsPlugin::chartTypes()
if ( isDefault ) if ( isDefault )
c[ "default" ] = "true"; c[ "default" ] = "true";
QList<InfoStringHash> extraTypeData = extraType[ extra ][ type ].value< QList< InfoStringHash > >(); QList< Tomahawk::InfoSystem::InfoStringHash > extraTypeData = extraType[ extra ][ type ].value< QList< Tomahawk::InfoSystem::InfoStringHash > >();
extraTypeData.append( c ); extraTypeData.append( c );
extraType[ extra ][ type ] = QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > >( extraTypeData );
extraType[ extra ].insert( type, QVariant::fromValue< QList< InfoStringHash > >( extraTypeData ) );
if ( isDefault ) if ( isDefault )
{ {
defaultChain.clear(); defaultChain.clear();
@@ -319,7 +324,7 @@ ChartsPlugin::chartTypes()
foreach( const QString& c, extraType.keys() ) foreach( const QString& c, extraType.keys() )
{ {
charts[ c ] = extraType[ c ]; charts[ c ] = extraType[ c ];
// qDebug() << "extraType has types:" << c; // tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "extraType has types:" << c;
} }
if( source == "itunes" ){ if( source == "itunes" ){
chartName = "iTunes"; chartName = "iTunes";
@@ -330,7 +335,8 @@ ChartsPlugin::chartTypes()
} }
} }
}else }
else
{ {
// We'll just build: // We'll just build:
// [Source] - Album - Chart Type // [Source] - Album - Chart Type
@@ -380,11 +386,11 @@ ChartsPlugin::chartTypes()
} }
} }
if( !artistCharts.isEmpty() ) if( !artistCharts.isEmpty() )
charts.insert( tr( "Artists" ), QVariant::fromValue< QList< InfoStringHash > >( artistCharts ) ); charts.insert( tr( "Artists" ), QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > >( artistCharts ) );
if( !albumCharts.isEmpty() ) if( !albumCharts.isEmpty() )
charts.insert( tr( "Albums" ), QVariant::fromValue< QList< InfoStringHash > >( albumCharts ) ); charts.insert( tr( "Albums" ), QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > >( albumCharts ) );
if( !trackCharts.isEmpty() ) if( !trackCharts.isEmpty() )
charts.insert( tr( "Tracks" ), QVariant::fromValue< QList< InfoStringHash > >( trackCharts ) ); charts.insert( tr( "Tracks" ), QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > >( trackCharts ) );
/// @note For displaying purposes, upper the first letter /// @note For displaying purposes, upper the first letter
/// @note Remeber to lower it when fetching this! /// @note Remeber to lower it when fetching this!
@@ -394,7 +400,7 @@ ChartsPlugin::chartTypes()
} }
/// Add the possible charts and its types to breadcrumb /// Add the possible charts and its types to breadcrumb
// qDebug() << "ADDING CHART TYPE TO CHARTS:" << chartName; // tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "ADDING CHART TYPE TO CHARTS:" << chartName;
QVariantMap defaultMap = m_allChartsMap.value( "defaults" ).value< QVariantMap >(); QVariantMap defaultMap = m_allChartsMap.value( "defaults" ).value< QVariantMap >();
defaultMap[ source ] = defaultChain; defaultMap[ source ] = defaultChain;
m_allChartsMap[ "defaults" ] = defaultMap; m_allChartsMap[ "defaults" ] = defaultMap;
@@ -413,6 +419,10 @@ ChartsPlugin::chartTypes()
foreach ( InfoRequestData request, m_cachedRequests ) foreach ( InfoRequestData request, m_cachedRequests )
{ {
emit info( request, m_allChartsMap ); emit info( request, m_allChartsMap );
// update cache
Tomahawk::InfoSystem::InfoStringHash criteria;
criteria[ "InfoChartCapabilities" ] = "chartsplugin";
emit updateCache( criteria, 604800000, request.type, m_allChartsMap );
} }
m_cachedRequests.clear(); m_cachedRequests.clear();
} }
@@ -441,8 +451,8 @@ ChartsPlugin::chartReturned()
/// SO we have a result, parse it! /// SO we have a result, parse it!
QVariantList chartResponse = res.value( "list" ).toList(); QVariantList chartResponse = res.value( "list" ).toList();
QList< InfoStringHash > top_tracks; QList< Tomahawk::InfoSystem::InfoStringHash > top_tracks;
QList< InfoStringHash > top_albums; QList< Tomahawk::InfoSystem::InfoStringHash > top_albums;
QStringList top_artists; QStringList top_artists;
/// Deside what type, we need to handle it differently /// Deside what type, we need to handle it differently
@@ -478,16 +488,16 @@ ChartsPlugin::chartReturned()
if ( album.isEmpty() && artist.isEmpty() ) // don't have enough... if ( album.isEmpty() && artist.isEmpty() ) // don't have enough...
{ {
tLog() << "Didn't get an artist and album name from chart, not enough to build a query on. Aborting" << title << album << artist; tDebug( LOGVERBOSE ) << "Didn't get an artist and album name from chart, not enough to build a query on. Aborting" << title << album << artist;
} }
else else
{ {
qDebug() << Q_FUNC_INFO << album << artist;
InfoStringHash pair; Tomahawk::InfoSystem::InfoStringHash pair;
pair["artist"] = artist; pair["artist"] = artist;
pair["album"] = album; pair["album"] = album;
top_albums << pair; top_albums.append( pair );
} }
} }
@@ -497,28 +507,28 @@ ChartsPlugin::chartReturned()
if ( title.isEmpty() && artist.isEmpty() ) // don't have enough... if ( title.isEmpty() && artist.isEmpty() ) // don't have enough...
{ {
tLog() << "Didn't get an artist and track name from charts, not enough to build a query on. Aborting" << title << artist << album; tDebug( LOGVERBOSE ) << "Didn't get an artist and track name from charts, not enough to build a query on. Aborting" << title << artist << album;
} }
else else
{ {
InfoStringHash pair; Tomahawk::InfoSystem::InfoStringHash pair;
pair["artist"] = artist; pair["artist"] = artist;
pair["track"] = title; pair["track"] = title;
top_tracks << pair; top_tracks.append( pair );
} }
}else if( chartType() == Artist ) }else if( chartType() == Artist )
{ {
if ( artist.isEmpty() ) // don't have enough... if ( artist.isEmpty() ) // don't have enough...
{ {
tLog() << "Didn't get an artist from charts, not enough to build a query on. Aborting" << artist; tDebug( LOGVERBOSE ) << "Didn't get an artist from charts, not enough to build a query on. Aborting" << artist;
} }
else else
{ {
top_artists << artist; top_artists.append( artist );
} }
} }
@@ -528,31 +538,35 @@ ChartsPlugin::chartReturned()
if( chartType() == Artist ) if( chartType() == Artist )
{ {
tDebug() << "ChartsPlugin:" << "\tgot " << top_artists.size() << " artists"; tDebug() << "ChartsPlugin:" << "\tgot " << top_artists.size() << " artists";
returnedData["artists"] = QVariant::fromValue( top_artists ); returnedData[ "artists" ] = QVariant::fromValue< QStringList >( top_artists );
returnedData["type"] = "artists"; returnedData[ "type" ] = "artists";
} }
if( chartType() == Track ) if( chartType() == Track )
{ {
tDebug() << "ChartsPlugin:" << "\tgot " << top_tracks.size() << " tracks"; tDebug() << "ChartsPlugin:" << "\tgot " << top_tracks.size() << " tracks";
returnedData["tracks"] = QVariant::fromValue( top_tracks ); returnedData[ "tracks" ] = QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > >( top_tracks );
returnedData["type"] = "tracks"; returnedData[ "type" ] = "tracks";
} }
if( chartType() == Album ) if( chartType() == Album )
{ {
tDebug() << "ChartsPlugin:" << "\tgot " << top_albums.size() << " albums"; tDebug() << "ChartsPlugin:" << "\tgot " << top_albums.size() << " albums";
returnedData["albums"] = QVariant::fromValue( top_albums ); returnedData[ "albums" ] = QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > >( top_albums );
returnedData["type"] = "albums"; returnedData[ "type" ] = "albums";
} }
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(); Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
emit info( requestData, returnedData ); emit info( requestData, returnedData );
// TODO update cache // update cache
Tomahawk::InfoSystem::InfoStringHash criteria;
Tomahawk::InfoSystem::InfoStringHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
criteria[ "chart_id" ] = origData[ "chart_id" ];
criteria[ "chart_source" ] = origData[ "chart_source" ];
emit updateCache( criteria, 86400000, requestData.type, returnedData );
} }
else else
qDebug() << "Network error in fetching chart:" << reply->url().toString(); tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Network error in fetching chart:" << reply->url().toString();
} }

View File

@@ -21,8 +21,8 @@
#include "infosystem/infosystem.h" #include "infosystem/infosystem.h"
#include "infosystem/infosystemworker.h" #include "infosystem/infosystemworker.h"
#include <QNetworkReply> #include <QtNetwork/QNetworkReply>
#include <QObject> #include <QtCore/QObject>
class QNetworkReply; class QNetworkReply;
@@ -47,8 +47,9 @@ public:
Artist = 0x04 Artist = 0x04
}; };
void setChartType( ChartType type ) { m_chartType = type; }
ChartType chartType() const { return m_chartType; } void setChartType( ChartType type ) { m_chartType = type; }
ChartType chartType() const { return m_chartType; }
public slots: public slots:
void chartReturned(); void chartReturned();
@@ -58,15 +59,20 @@ protected slots:
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData ); virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData ); virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
virtual void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant data ); virtual void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant data )
{
Q_UNUSED( caller )
Q_UNUSED( type )
Q_UNUSED( data )
}
private: private:
void fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData ); void fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData );
void fetchChartCapabilities( Tomahawk::InfoSystem::InfoRequestData requestData ); void fetchChartCapabilities( Tomahawk::InfoSystem::InfoRequestData requestData );
void dataError( Tomahawk::InfoSystem::InfoRequestData requestData ); void dataError( Tomahawk::InfoSystem::InfoRequestData requestData );
QVariantList m_chartResources; QStringList m_chartResources;
QList<InfoStringHash> m_charts; QList< InfoStringHash > m_charts;
ChartType m_chartType; ChartType m_chartType;
QVariantMap m_allChartsMap; QVariantMap m_allChartsMap;

View File

@@ -23,11 +23,9 @@
#include <QCryptographicHash> #include <QCryptographicHash>
#include <QNetworkConfiguration> #include <QNetworkConfiguration>
#include <QNetworkReply> #include <QNetworkReply>
#include <QDomElement>
#include "album.h" #include "album.h"
#include "typedefs.h" #include "typedefs.h"
#include "audio/audioengine.h"
#include "tomahawksettings.h" #include "tomahawksettings.h"
#include "utils/tomahawkutils.h" #include "utils/tomahawkutils.h"
#include "utils/logger.h" #include "utils/logger.h"
@@ -140,16 +138,6 @@ hypemPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
} }
} }
void
hypemPlugin::pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input )
{
Q_UNUSED( caller )
Q_UNUSED( type)
Q_UNUSED( input )
}
void void
hypemPlugin::fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData ) hypemPlugin::fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData )
{ {
@@ -173,8 +161,9 @@ hypemPlugin::fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData )
/// Set the criterias for current chart /// Set the criterias for current chart
criteria["chart_id"] = hash["chart_id"]; criteria["chart_id"] = hash["chart_id"];
criteria["chart_source"] = hash["chart_source"]; criteria["chart_source"] = hash["chart_source"];
/// @todo
emit getCachedInfo( criteria, 0, requestData ); /// set cache time based on wether requested type is 3day, lastweek or recent.
emit getCachedInfo( criteria, 86400000, requestData );
} }
void void
@@ -198,7 +187,7 @@ hypemPlugin::notInCacheSlot( QHash<QString, QString> criteria, Tomahawk::InfoSys
case InfoChart: case InfoChart:
{ {
/// Fetch the chart, we need source and id /// Fetch the chart, we need source and id
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "InfoChart not in cache! Fetching...";
QUrl url = QUrl( QString( HYPEM_URL "%1/%2" ).arg( criteria["chart_id"].toLower() ).arg(HYPEM_END_URL) ); QUrl url = QUrl( QString( HYPEM_URL "%1/%2" ).arg( criteria["chart_id"].toLower() ).arg(HYPEM_END_URL) );
qDebug() << Q_FUNC_INFO << "Getting chart url" << url; qDebug() << Q_FUNC_INFO << "Getting chart url" << url;
@@ -212,6 +201,7 @@ hypemPlugin::notInCacheSlot( QHash<QString, QString> criteria, Tomahawk::InfoSys
case InfoChartCapabilities: case InfoChartCapabilities:
{ {
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "InfoChartCapabilities not in cache! Fetching...";
if ( m_chartsFetchJobs > 0 ) if ( m_chartsFetchJobs > 0 )
{ {
qDebug() << Q_FUNC_INFO << "InfoChartCapabilities still fetching!"; qDebug() << Q_FUNC_INFO << "InfoChartCapabilities still fetching!";
@@ -390,7 +380,14 @@ hypemPlugin::chartReturned()
emit info( requestData, returnedData ); emit info( requestData, returnedData );
// TODO update cache // update cache
Tomahawk::InfoSystem::InfoStringHash criteria;
Tomahawk::InfoSystem::InfoStringHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
criteria[ "chart_id" ] = origData[ "chart_id" ];
criteria[ "chart_source" ] = origData[ "chart_source" ];
/// @todo
/// set cache time based on wether requested type is 3day, lastweek or recent.
emit updateCache( criteria, 86400000, requestData.type, returnedData );
} }
else else
qDebug() << "Network error in fetching chart:" << reply->url().toString(); qDebug() << "Network error in fetching chart:" << reply->url().toString();

View File

@@ -57,8 +57,13 @@ public slots:
protected slots: protected slots:
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData ); virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData ); virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
virtual void pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input )
{
Q_UNUSED( caller )
Q_UNUSED( type)
Q_UNUSED( input )
}
virtual void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant data );
private: private:
void fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData ); void fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData );

View File

@@ -53,11 +53,6 @@ LastFmPlugin::LastFmPlugin()
m_supportedGetTypes << InfoAlbumCoverArt << InfoArtistImages << InfoArtistSimilars << InfoArtistSongs << InfoChart << InfoChartCapabilities; m_supportedGetTypes << InfoAlbumCoverArt << InfoArtistImages << InfoArtistSimilars << InfoArtistSongs << InfoChart << InfoChartCapabilities;
m_supportedPushTypes << InfoSubmitScrobble << InfoSubmitNowPlaying << InfoLove << InfoUnLove; m_supportedPushTypes << InfoSubmitScrobble << InfoSubmitNowPlaying << InfoLove << InfoUnLove;
/*
Your API Key is 7194b85b6d1f424fe1668173a78c0c4a
Your secret is ba80f1df6d27ae63e9cb1d33ccf2052f
*/
// Flush session key cache // Flush session key cache
TomahawkSettings::instance()->setLastFmSessionKey( QByteArray() ); TomahawkSettings::instance()->setLastFmSessionKey( QByteArray() );
@@ -394,9 +389,7 @@ LastFmPlugin::notInCacheSlot( QHash<QString, QString> criteria, Tomahawk::InfoSy
} }
} }
tDebug() << "LastFmPlugin: InfoChart not in cache, fetching";
QMap<QString, QString> args; QMap<QString, QString> args;
tDebug() << "LastFmPlugin: " << "args chart_id" << criteria["chart_id"];
args["method"] = criteria["chart_id"]; args["method"] = criteria["chart_id"];
args["limit"] = "100"; args["limit"] = "100";
QNetworkReply* reply = lastfm::ws::get(args); QNetworkReply* reply = lastfm::ws::get(args);
@@ -412,26 +405,24 @@ LastFmPlugin::notInCacheSlot( QHash<QString, QString> criteria, Tomahawk::InfoSy
InfoStringHash c; InfoStringHash c;
c[ "type" ] = "tracks"; c[ "type" ] = "tracks";
c[ "id" ] = "chart.getTopTracks"; c[ "id" ] = "chart.getTopTracks";
c[ "label" ] = "Top Tracks"; c[ "label" ] = tr( "Top Tracks" );
track_charts.append( c ); track_charts.append( c );
c[ "id" ] = "chart.getLovedTracks"; c[ "id" ] = "chart.getLovedTracks";
c[ "label" ] = "Loved Tracks"; c[ "label" ] = tr( "Loved Tracks" );
track_charts.append( c ); track_charts.append( c );
c[ "id" ] = "chart.getHypedTracks"; c[ "id" ] = "chart.getHypedTracks";
c[ "label" ] = "Hyped Tracks"; c[ "label" ] = tr( "Hyped Tracks" );
track_charts.append( c ); track_charts.append( c );
QList< InfoStringHash > artist_charts; QList< InfoStringHash > artist_charts;
c[ "type" ] = "artists"; c[ "type" ] = "artists";
c[ "id" ] = "chart.getTopArtists"; c[ "id" ] = "chart.getTopArtists";
c[ "label" ] = "Top Artists"; c[ "label" ] = tr( "Top Artists" );
artist_charts.append( c ); artist_charts.append( c );
c[ "id" ] = "chart.getHypedArtists"; c[ "id" ] = "chart.getHypedArtists";
c[ "label" ] = "Hyped Artists"; c[ "label" ] = tr( "Hyped Artists" );
artist_charts.append( c ); artist_charts.append( c );
QVariantMap charts; QVariantMap charts;
charts.insert( "Tracks", QVariant::fromValue< QList< InfoStringHash > >( track_charts ) ); charts.insert( "Tracks", QVariant::fromValue< QList< InfoStringHash > >( track_charts ) );
charts.insert( "Artists", QVariant::fromValue< QList< InfoStringHash > >( artist_charts ) ); charts.insert( "Artists", QVariant::fromValue< QList< InfoStringHash > >( artist_charts ) );
@@ -439,7 +430,6 @@ LastFmPlugin::notInCacheSlot( QHash<QString, QString> criteria, Tomahawk::InfoSy
QVariantMap result; QVariantMap result;
result.insert( "Last.fm", QVariant::fromValue<QVariantMap>( charts ) ); result.insert( "Last.fm", QVariant::fromValue<QVariantMap>( charts ) );
tDebug() << "LASTFM RETURNING CHART LIST!";
emit info( requestData, result ); emit info( requestData, result );
return; return;
} }
@@ -531,7 +521,6 @@ LastFmPlugin::similarArtistsReturned()
void void
LastFmPlugin::chartReturned() LastFmPlugin::chartReturned()
{ {
tDebug() << "LastfmPlugin: InfoChart data returned!";
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() ); QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
QVariantMap returnedData; QVariantMap returnedData;
@@ -549,7 +538,6 @@ LastFmPlugin::chartReturned()
pair[ "track" ] = t.title(); pair[ "track" ] = t.title();
top_tracks << pair; top_tracks << pair;
} }
tDebug() << "LastFmPlugin:" << "\tgot " << top_tracks.size() << " tracks";
returnedData["tracks"] = QVariant::fromValue( top_tracks ); returnedData["tracks"] = QVariant::fromValue( top_tracks );
returnedData["type"] = "tracks"; returnedData["type"] = "tracks";
@@ -558,7 +546,6 @@ LastFmPlugin::chartReturned()
{ {
QList<lastfm::Artist> list = lastfm::Artist::list( reply ); QList<lastfm::Artist> list = lastfm::Artist::list( reply );
QStringList al; QStringList al;
tDebug() << "LastFmPlugin:"<< "\tgot " << list.size() << " artists";
foreach ( const lastfm::Artist& a, list ) foreach ( const lastfm::Artist& a, list )
al << a.toString(); al << a.toString();
returnedData["artists"] = al; returnedData["artists"] = al;
@@ -566,7 +553,7 @@ LastFmPlugin::chartReturned()
} }
else else
{ {
tDebug() << "LastfmPlugin:: got non tracks and non artists"; tDebug() << Q_FUNC_INFO << "got non tracks and non artists";
} }
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(); Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();

View File

@@ -165,6 +165,7 @@ MusicBrainzPlugin::artistSearchSlot()
if ( domNodeList.isEmpty() ) if ( domNodeList.isEmpty() )
{ {
emit info( oldReply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() ); emit info( oldReply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
tDebug() << Q_FUNC_INFO << doc.toString();
return; return;
} }

View File

@@ -23,7 +23,6 @@
#include <QCryptographicHash> #include <QCryptographicHash>
#include <QNetworkConfiguration> #include <QNetworkConfiguration>
#include <QNetworkReply> #include <QNetworkReply>
#include <QDomElement>
#include "album.h" #include "album.h"
#include "typedefs.h" #include "typedefs.h"
@@ -33,7 +32,7 @@
#include "utils/logger.h" #include "utils/logger.h"
#include "chartsplugin_data_p.h" #include "chartsplugin_data_p.h"
#define SPOTIFY_API_URL "http://spotikea.tomahawk-player.org:10380/" #define SPOTIFY_API_URL "http://spotikea.tomahawk-player.org/"
#include <qjson/parser.h> #include <qjson/parser.h>
#include <qjson/serializer.h> #include <qjson/serializer.h>
@@ -47,19 +46,6 @@ SpotifyPlugin::SpotifyPlugin()
m_supportedGetTypes << InfoChart << InfoChartCapabilities; m_supportedGetTypes << InfoChart << InfoChartCapabilities;
// we never need to re-fetch
if ( !m_allChartsMap.isEmpty() )
return;
/// We need to fetch possible types before they are asked for
tDebug() << "SpotifyPlugin: InfoChart fetching possible resources";
QUrl url = QUrl( QString( SPOTIFY_API_URL "toplist/charts" ) );
QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
tDebug() << Q_FUNC_INFO << "fetching:" << url;
connect( reply, SIGNAL( finished() ), SLOT( chartTypes() ) );
m_chartsFetchJobs++;
} }
@@ -107,14 +93,6 @@ SpotifyPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
} }
void
SpotifyPlugin::pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input )
{
Q_UNUSED( caller )
Q_UNUSED( type)
Q_UNUSED( input )
}
void void
SpotifyPlugin::fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData ) SpotifyPlugin::fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData )
{ {
@@ -123,17 +101,22 @@ SpotifyPlugin::fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData )
dataError( requestData ); dataError( requestData );
return; return;
} }
InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >(); InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
Tomahawk::InfoSystem::InfoStringHash criteria; Tomahawk::InfoSystem::InfoStringHash criteria;
if ( !hash.contains( "chart_id" ) ) /// Each request needs to contain both a id and source
if ( !hash.contains( "chart_id" ) && !hash.contains( "chart_source" ) )
{ {
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Hash did not contain required params!";
dataError( requestData ); dataError( requestData );
return; return;
} else {
criteria["chart_id"] = hash["chart_id"];
}
emit getCachedInfo( criteria, 604800000 /* Expire chart cache in 1 week */, requestData ); }
/// Set the criterias for current chart
criteria["chart_id"] = hash["chart_id"];
criteria["chart_source"] = hash["chart_source"];
emit getCachedInfo( criteria, 86400000 /* Expire chart cache in 1 day */, requestData );
} }
void void
SpotifyPlugin::fetchChartCapabilities( Tomahawk::InfoSystem::InfoRequestData requestData ) SpotifyPlugin::fetchChartCapabilities( Tomahawk::InfoSystem::InfoRequestData requestData )
@@ -145,7 +128,8 @@ SpotifyPlugin::fetchChartCapabilities( Tomahawk::InfoSystem::InfoRequestData req
} }
Tomahawk::InfoSystem::InfoStringHash criteria; Tomahawk::InfoSystem::InfoStringHash criteria;
emit getCachedInfo( criteria, 0, requestData ); criteria[ "InfoChartCapabilities" ] = "spotifyplugin";
emit getCachedInfo( criteria, 604800000, requestData );
} }
void void
@@ -157,6 +141,7 @@ SpotifyPlugin::notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, To
case InfoChart: case InfoChart:
{ {
/// Fetch the chart, we need source and id /// Fetch the chart, we need source and id
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "InfoChart not in cache! Fetching...";
QUrl url = QUrl( QString( SPOTIFY_API_URL "toplist/%1/" ).arg( criteria["chart_id"] ) ); QUrl url = QUrl( QString( SPOTIFY_API_URL "toplist/%1/" ).arg( criteria["chart_id"] ) );
qDebug() << Q_FUNC_INFO << "Getting chart url" << url; qDebug() << Q_FUNC_INFO << "Getting chart url" << url;
@@ -169,6 +154,21 @@ SpotifyPlugin::notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, To
} }
case InfoChartCapabilities: case InfoChartCapabilities:
{ {
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "InfoChartCapabilities not in cache! Fetching...";
// we never need to re-fetch
if ( !m_allChartsMap.isEmpty() )
return;
/// We need to fetch possible types before they are asked for
tDebug() << "SpotifyPlugin: InfoChart fetching possible resources";
QUrl url = QUrl( QString( SPOTIFY_API_URL "toplist/charts" ) );
QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
tDebug() << Q_FUNC_INFO << "fetching:" << url;
connect( reply, SIGNAL( finished() ), SLOT( chartTypes() ) );
m_chartsFetchJobs++;
if ( m_chartsFetchJobs > 0 ) if ( m_chartsFetchJobs > 0 )
{ {
qDebug() << Q_FUNC_INFO << "InfoChartCapabilities still fetching!"; qDebug() << Q_FUNC_INFO << "InfoChartCapabilities still fetching!";
@@ -275,6 +275,9 @@ SpotifyPlugin::chartTypes()
foreach ( InfoRequestData request, m_cachedRequests ) foreach ( InfoRequestData request, m_cachedRequests )
{ {
emit info( request, m_allChartsMap ); emit info( request, m_allChartsMap );
Tomahawk::InfoSystem::InfoStringHash criteria;
criteria[ "InfoChartCapabilities" ] = "spotifyplugin";
emit updateCache( criteria,604800000, request.type, m_allChartsMap );
} }
m_cachedRequests.clear(); m_cachedRequests.clear();
} }
@@ -379,9 +382,14 @@ SpotifyPlugin::chartReturned()
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(); Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
emit info( requestData, returnedData ); emit info( requestData, returnedData );
// update cache
Tomahawk::InfoSystem::InfoStringHash criteria;
Tomahawk::InfoSystem::InfoStringHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
criteria[ "chart_id" ] = origData[ "chart_id" ];
criteria[ "chart_source" ] = origData[ "chart_source" ];
emit updateCache( criteria, 86400000, requestData.type, returnedData );
} }
else else
qDebug() << "Network error in fetching chart:" << reply->url().toString(); qDebug() << "Network error in fetching chart:" << reply->url().toString();

View File

@@ -57,7 +57,12 @@ public slots:
protected slots: protected slots:
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData ); virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData ); virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
virtual void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant data ); virtual void pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input )
{
Q_UNUSED( caller )
Q_UNUSED( type)
Q_UNUSED( input )
}
private: private:
void fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData ); void fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData );

View File

@@ -258,7 +258,7 @@ MprisPlugin::metadata() const
// Only return art if tempfile exists, and if its name contains the same "artist_album_tomahawk_cover.png" // Only return art if tempfile exists, and if its name contains the same "artist_album_tomahawk_cover.png"
if( m_coverTempFile && m_coverTempFile->exists() && if( m_coverTempFile && m_coverTempFile->exists() &&
m_coverTempFile->fileName().contains( track->artist()->name() + "_" + track->album()->name() + "_tomahawk_cover.png" ) ) m_coverTempFile->fileName().contains( track->artist()->name() + "_" + track->album()->name() + "_tomahawk_cover.png" ) )
metadataMap.insert( "mpris:artUrl", QFileInfo( *m_coverTempFile ).absoluteFilePath() ); metadataMap.insert( "mpris:artUrl", QString( QUrl::fromLocalFile( QFileInfo( *m_coverTempFile ).absoluteFilePath() ).toEncoded() ) );
else else
{ {
// Need to fetch the album cover // Need to fetch the album cover
@@ -275,7 +275,6 @@ MprisPlugin::metadata() const
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData ); Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData );
} }
} }
return metadataMap; return metadataMap;

View File

@@ -51,6 +51,7 @@ InfoSystem::instance()
InfoSystem::InfoSystem( QObject *parent ) InfoSystem::InfoSystem( QObject *parent )
: QObject( parent ) : QObject( parent )
, m_inited( false )
, m_infoSystemCacheThreadController( 0 ) , m_infoSystemCacheThreadController( 0 )
, m_infoSystemWorkerThreadController( 0 ) , m_infoSystemWorkerThreadController( 0 )
{ {
@@ -59,71 +60,94 @@ InfoSystem::InfoSystem( QObject *parent )
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
m_infoSystemCacheThreadController = new InfoSystemCacheThread( this ); m_infoSystemCacheThreadController = new InfoSystemCacheThread( this );
m_cache = QWeakPointer< InfoSystemCache >( new InfoSystemCache() );
m_cache.data()->moveToThread( m_infoSystemCacheThreadController );
m_infoSystemCacheThreadController->setCache( m_cache );
m_infoSystemCacheThreadController->start( QThread::IdlePriority ); m_infoSystemCacheThreadController->start( QThread::IdlePriority );
m_infoSystemWorkerThreadController = new InfoSystemWorkerThread( this ); m_infoSystemWorkerThreadController = new InfoSystemWorkerThread( this );
m_worker = QWeakPointer< InfoSystemWorker >( new InfoSystemWorker() );
m_worker.data()->moveToThread( m_infoSystemWorkerThreadController );
m_infoSystemWorkerThreadController->setWorker( m_worker );
m_infoSystemWorkerThreadController->start(); m_infoSystemWorkerThreadController->start();
QMetaObject::invokeMethod( m_worker.data(), "init", Qt::QueuedConnection, Q_ARG( QWeakPointer< Tomahawk::InfoSystem::InfoSystemCache >, m_cache ) ); QTimer::singleShot( 0, this, SLOT( init() ) );
connect( m_cache.data(), SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
m_worker.data(), SLOT( infoSlot( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), Qt::UniqueConnection );
connect( m_worker.data(), SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
this, SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), Qt::UniqueConnection );
connect( m_worker.data(), SIGNAL( finished( QString ) ), this, SIGNAL( finished( QString ) ), Qt::UniqueConnection );
connect( m_worker.data(), SIGNAL( finished( QString, Tomahawk::InfoSystem::InfoType ) ),
this, SIGNAL( finished( QString, Tomahawk::InfoSystem::InfoType ) ), Qt::UniqueConnection );
} }
InfoSystem::~InfoSystem() InfoSystem::~InfoSystem()
{ {
qDebug() << Q_FUNC_INFO << " beginning"; tDebug() << Q_FUNC_INFO << " beginning";
if ( !m_worker.isNull() ) if ( m_infoSystemWorkerThreadController->worker() )
{ {
m_infoSystemWorkerThreadController->quit(); m_infoSystemWorkerThreadController->quit();
m_infoSystemWorkerThreadController->wait( 60000 ); m_infoSystemWorkerThreadController->wait( 60000 );
//delete m_worker.data();
delete m_infoSystemWorkerThreadController; delete m_infoSystemWorkerThreadController;
m_infoSystemWorkerThreadController = 0; m_infoSystemWorkerThreadController = 0;
} }
qDebug() << Q_FUNC_INFO << " done deleting worker"; tDebug() << Q_FUNC_INFO << " done deleting worker";
if( m_infoSystemCacheThreadController ) if( m_infoSystemCacheThreadController->cache() )
{ {
m_infoSystemCacheThreadController->quit(); m_infoSystemCacheThreadController->quit();
m_infoSystemCacheThreadController->wait( 60000 ); m_infoSystemCacheThreadController->wait( 60000 );
//delete m_cache.data();
delete m_infoSystemCacheThreadController; delete m_infoSystemCacheThreadController;
m_infoSystemCacheThreadController = 0; m_infoSystemCacheThreadController = 0;
} }
qDebug() << Q_FUNC_INFO << " done deleting cache"; tDebug() << Q_FUNC_INFO << " done deleting cache";
} }
void void
InfoSystem::init()
{
tDebug() << Q_FUNC_INFO;
if ( !m_infoSystemCacheThreadController->cache() || !m_infoSystemWorkerThreadController->worker() )
{
QTimer::singleShot( 0, this, SLOT( init() ) );
return;
}
Tomahawk::InfoSystem::InfoSystemCache* cache = m_infoSystemCacheThreadController->cache();
Tomahawk::InfoSystem::InfoSystemWorker* worker = m_infoSystemWorkerThreadController->worker();
connect( cache, SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
worker, SLOT( infoSlot( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), Qt::UniqueConnection );
connect( worker, SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
this, SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), Qt::UniqueConnection );
connect( worker, SIGNAL( finished( QString ) ), this, SIGNAL( finished( QString ) ), Qt::UniqueConnection );
connect( worker, SIGNAL( finished( QString, Tomahawk::InfoSystem::InfoType ) ),
this, SIGNAL( finished( QString, Tomahawk::InfoSystem::InfoType ) ), Qt::UniqueConnection );
QMetaObject::invokeMethod( worker, "init", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoSystemCache*, cache ) );
m_inited = true;
}
bool
InfoSystem::getInfo( const InfoRequestData &requestData ) InfoSystem::getInfo( const InfoRequestData &requestData )
{ {
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
QMetaObject::invokeMethod( m_worker.data(), "getInfo", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoRequestData, requestData ) ); if ( !m_inited || !m_infoSystemWorkerThreadController->worker() )
{
init();
return false;
}
QMetaObject::invokeMethod( m_infoSystemWorkerThreadController->worker(), "getInfo", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoRequestData, requestData ) );
return true;
} }
void bool
InfoSystem::getInfo( const QString &caller, const QVariantMap &customData, const InfoTypeMap &inputMap, const InfoTimeoutMap &timeoutMap, bool allSources ) InfoSystem::getInfo( const QString &caller, const QVariantMap &customData, const InfoTypeMap &inputMap, const InfoTimeoutMap &timeoutMap, bool allSources )
{ {
if ( !m_inited || !m_infoSystemWorkerThreadController->worker() )
{
init();
return false;
}
InfoRequestData requestData; InfoRequestData requestData;
requestData.caller = caller; requestData.caller = caller;
requestData.customData = customData; requestData.customData = customData;
@@ -133,82 +157,102 @@ InfoSystem::getInfo( const QString &caller, const QVariantMap &customData, const
requestData.type = type; requestData.type = type;
requestData.input = inputMap[ type ]; requestData.input = inputMap[ type ];
requestData.timeoutMillis = timeoutMap.contains( type ) ? timeoutMap[ type ] : 10000; requestData.timeoutMillis = timeoutMap.contains( type ) ? timeoutMap[ type ] : 10000;
QMetaObject::invokeMethod( m_worker.data(), "getInfo", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoRequestData, requestData ) ); QMetaObject::invokeMethod( m_infoSystemWorkerThreadController->worker(), "getInfo", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoRequestData, requestData ) );
} }
return false;
} }
void bool
InfoSystem::pushInfo( const QString &caller, const InfoType type, const QVariant& input ) InfoSystem::pushInfo( const QString &caller, const InfoType type, const QVariant& input )
{ {
qDebug() << Q_FUNC_INFO; tDebug() << Q_FUNC_INFO;
QMetaObject::invokeMethod( m_worker.data(), "pushInfo", Qt::QueuedConnection, Q_ARG( QString, caller ), Q_ARG( Tomahawk::InfoSystem::InfoType, type ), Q_ARG( QVariant, input ) ); if ( !m_inited || !m_infoSystemWorkerThreadController->worker() )
{
init();
return false;
}
QMetaObject::invokeMethod( m_infoSystemWorkerThreadController->worker(), "pushInfo", Qt::QueuedConnection, Q_ARG( QString, caller ), Q_ARG( Tomahawk::InfoSystem::InfoType, type ), Q_ARG( QVariant, input ) );
return true;
} }
void bool
InfoSystem::pushInfo( const QString &caller, const InfoTypeMap &input ) InfoSystem::pushInfo( const QString &caller, const InfoTypeMap &input )
{ {
if ( !m_inited || !m_infoSystemWorkerThreadController->worker() )
{
init();
return false;
}
Q_FOREACH( InfoType type, input.keys() ) Q_FOREACH( InfoType type, input.keys() )
QMetaObject::invokeMethod( m_worker.data(), "pushInfo", Qt::QueuedConnection, Q_ARG( QString, caller ), Q_ARG( Tomahawk::InfoSystem::InfoType, type ), Q_ARG( QVariant, input[ type ] ) ); QMetaObject::invokeMethod( m_infoSystemWorkerThreadController->worker(), "pushInfo", Qt::QueuedConnection, Q_ARG( QString, caller ), Q_ARG( Tomahawk::InfoSystem::InfoType, type ), Q_ARG( QVariant, input[ type ] ) );
return true;
} }
InfoSystemCacheThread::InfoSystemCacheThread( QObject *parent ) InfoSystemCacheThread::InfoSystemCacheThread( QObject *parent )
: QThread( parent ) : QThread( parent )
{ {
tDebug() << Q_FUNC_INFO;
} }
InfoSystemCacheThread::~InfoSystemCacheThread() InfoSystemCacheThread::~InfoSystemCacheThread()
{ {
delete m_cache.data(); tDebug() << Q_FUNC_INFO;
} }
void void
InfoSystemCacheThread::InfoSystemCacheThread::run() InfoSystemCacheThread::InfoSystemCacheThread::run()
{ {
m_cache = QWeakPointer< InfoSystemCache >( new InfoSystemCache() );
exec(); exec();
if ( !m_cache.isNull() )
delete m_cache.data();
} }
QWeakPointer< InfoSystemCache >
InfoSystemCache*
InfoSystemCacheThread::cache() const InfoSystemCacheThread::cache() const
{ {
return m_cache; if ( m_cache.isNull() )
return 0;
return m_cache.data();
} }
void
InfoSystemCacheThread::setCache( QWeakPointer< InfoSystemCache > cache )
{
m_cache = cache;
}
InfoSystemWorkerThread::InfoSystemWorkerThread( QObject *parent ) InfoSystemWorkerThread::InfoSystemWorkerThread( QObject *parent )
: QThread( parent ) : QThread( parent )
{ {
tDebug() << Q_FUNC_INFO;
} }
InfoSystemWorkerThread::~InfoSystemWorkerThread() InfoSystemWorkerThread::~InfoSystemWorkerThread()
{ {
tDebug() << Q_FUNC_INFO;
} }
void void
InfoSystemWorkerThread::InfoSystemWorkerThread::run() InfoSystemWorkerThread::InfoSystemWorkerThread::run()
{ {
m_worker = QWeakPointer< InfoSystemWorker >( new InfoSystemWorker() );
exec(); exec();
if( m_worker ) if( !m_worker.isNull() )
delete m_worker.data(); delete m_worker.data();
} }
QWeakPointer< InfoSystemWorker > InfoSystemWorker*
InfoSystemWorkerThread::worker() const InfoSystemWorkerThread::worker() const
{ {
return m_worker; if ( m_worker.isNull() )
} return 0;
return m_worker.data();
void
InfoSystemWorkerThread::setWorker( QWeakPointer< InfoSystemWorker > worker )
{
m_worker = worker;
} }

View File

@@ -205,8 +205,7 @@ public:
virtual ~InfoSystemCacheThread(); virtual ~InfoSystemCacheThread();
void run(); void run();
QWeakPointer< InfoSystemCache > cache() const; InfoSystemCache* cache() const;
void setCache( QWeakPointer< InfoSystemCache > cache );
private: private:
QWeakPointer< InfoSystemCache > m_cache; QWeakPointer< InfoSystemCache > m_cache;
@@ -221,8 +220,7 @@ public:
virtual ~InfoSystemWorkerThread(); virtual ~InfoSystemWorkerThread();
void run(); void run();
QWeakPointer< InfoSystemWorker > worker() const; InfoSystemWorker* worker() const;
void setWorker( QWeakPointer< InfoSystemWorker > worker );
private: private:
QWeakPointer< InfoSystemWorker > m_worker; QWeakPointer< InfoSystemWorker > m_worker;
@@ -238,20 +236,22 @@ public:
InfoSystem( QObject *parent ); InfoSystem( QObject *parent );
~InfoSystem(); ~InfoSystem();
void getInfo( const InfoRequestData &requestData ); bool getInfo( const InfoRequestData &requestData );
//WARNING: if changing timeoutMillis above, also change in below function in .cpp file //WARNING: if changing timeoutMillis above, also change in below function in .cpp file
void getInfo( const QString &caller, const QVariantMap &customData, const InfoTypeMap &inputMap, const InfoTimeoutMap &timeoutMap = InfoTimeoutMap(), bool allSources = false ); bool getInfo( const QString &caller, const QVariantMap &customData, const InfoTypeMap &inputMap, const InfoTimeoutMap &timeoutMap = InfoTimeoutMap(), bool allSources = false );
void pushInfo( const QString &caller, const InfoType type, const QVariant &input ); bool pushInfo( const QString &caller, const InfoType type, const QVariant &input );
void pushInfo( const QString &caller, const InfoTypeMap &input ); bool pushInfo( const QString &caller, const InfoTypeMap &input );
signals: signals:
void info( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output ); void info( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
void finished( QString target ); void finished( QString target );
void finished( QString target, Tomahawk::InfoSystem::InfoType type ); void finished( QString target, Tomahawk::InfoSystem::InfoType type );
private slots:
void init();
private: private:
QWeakPointer< InfoSystemCache > m_cache; bool m_inited;
QWeakPointer< InfoSystemWorker > m_worker;
InfoSystemCacheThread* m_infoSystemCacheThreadController; InfoSystemCacheThread* m_infoSystemCacheThreadController;
InfoSystemWorkerThread* m_infoSystemWorkerThreadController; InfoSystemWorkerThread* m_infoSystemWorkerThreadController;
@@ -287,7 +287,7 @@ inline uint qHash( Tomahawk::InfoSystem::InfoStringHash hash )
Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoRequestData ); Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoRequestData );
Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoStringHash ); Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoStringHash );
Q_DECLARE_METATYPE( QWeakPointer< Tomahawk::InfoSystem::InfoSystemCache > ); Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoSystemCache* );
Q_DECLARE_METATYPE( QList<Tomahawk::InfoSystem::InfoStringHash> ); Q_DECLARE_METATYPE( QList< Tomahawk::InfoSystem::InfoStringHash > );
#endif // TOMAHAWK_INFOSYSTEM_H #endif // TOMAHAWK_INFOSYSTEM_H

View File

@@ -39,6 +39,7 @@ InfoSystemCache::InfoSystemCache( QObject* parent )
, m_cacheBaseDir( QDesktopServices::storageLocation( QDesktopServices::CacheLocation ) + "/InfoSystemCache/" ) , m_cacheBaseDir( QDesktopServices::storageLocation( QDesktopServices::CacheLocation ) + "/InfoSystemCache/" )
, m_cacheVersion( 2 ) , m_cacheVersion( 2 )
{ {
tDebug() << Q_FUNC_INFO;
TomahawkSettings *s = TomahawkSettings::instance(); TomahawkSettings *s = TomahawkSettings::instance();
if ( s->infoSystemCacheVersion() != m_cacheVersion ) if ( s->infoSystemCacheVersion() != m_cacheVersion )
{ {
@@ -64,6 +65,7 @@ InfoSystemCache::InfoSystemCache( QObject* parent )
InfoSystemCache::~InfoSystemCache() InfoSystemCache::~InfoSystemCache()
{ {
tDebug() << Q_FUNC_INFO;
} }
void void

View File

@@ -53,7 +53,7 @@ namespace InfoSystem
InfoSystemWorker::InfoSystemWorker() InfoSystemWorker::InfoSystemWorker()
: QObject() : QObject()
{ {
// qDebug() << Q_FUNC_INFO; tDebug() << Q_FUNC_INFO;
m_checkTimeoutsTimer.setInterval( 1000 ); m_checkTimeoutsTimer.setInterval( 1000 );
m_checkTimeoutsTimer.setSingleShot( false ); m_checkTimeoutsTimer.setSingleShot( false );
@@ -64,20 +64,20 @@ InfoSystemWorker::InfoSystemWorker()
InfoSystemWorker::~InfoSystemWorker() InfoSystemWorker::~InfoSystemWorker()
{ {
// qDebug() << Q_FUNC_INFO << " beginning"; tDebug() << Q_FUNC_INFO << " beginning";
Q_FOREACH( InfoPluginPtr plugin, m_plugins ) Q_FOREACH( InfoPluginPtr plugin, m_plugins )
{ {
if( plugin ) if( plugin )
delete plugin.data(); delete plugin.data();
} }
// qDebug() << Q_FUNC_INFO << " finished"; tDebug() << Q_FUNC_INFO << " finished";
} }
void void
InfoSystemWorker::init( QWeakPointer< Tomahawk::InfoSystem::InfoSystemCache> cache ) InfoSystemWorker::init( Tomahawk::InfoSystem::InfoSystemCache* cache )
{ {
// qDebug() << Q_FUNC_INFO << "and cache is" << cache.data(); tDebug() << Q_FUNC_INFO;
InfoPluginPtr enptr( new EchoNestPlugin() ); InfoPluginPtr enptr( new EchoNestPlugin() );
m_plugins.append( enptr ); m_plugins.append( enptr );
@@ -132,13 +132,13 @@ InfoSystemWorker::init( QWeakPointer< Tomahawk::InfoSystem::InfoSystemCache> cac
connect( connect(
plugin.data(), plugin.data(),
SIGNAL( getCachedInfo( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoRequestData ) ), SIGNAL( getCachedInfo( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoRequestData ) ),
cache.data(), cache,
SLOT( getCachedInfoSlot( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoRequestData ) ) SLOT( getCachedInfoSlot( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoRequestData ) )
); );
connect( connect(
plugin.data(), plugin.data(),
SIGNAL( updateCache( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoType, QVariant ) ), SIGNAL( updateCache( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoType, QVariant ) ),
cache.data(), cache,
SLOT( updateCacheSlot( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoType, QVariant ) ) SLOT( updateCacheSlot( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoType, QVariant ) )
); );
} }

View File

@@ -55,7 +55,7 @@ signals:
void finished( QString target, Tomahawk::InfoSystem::InfoType type ); void finished( QString target, Tomahawk::InfoSystem::InfoType type );
public slots: public slots:
void init( QWeakPointer< Tomahawk::InfoSystem::InfoSystemCache > cache ); void init( Tomahawk::InfoSystem::InfoSystemCache* cache );
void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData ); void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input ); void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input );

View File

@@ -21,18 +21,21 @@
#include "JobStatusItem.h" #include "JobStatusItem.h"
#include "utils/logger.h" #include "utils/logger.h"
JobStatusModel::JobStatusModel( QObject* parent ) JobStatusModel::JobStatusModel( QObject* parent )
: QAbstractListModel ( parent ) : QAbstractListModel ( parent )
{ {
} }
JobStatusModel::~JobStatusModel() JobStatusModel::~JobStatusModel()
{ {
qDeleteAll( m_items ); qDeleteAll( m_items );
m_collapseCount.clear(); m_collapseCount.clear();
} }
void void
JobStatusModel::addJob( JobStatusItem* item ) JobStatusModel::addJob( JobStatusItem* item )
{ {
@@ -55,11 +58,12 @@ JobStatusModel::addJob( JobStatusItem* item )
} }
qDebug() << "Adding item:" << item; qDebug() << "Adding item:" << item;
beginInsertRows( QModelIndex(), 0, 0 ); beginInsertRows( QModelIndex(), m_items.count(), m_items.count() );
m_items.prepend( item ); m_items.append( item );
endInsertRows(); endInsertRows();
} }
Qt::ItemFlags Qt::ItemFlags
JobStatusModel::flags( const QModelIndex& index ) const JobStatusModel::flags( const QModelIndex& index ) const
{ {
@@ -81,6 +85,7 @@ JobStatusModel::data( const QModelIndex& index, int role ) const
{ {
case Qt::DecorationRole: case Qt::DecorationRole:
return item->icon(); return item->icon();
case Qt::ToolTipRole:
case Qt::DisplayRole: case Qt::DisplayRole:
{ {
if ( m_collapseCount.contains( item->type() ) ) if ( m_collapseCount.contains( item->type() ) )
@@ -100,6 +105,7 @@ JobStatusModel::data( const QModelIndex& index, int role ) const
return QVariant(); return QVariant();
} }
int int
JobStatusModel::rowCount( const QModelIndex& parent ) const JobStatusModel::rowCount( const QModelIndex& parent ) const
{ {
@@ -114,7 +120,7 @@ JobStatusModel::itemFinished()
JobStatusItem* item = qobject_cast< JobStatusItem* >( sender() ); JobStatusItem* item = qobject_cast< JobStatusItem* >( sender() );
Q_ASSERT( item ); Q_ASSERT( item );
tDebug() << "Got item finished:" << item->type() << item->mainText() << item; // tDebug() << "Got item finished:" << item->type() << item->mainText() << item;
if ( !m_items.contains( item ) && !m_collapseCount.contains( item->type() ) ) if ( !m_items.contains( item ) && !m_collapseCount.contains( item->type() ) )
return; return;
@@ -140,7 +146,7 @@ JobStatusModel::itemFinished()
// qDebug() << "Replaced" << m_collapseCount[ item->type() ].first() << "with:" << m_collapseCount[ item->type() ][ 1 ] << m_items; // qDebug() << "Replaced" << m_collapseCount[ item->type() ].first() << "with:" << m_collapseCount[ item->type() ][ 1 ] << m_items;
} }
m_collapseCount[ item->type() ].removeAll( item ); m_collapseCount[ item->type() ].removeAll( item );
tDebug() << "New collapse count list:" << m_collapseCount[ item->type() ]; // tDebug() << "New collapse count list:" << m_collapseCount[ item->type() ];
if ( m_collapseCount[ item->type() ].isEmpty() ) if ( m_collapseCount[ item->type() ].isEmpty() )
m_collapseCount.remove( item->type() ); m_collapseCount.remove( item->type() );
else else
@@ -164,6 +170,7 @@ JobStatusModel::itemFinished()
item->deleteLater(); item->deleteLater();
} }
void void
JobStatusModel::itemUpdated() JobStatusModel::itemUpdated()
{ {

View File

@@ -19,23 +19,22 @@
#include "JobStatusView.h" #include "JobStatusView.h"
#include "pipeline.h"
#include "libtomahawk/pipeline.h"
#include "JobStatusModel.h" #include "JobStatusModel.h"
#include "JobStatusDelegate.h" #include "JobStatusDelegate.h"
#include "PipelineStatusItem.h" #include "PipelineStatusItem.h"
#include "TransferStatusItem.h"
#include "LatchedStatusItem.h"
#include "utils/logger.h" #include "utils/logger.h"
#include <QHeaderView> #include <QHeaderView>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QListView> #include <QListView>
#include <QAbstractItemModel> #include <QAbstractItemModel>
#include "TransferStatusItem.h"
#include "LatchedStatusItem.h"
using namespace Tomahawk; using namespace Tomahawk;
JobStatusView* JobStatusView::s_instance = 0; JobStatusView* JobStatusView::s_instance = 0;
JobStatusView::JobStatusView( AnimatedSplitter* parent ) JobStatusView::JobStatusView( AnimatedSplitter* parent )
@@ -72,13 +71,12 @@ JobStatusView::JobStatusView( AnimatedSplitter* parent )
setFont( f ); setFont( f );
#endif #endif
hideWidget();
new PipelineStatusManager( this ); new PipelineStatusManager( this );
new TransferStatusManager( this ); new TransferStatusManager( this );
new LatchedStatusManager( this ); new LatchedStatusManager( this );
} }
void void
JobStatusView::setModel( JobStatusModel* m ) JobStatusView::setModel( JobStatusModel* m )
{ {
@@ -90,15 +88,14 @@ JobStatusView::setModel( JobStatusModel* m )
connect( m_view->model(), SIGNAL( rowsRemoved( QModelIndex, int, int ) ), this, SLOT( checkCount() ) ); connect( m_view->model(), SIGNAL( rowsRemoved( QModelIndex, int, int ) ), this, SLOT( checkCount() ) );
} }
void void
JobStatusView::checkCount() JobStatusView::checkCount()
{ {
if ( m_view->model()->rowCount() == 0 && !isHidden() ) if ( m_view->model()->rowCount() == 0 && !isHidden() )
emit hideWidget(); emit hideWidget();
else if ( isHidden() && m_view->model()->rowCount() > 0 )
emit showWidget();
else else
emit sizeChanged( sizeHint() ); emit sizeHintChanged( sizeHint() );
} }

View File

@@ -18,8 +18,8 @@
#include "connection.h" #include "connection.h"
#include <QTime> #include <QtCore/QTime>
#include <QThread> #include <QtCore/QThread>
#include "network/servent.h" #include "network/servent.h"
#include "utils/logger.h" #include "utils/logger.h"
@@ -63,7 +63,7 @@ Connection::Connection( Servent* parent )
Connection::~Connection() Connection::~Connection()
{ {
qDebug() << "DTOR connection (super)" << id() << thread() << m_sock.isNull(); tDebug() << "DTOR connection (super)" << id() << thread() << m_sock.isNull();
if( !m_sock.isNull() ) if( !m_sock.isNull() )
{ {
// qDebug() << "deleteLatering sock" << m_sock; // qDebug() << "deleteLatering sock" << m_sock;
@@ -82,7 +82,7 @@ Connection::handleIncomingQueueEmpty()
// << "m_peer_disconnected" << m_peer_disconnected // << "m_peer_disconnected" << m_peer_disconnected
// << "bytes rx" << bytesReceived(); // << "bytes rx" << bytesReceived();
if( m_sock->bytesAvailable() == 0 && m_peer_disconnected ) if( !m_sock.isNull() && m_sock->bytesAvailable() == 0 && m_peer_disconnected )
{ {
qDebug() << "No more data to read, peer disconnected. shutting down connection." qDebug() << "No more data to read, peer disconnected. shutting down connection."
<< "bytesavail" << m_sock->bytesAvailable() << "bytesavail" << m_sock->bytesAvailable()
@@ -144,13 +144,13 @@ void
Connection::actualShutdown() Connection::actualShutdown()
{ {
qDebug() << Q_FUNC_INFO << m_actually_shutting_down << id(); qDebug() << Q_FUNC_INFO << m_actually_shutting_down << id();
if( m_actually_shutting_down ) if ( m_actually_shutting_down )
{ {
return; return;
} }
m_actually_shutting_down = true; m_actually_shutting_down = true;
if( !m_sock.isNull() && m_sock->isOpen() ) if ( !m_sock.isNull() && m_sock->isOpen() )
{ {
m_sock->disconnectFromHost(); m_sock->disconnectFromHost();
} }
@@ -261,7 +261,7 @@ Connection::doSetup()
void void
Connection::socketDisconnected() Connection::socketDisconnected()
{ {
qDebug() << "SOCKET DISCONNECTED" << this->name() << id() tDebug() << "SOCKET DISCONNECTED" << this->name() << id()
<< "shutdown will happen after incoming queue empties." << "shutdown will happen after incoming queue empties."
<< "bytesavail:" << m_sock->bytesAvailable() << "bytesavail:" << m_sock->bytesAvailable()
<< "bytesRecvd" << bytesReceived(); << "bytesRecvd" << bytesReceived();
@@ -276,14 +276,15 @@ Connection::socketDisconnected()
} }
} }
void void
Connection::socketDisconnectedError(QAbstractSocket::SocketError e) Connection::socketDisconnectedError( QAbstractSocket::SocketError e )
{ {
qDebug() << "SOCKET ERROR CODE" << e << this->name() << "CALLING Connection::shutdown(false)";
if ( e == QAbstractSocket::RemoteHostClosedError ) if ( e == QAbstractSocket::RemoteHostClosedError )
return; return;
qDebug() << "SOCKET ERROR CODE" << e << this->name() << "CALLING Connection::shutdown(false)";
m_peer_disconnected = true; m_peer_disconnected = true;
emit socketErrored(e); emit socketErrored(e);
@@ -423,16 +424,16 @@ Connection::sendMsg_now( msg_ptr msg )
{ {
//qDebug() << Q_FUNC_INFO << thread() << QThread::currentThread(); //qDebug() << Q_FUNC_INFO << thread() << QThread::currentThread();
Q_ASSERT( QThread::currentThread() == thread() ); Q_ASSERT( QThread::currentThread() == thread() );
Q_ASSERT( this->isRunning() ); // Q_ASSERT( this->isRunning() );
if( m_sock.isNull() || !m_sock->isOpen() || !m_sock->isWritable() ) if ( m_sock.isNull() || !m_sock->isOpen() || !m_sock->isWritable() )
{ {
qDebug() << "***** Socket problem, whilst in sendMsg(). Cleaning up. *****"; qDebug() << "***** Socket problem, whilst in sendMsg(). Cleaning up. *****";
shutdown( false ); shutdown( false );
return; return;
} }
if( ! msg->write( m_sock.data() ) ) if ( !msg->write( m_sock.data() ) )
{ {
//qDebug() << "Error writing to socket in sendMsg() *************"; //qDebug() << "Error writing to socket in sendMsg() *************";
shutdown( false ); shutdown( false );

View File

@@ -19,17 +19,17 @@
#ifndef CONNECTION_H #ifndef CONNECTION_H
#define CONNECTION_H #define CONNECTION_H
#include <QSharedPointer> #include <QtCore/QSharedPointer>
#include <QTcpSocket> #include <QtNetwork/QTcpSocket>
#include <QHostAddress> #include <QtNetwork/QHostAddress>
#include <QVariant> #include <QtCore/QVariant>
#include <QVariantMap> #include <QtCore/QVariantMap>
#include <QString> #include <QtCore/QString>
#include <QDataStream> #include <QtCore/QDataStream>
#include <QtEndian> #include <QtCore/QtEndian>
#include <QTimer> #include <QtCore/QTimer>
#include <QTime> #include <QtCore/QTime>
#include <QPointer> #include <QtCore/QPointer>
#include <qjson/parser.h> #include <qjson/parser.h>
#include <qjson/serializer.h> #include <qjson/serializer.h>
@@ -87,6 +87,8 @@ public:
void setMsgProcessorModeOut( quint32 m ) { m_msgprocessor_out.setMode( m ); } void setMsgProcessorModeOut( quint32 m ) { m_msgprocessor_out.setMode( m ); }
void setMsgProcessorModeIn( quint32 m ) { m_msgprocessor_in.setMode( m ); } void setMsgProcessorModeIn( quint32 m ) { m_msgprocessor_in.setMode( m ); }
const QHostAddress peerIpAddress() const { return m_peerIpAddress; }
signals: signals:
void ready(); void ready();
void failed(); void failed();
@@ -128,6 +130,7 @@ protected:
bool m_outbound, m_ready, m_onceonly; bool m_outbound, m_ready, m_onceonly;
msg_ptr m_firstmsg; msg_ptr m_firstmsg;
QString m_name; QString m_name;
QHostAddress m_peerIpAddress;
private: private:
void handleReadMsg(); void handleReadMsg();

View File

@@ -33,7 +33,7 @@
using namespace Tomahawk; using namespace Tomahawk;
ControlConnection::ControlConnection( Servent* parent ) ControlConnection::ControlConnection( Servent* parent, const QHostAddress &ha )
: Connection( parent ) : Connection( parent )
, m_dbsyncconn( 0 ) , m_dbsyncconn( 0 )
, m_registered( false ) , m_registered( false )
@@ -47,6 +47,38 @@ ControlConnection::ControlConnection( Servent* parent )
this->setMsgProcessorModeIn( MsgProcessor::UNCOMPRESS_ALL | MsgProcessor::PARSE_JSON ); this->setMsgProcessorModeIn( MsgProcessor::UNCOMPRESS_ALL | MsgProcessor::PARSE_JSON );
this->setMsgProcessorModeOut( MsgProcessor::COMPRESS_IF_LARGE ); this->setMsgProcessorModeOut( MsgProcessor::COMPRESS_IF_LARGE );
m_peerIpAddress = ha;
}
ControlConnection::ControlConnection( Servent* parent, const QString &ha )
: Connection( parent )
, m_dbsyncconn( 0 )
, m_registered( false )
, m_pingtimer( 0 )
{
qDebug() << "CTOR controlconnection";
setId("ControlConnection()");
// auto delete when connection closes:
connect( this, SIGNAL( finished() ), SLOT( deleteLater() ) );
this->setMsgProcessorModeIn( MsgProcessor::UNCOMPRESS_ALL | MsgProcessor::PARSE_JSON );
this->setMsgProcessorModeOut( MsgProcessor::COMPRESS_IF_LARGE );
if ( !ha.isEmpty() )
{
QHostAddress qha( ha );
if ( !qha.isNull() )
m_peerIpAddress = qha;
else
{
QHostInfo qhi = QHostInfo::fromName( ha );
if ( !qhi.addresses().isEmpty() )
m_peerIpAddress = qhi.addresses().first();
}
}
} }
@@ -72,7 +104,7 @@ ControlConnection::source() const
Connection* Connection*
ControlConnection::clone() ControlConnection::clone()
{ {
ControlConnection* clone = new ControlConnection( servent() ); ControlConnection* clone = new ControlConnection( servent(), m_peerIpAddress.toString() );
clone->setOnceOnly( onceOnly() ); clone->setOnceOnly( onceOnly() );
clone->setName( name() ); clone->setName( name() );
return clone; return clone;
@@ -102,6 +134,8 @@ ControlConnection::setup()
else else
friendlyName = name(); friendlyName = name();
tDebug() << "Detected name:" << name() << friendlyName << m_sock->peerAddress();
// setup source and remote collection for this peer // setup source and remote collection for this peer
m_source = SourceList::instance()->get( id(), friendlyName ); m_source = SourceList::instance()->get( id(), friendlyName );
m_source->setControlConnection( this ); m_source->setControlConnection( this );

View File

@@ -39,7 +39,8 @@ class DLLEXPORT ControlConnection : public Connection
Q_OBJECT Q_OBJECT
public: public:
explicit ControlConnection( Servent* parent = 0 ); explicit ControlConnection( Servent* parent = 0, const QHostAddress &ha = QHostAddress() );
explicit ControlConnection( Servent* parent = 0, const QString &ha = QString() );
~ControlConnection(); ~ControlConnection();
Connection* clone(); Connection* clone();

View File

@@ -39,10 +39,6 @@
#include "sourcelist.h" #include "sourcelist.h"
#include "utils/logger.h" #include "utils/logger.h"
// close the dbsync connection after this much inactivity.
// it's automatically reestablished as needed.
#define IDLE_TIMEOUT 300000
using namespace Tomahawk; using namespace Tomahawk;
@@ -52,11 +48,11 @@ DBSyncConnection::DBSyncConnection( Servent* s, const source_ptr& src )
, m_state( UNKNOWN ) , m_state( UNKNOWN )
{ {
qDebug() << Q_FUNC_INFO << src->id() << thread(); qDebug() << Q_FUNC_INFO << src->id() << thread();
connect( this, SIGNAL( stateChanged( DBSyncConnection::State, DBSyncConnection::State, QString ) ), connect( this, SIGNAL( stateChanged( DBSyncConnection::State, DBSyncConnection::State, QString ) ),
m_source.data(), SLOT( onStateChanged( DBSyncConnection::State, DBSyncConnection::State, QString ) ) ); m_source.data(), SLOT( onStateChanged( DBSyncConnection::State, DBSyncConnection::State, QString ) ) );
connect( m_source.data(), SIGNAL( commandsFinished() ),
m_timer.setInterval( IDLE_TIMEOUT ); this, SLOT( lastOpApplied() ) );
connect( &m_timer, SIGNAL( timeout() ), SLOT( idleTimeout() ) );
this->setMsgProcessorModeIn( MsgProcessor::PARSE_JSON | MsgProcessor::UNCOMPRESS_ALL ); this->setMsgProcessorModeIn( MsgProcessor::PARSE_JSON | MsgProcessor::UNCOMPRESS_ALL );
@@ -67,19 +63,11 @@ DBSyncConnection::DBSyncConnection( Servent* s, const source_ptr& src )
DBSyncConnection::~DBSyncConnection() DBSyncConnection::~DBSyncConnection()
{ {
qDebug() << "DTOR" << Q_FUNC_INFO; tDebug() << "DTOR" << Q_FUNC_INFO << m_source->id() << m_source->friendlyName();
m_state = SHUTDOWN; m_state = SHUTDOWN;
} }
void
DBSyncConnection::idleTimeout()
{
qDebug() << Q_FUNC_INFO;
shutdown( true );
}
void void
DBSyncConnection::changeState( State newstate ) DBSyncConnection::changeState( State newstate )
{ {
@@ -96,7 +84,6 @@ DBSyncConnection::changeState( State newstate )
void void
DBSyncConnection::setup() DBSyncConnection::setup()
{ {
// qDebug() << Q_FUNC_INFO;
setId( QString( "DBSyncConnection/%1" ).arg( socket()->peerAddress().toString() ) ); setId( QString( "DBSyncConnection/%1" ).arg( socket()->peerAddress().toString() ) );
check(); check();
} }
@@ -105,23 +92,19 @@ DBSyncConnection::setup()
void void
DBSyncConnection::trigger() DBSyncConnection::trigger()
{ {
// qDebug() << Q_FUNC_INFO;
// if we're still setting up the connection, do nothing - we sync on first connect anyway: // if we're still setting up the connection, do nothing - we sync on first connect anyway:
if ( !isRunning() ) if ( !isRunning() )
return; return;
QMetaObject::invokeMethod( this, "sendMsg", Qt::QueuedConnection, QMetaObject::invokeMethod( this, "sendMsg", Qt::QueuedConnection,
Q_ARG( msg_ptr, Q_ARG( msg_ptr, Msg::factory( "{\"method\":\"trigger\"}", Msg::JSON ) ) );
Msg::factory( "{\"method\":\"trigger\"}", Msg::JSON ) )
);
} }
void void
DBSyncConnection::check() DBSyncConnection::check()
{ {
qDebug() << Q_FUNC_INFO << m_source->id(); qDebug() << Q_FUNC_INFO << this << m_source->id();
if ( m_state != UNKNOWN && m_state != SYNCED ) if ( m_state != UNKNOWN && m_state != SYNCED )
{ {
qDebug() << "Syncing in progress already."; qDebug() << "Syncing in progress already.";
@@ -133,10 +116,7 @@ DBSyncConnection::check()
return; return;
} }
Q_ASSERT( m_cmds.isEmpty() );
m_uscache.clear(); m_uscache.clear();
m_us.clear();
changeState( CHECKING ); changeState( CHECKING );
// load last-modified etc data for our collection and theirs from our DB: // load last-modified etc data for our collection and theirs from our DB:
@@ -154,9 +134,6 @@ DBSyncConnection::check()
{ {
fetchOpsData( m_source->lastCmdGuid() ); fetchOpsData( m_source->lastCmdGuid() );
} }
// restarts idle countdown
m_timer.start();
} }
@@ -165,7 +142,7 @@ DBSyncConnection::check()
void void
DBSyncConnection::gotUs( const QVariantMap& m ) DBSyncConnection::gotUs( const QVariantMap& m )
{ {
m_us = m; Q_UNUSED( m )
if ( !m_uscache.empty() ) if ( !m_uscache.empty() )
sendOps(); sendOps();
} }
@@ -231,19 +208,16 @@ DBSyncConnection::handleMsg( msg_ptr msg )
if ( msg->is( Msg::DBOP ) ) if ( msg->is( Msg::DBOP ) )
{ {
DatabaseCommand* cmd = DatabaseCommand::factory( m, m_source ); DatabaseCommand* cmd = DatabaseCommand::factory( m, m_source );
if ( !cmd ) if ( cmd )
{ {
qDebug() << "UNKNOWN DBOP CMD"; QSharedPointer<DatabaseCommand> cmdsp = QSharedPointer<DatabaseCommand>(cmd);
return; m_source->addCommand( cmdsp );
} }
QSharedPointer<DatabaseCommand> cmdsp = QSharedPointer<DatabaseCommand>(cmd);
m_cmds << cmdsp;
if ( !msg->is( Msg::FRAGMENT ) ) // last msg in this batch if ( !msg->is( Msg::FRAGMENT ) ) // last msg in this batch
{ {
changeState( SAVING ); // just DB work left to complete changeState( SAVING ); // just DB work left to complete
executeCommands(); m_source->executeCommands();
} }
return; return;
} }
@@ -251,8 +225,7 @@ DBSyncConnection::handleMsg( msg_ptr msg )
if ( m.value( "method" ).toString() == "fetchops" ) if ( m.value( "method" ).toString() == "fetchops" )
{ {
m_uscache = m; m_uscache = m;
if ( !m_us.empty() ) sendOps();
sendOps();
return; return;
} }
@@ -269,23 +242,11 @@ DBSyncConnection::handleMsg( msg_ptr msg )
void void
DBSyncConnection::executeCommands() DBSyncConnection::lastOpApplied()
{ {
if ( !m_cmds.isEmpty() ) changeState( SYNCED );
{ // check again, until peer responds we have no new ops to process
QSharedPointer<DatabaseCommand> cmd = m_cmds.takeFirst(); check();
if ( !cmd->singletonCmd() )
m_source->setLastCmdGuid( cmd->guid() );
connect( cmd.data(), SIGNAL( finished() ), SLOT( executeCommands() ) );
Database::instance()->enqueue( cmd );
}
else
{
changeState( SYNCED );
// check again, until peer responds we have no new ops to process
check();
}
} }
@@ -298,8 +259,8 @@ DBSyncConnection::sendOps()
source_ptr src = SourceList::instance()->getLocal(); source_ptr src = SourceList::instance()->getLocal();
DatabaseCommand_loadOps* cmd = new DatabaseCommand_loadOps( src, m_uscache.value( "lastop" ).toString() ); DatabaseCommand_loadOps* cmd = new DatabaseCommand_loadOps( src, m_uscache.value( "lastop" ).toString() );
connect( cmd, SIGNAL( done( QString, QString, QList< dbop_ptr > ) ), connect( cmd, SIGNAL( done( QString, QString, QList< dbop_ptr > ) ),
SLOT( sendOpsData( QString, QString, QList< dbop_ptr > ) ) ); SLOT( sendOpsData( QString, QString, QList< dbop_ptr > ) ) );
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) ); Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
} }
@@ -314,6 +275,7 @@ DBSyncConnection::sendOpsData( QString sinceguid, QString lastguid, QList< dbop_
m_lastSentOp = lastguid; m_lastSentOp = lastguid;
if ( ops.length() == 0 ) if ( ops.length() == 0 )
{ {
tLog( LOGVERBOSE ) << "Sending ok" << m_source->id() << m_source->friendlyName();
sendMsg( Msg::factory( "ok", Msg::DBOP ) ); sendMsg( Msg::factory( "ok", Msg::DBOP ) );
return; return;
} }

Some files were not shown because too many files have changed in this diff Show More