diff --git a/data/images/new-releases.png b/data/images/new-releases.png
new file mode 100644
index 000000000..05252d24e
Binary files /dev/null and b/data/images/new-releases.png differ
diff --git a/data/images/share.png b/data/images/share.png
index c6db17530..7cd3e0023 100644
Binary files a/data/images/share.png and b/data/images/share.png differ
diff --git a/lang/tomahawk_bg.ts b/lang/tomahawk_bg.ts
index e36a5aa44..84556d15f 100644
--- a/lang/tomahawk_bg.ts
+++ b/lang/tomahawk_bg.ts
@@ -296,36 +296,41 @@ Remember: Only allow peers to connect if you trust who they are and if you have
+ social
+ социален
+
+
+
love
Харесай
-
+
Time
Продължителност
-
+
Time Left
Оставащо време
-
+
Shuffle
Разбъркано
-
+
Repeat
Повтори
-
+
Low
0
-
+
High
100%
@@ -680,6 +685,14 @@ Remember: Only allow peers to connect if you trust who they are and if you have
Създай нов списък
+
+ NewReleasesWidget
+
+
+ New Releases
+
+
+
PlaylistItemDelegate
@@ -972,7 +985,7 @@ Remember: Only allow peers to connect if you trust who they are and if you have
Failed to load: %1
- Неуспех при зареждане на %1
+ Не мога да заредя %1
@@ -1052,6 +1065,49 @@ Remember: Only allow peers to connect if you trust who they are and if you have
Най-изпълнявани песни, които нямаш в наличност
+
+ SocialWidget
+
+
+ Form
+ Бланка
+
+
+
+ Facebook
+ Facebook
+
+
+
+ Twitter
+ Twitter
+
+
+
+ Cover
+ Обложка
+
+
+
+ TextLabel
+ Етикет
+
+
+
+ Listening to "%1" by %2 and loving it! %4
+ <3 "%1" от %2 %4
+
+
+
+ Listening to "%1" by %2 on "%3" and loving it! %4
+ <3 "%1" от %2 от "%3" %4
+
+
+
+ %1 characters left
+ Остават още %1 символа
+
+
SourceDelegate
@@ -1265,6 +1321,11 @@ Remember: Only allow peers to connect if you trust who they are and if you have
+ New Releases
+
+
+
+
Friends
Приятели
@@ -1408,8 +1469,8 @@ Spotify e TM на Spotify Group.
- Allow web browsers to interact with Tomahawk
- Позволи на web браузъри да работят заедно с Tomahawk.
+ Allow web browsers to interact with Tomahawk (recommended)
+
@@ -1513,7 +1574,7 @@ Spotify e TM на Spotify Group.
Success
- Успех!
+ Ура!
@@ -1532,7 +1593,7 @@ Spotify e TM на Spotify Group.
Tomahawk::Accounts::TwitterAccountFactory
-
+
Connect to your Twitter followers.
Свържи се с твоите приятели в Twitter
@@ -1732,12 +1793,12 @@ You may wish to try re-authenticating.
&Continue Playback after this Track
-
+ &Продължи след тази песен
&Stop Playback after this Track
-
+ &Спри след тази песен
@@ -1813,7 +1874,7 @@ Please change the filters or try again.
Failed to generate preview with the desired filters
- Неуспех при генериране на предварителен преглед на избраните филтри.
+ Не мога да генерирам предварителен преглед на избраните филтри.
@@ -2123,7 +2184,7 @@ Try tweaking the filters for a new set of songs to play.
about %n minute(s) long
- около %n минути
+ около %n минутаоколо %n минути
@@ -2166,7 +2227,7 @@ Try tweaking the filters for a new set of songs to play.
Steer this station:
- Задръж тази станция:
+ Настройки:
@@ -2186,7 +2247,7 @@ Try tweaking the filters for a new set of songs to play.
Keep at current
- Задръж
+ Запази
@@ -2270,22 +2331,22 @@ Try tweaking the filters for a new set of songs to play.
Tomahawk::InfoSystem::ChartsPlugin
-
+
Top Overall
Най-известни
-
+
Artists
Артисти
-
+
Albums
Албуми
-
+
Tracks
Песни
@@ -2293,44 +2354,60 @@ Try tweaking the filters for a new set of songs to play.
Tomahawk::InfoSystem::FdoNotifyPlugin
-
+
Tomahawk is playing "%1" by %2%3.
-
+ Tomahawk възпроизвежда "%1" от %2%3
-
+
on "%1"
-
+ от "%1"
Tomahawk::InfoSystem::LastFmPlugin
-
+
Top Tracks
Най-актуални песни
-
+
Loved Tracks
Харесвани песни
-
+
Hyped Tracks
Песни слушани най-често
-
+
Top Artists
Най-слушани артисти
-
+
Hyped Artists
Артисти слушани най-често
+
+ Tomahawk::InfoSystem::NewReleasesPlugin
+
+
+ Albums
+
+
+
+
+ Tomahawk::InfoSystem::TwitterInfoPlugin
+
+
+ Listening to "%1" by %2 and loving it! %3
+ <3 "%1" от %2 %3
+
+
Tomahawk::ItunesParser
@@ -2349,7 +2426,7 @@ Try tweaking the filters for a new set of songs to play.
Failed to save tracks
- Неуспех при запаметяване на песни
+ Не мога да запазя избраните песни
@@ -2480,7 +2557,7 @@ Try tweaking the filters for a new set of songs to play.
TomahawkApp
-
+
My Collection
Моята колекция
@@ -2521,12 +2598,12 @@ enter the displayed PIN number here:
Play
-
+ Изпълни
Pause
-
+ Пауза
@@ -2534,7 +2611,7 @@ enter the displayed PIN number here:
Tomahawk
-
+ Tomahawk
@@ -2639,7 +2716,7 @@ enter the displayed PIN number here:
Ctrl+M
-
+ Ctrl+M
@@ -2649,7 +2726,7 @@ enter the displayed PIN number here:
Meta+Ctrl+Z
-
+ Mod+Ctrl+Z
@@ -2675,7 +2752,7 @@ enter the displayed PIN number here:
Space
-
+ Интервал
@@ -2733,7 +2810,7 @@ enter the displayed PIN number here:
Failed to save tracks
- Неуспех при запазване на списък с песни
+ Не мога да запазя списъкът с песни
@@ -3064,7 +3141,7 @@ enter the displayed PIN number here:
Status: No saved credentials
-
+ Статус: Няма запазени данни за вход
@@ -3126,17 +3203,17 @@ You can re-send a sync message at any time simply by sending another tweet using
ViewManager
-
+
SuperCollection
Супер колекция
-
+
Combined libraries of all your online friends
Комбинирани библиотеки от всичките ми приятели на линия
-
+
All available albums
Всички налични албуми
@@ -3405,107 +3482,107 @@ Lyrics for "%1" by %2:
XmppSipPlugin
-
+
User Interaction
Действие от потребителя
-
+
Host is unknown
Непознат адрес
-
+
Item not found
Обектът не е открит
-
+
Authorization Error
Грешка при даване на достъп
-
+
Remote Stream Error
Грешка в стриймът от отдалечената машина
-
+
Remote Connection failed
Отдалечената връзка е неуспешна
-
+
Internal Server Error
Вътрешна грешка на сървъра
-
+
System shutdown
Изключване на системата
-
+
Conflict
Конфликт
-
+
Unknown
-
+
No Compression Support
Няма поддръжка на компресия
-
+
No Encryption Support
Няма поддръжка на криптиране
-
+
No Authorization Support
Няма поддръжка на удостоверяване
-
+
No Supported Feature
-
+ Неподдържана функция
-
+
Add Friend
Добави приятел
-
+
Enter Xmpp ID:
Въведи Xmpp ID:
-
+
Add Friend...
Добави приятел...
-
+
XML Console...
XML Конзола...
-
+
I'm sorry -- I'm just an automatic presence used by Tomahawk Player (http://gettomahawk.com). If you are getting this message, the person you are trying to reach is probably not signed on, so please try again later!
Извинявай.. Аз съм режимът за автоматични отговори изпълзван от Tomahawk. ( http://gettomahawk.com ) Щом получаваш това съобщение, този с който се опитваш да се свържеш вероятно не е на линия. Моля, опитай отново по-късно.
-
+
Authorize User
Оправомощяване на потребител
-
+
Do you want to grant <b>%1</b> access to your Collection?
Искате ли да позволите на <b>%1</b> достъп до вашата колекция?
diff --git a/lang/tomahawk_de.ts b/lang/tomahawk_de.ts
index ef267e174..0fad17e4e 100644
--- a/lang/tomahawk_de.ts
+++ b/lang/tomahawk_de.ts
@@ -296,36 +296,41 @@ Denk dran: Erlaube das nur, wenn du dem Anderen vertraust und du die Rechte zum
+ social
+
+
+
+
love
Lieben
-
+
Time
Zeit
-
+
Time Left
Zeit verbleibend
-
+
Shuffle
Zufall
-
+
Repeat
Wiederholen
-
+
Low
Niedrig
-
+
High
Hoch
@@ -679,6 +684,14 @@ Denk dran: Erlaube das nur, wenn du dem Anderen vertraust und du die Rechte zum
Erstelle eine neue Playliste
+
+ NewReleasesWidget
+
+
+ New Releases
+
+
+
PlaylistItemDelegate
@@ -1051,6 +1064,49 @@ Denk dran: Erlaube das nur, wenn du dem Anderen vertraust und du die Rechte zum
Meist gehörte Lieder die du nicht kennst
+
+ SocialWidget
+
+
+ Form
+
+
+
+
+ Facebook
+
+
+
+
+ Twitter
+
+
+
+
+ Cover
+
+
+
+
+ TextLabel
+
+
+
+
+ Listening to "%1" by %2 and loving it! %4
+
+
+
+
+ Listening to "%1" by %2 on "%3" and loving it! %4
+
+
+
+
+ %1 characters left
+
+
+
SourceDelegate
@@ -1264,6 +1320,11 @@ Denk dran: Erlaube das nur, wenn du dem Anderen vertraust und du die Rechte zum
+ New Releases
+
+
+
+
Friends
Freunde
@@ -1403,8 +1464,8 @@ Denk dran: Erlaube das nur, wenn du dem Anderen vertraust und du die Rechte zum
- Allow web browsers to interact with Tomahawk
- Erlaube Webbrowsern mit Tomahawk zu interagieren
+ Allow web browsers to interact with Tomahawk (recommended)
+
@@ -1527,7 +1588,7 @@ Denk dran: Erlaube das nur, wenn du dem Anderen vertraust und du die Rechte zum
Tomahawk::Accounts::TwitterAccountFactory
-
+
Connect to your Twitter followers.
Verbinde dich zu deinen Twitter-Followern
@@ -2261,22 +2322,22 @@ Versuch die Filter anzupassen für neue Lieder.
Tomahawk::InfoSystem::ChartsPlugin
-
+
Top Overall
Top Allgemein
-
+
Artists
Künstler
-
+
Albums
Alben
-
+
Tracks
Stücke
@@ -2284,12 +2345,12 @@ Versuch die Filter anzupassen für neue Lieder.
Tomahawk::InfoSystem::FdoNotifyPlugin
-
+
Tomahawk is playing "%1" by %2%3.
-
+
on "%1"
@@ -2297,31 +2358,47 @@ Versuch die Filter anzupassen für neue Lieder.
Tomahawk::InfoSystem::LastFmPlugin
-
+
Top Tracks
Größte Hits
-
+
Loved Tracks
Lieblings Lieder
-
+
Hyped Tracks
Angesagte Stücke
-
+
Top Artists
-
+
Hyped Artists
+
+ Tomahawk::InfoSystem::NewReleasesPlugin
+
+
+ Albums
+
+
+
+
+ Tomahawk::InfoSystem::TwitterInfoPlugin
+
+
+ Listening to "%1" by %2 and loving it! %3
+
+
+
Tomahawk::ItunesParser
@@ -2471,7 +2548,7 @@ Versuch die Filter anzupassen für neue Lieder.
TomahawkApp
-
+
My Collection
Meine Sammlung
@@ -3108,17 +3185,17 @@ You can re-send a sync message at any time simply by sending another tweet using
ViewManager
-
+
SuperCollection
-
+
Combined libraries of all your online friends
-
+
All available albums
Alle verfügbaren Alben
@@ -3383,107 +3460,107 @@ Lyrics for "%1" by %2:
XmppSipPlugin
-
+
User Interaction
-
+
Host is unknown
-
+
Item not found
-
+
Authorization Error
-
+
Remote Stream Error
-
+
Remote Connection failed
-
+
Internal Server Error
-
+
System shutdown
-
+
Conflict
-
+
Unknown
-
+
No Compression Support
-
+
No Encryption Support
-
+
No Authorization Support
-
+
No Supported Feature
-
+
Add Friend
Freund hinzufügen...
-
+
Enter Xmpp ID:
XMPP-Benutzer:
-
+
Add Friend...
Freund hinzufügen...
-
+
XML Console...
XML-Konsole...
-
+
I'm sorry -- I'm just an automatic presence used by Tomahawk Player (http://gettomahawk.com). If you are getting this message, the person you are trying to reach is probably not signed on, so please try again later!
-
+
Authorize User
-
+
Do you want to grant <b>%1</b> access to your Collection?
Willst du <b>%1</b> Zugriff auf deine Sammlung gewähren?
diff --git a/lang/tomahawk_en.ts b/lang/tomahawk_en.ts
index f84149a1c..3eaf7eaea 100644
--- a/lang/tomahawk_en.ts
+++ b/lang/tomahawk_en.ts
@@ -296,36 +296,41 @@ Remember: Only allow peers to connect if you trust who they are and if you have
+ social
+ social
+
+
+
love
love
-
+
Time
Time
-
+
Time Left
Time Left
-
+
Shuffle
Shuffle
-
+
Repeat
Repeat
-
+
Low
Low
-
+
High
High
@@ -679,6 +684,14 @@ Remember: Only allow peers to connect if you trust who they are and if you have
Create a new playlist
+
+ NewReleasesWidget
+
+
+ New Releases
+ New Releases
+
+
PlaylistItemDelegate
@@ -1052,6 +1065,49 @@ Remember: Only allow peers to connect if you trust who they are and if you have
Most Played Tracks You Don't Have
+
+ SocialWidget
+
+
+ Form
+ Form
+
+
+
+ Facebook
+ Facebook
+
+
+
+ Twitter
+ Twitter
+
+
+
+ Cover
+ Cover
+
+
+
+ TextLabel
+ TextLabel
+
+
+
+ Listening to "%1" by %2 and loving it! %4
+ Listening to "%1" by %2 and loving it! %4
+
+
+
+ Listening to "%1" by %2 on "%3" and loving it! %4
+ Listening to "%1" by %2 on "%3" and loving it! %4
+
+
+
+ %1 characters left
+ %1 characters left
+
+
SourceDelegate
@@ -1265,6 +1321,11 @@ Remember: Only allow peers to connect if you trust who they are and if you have
+ New Releases
+ New Releases
+
+
+
Friends
Friends
@@ -1407,8 +1468,8 @@ Remember: Only allow peers to connect if you trust who they are and if you have
- Allow web browsers to interact with Tomahawk
- Allow web browsers to interact with Tomahawk
+ Allow web browsers to interact with Tomahawk (recommended)
+ Allow web browsers to interact with Tomahawk (recommended)
@@ -1531,7 +1592,7 @@ Remember: Only allow peers to connect if you trust who they are and if you have
Tomahawk::Accounts::TwitterAccountFactory
-
+
Connect to your Twitter followers.
Connect to your Twitter followers.
@@ -2268,22 +2329,22 @@ Try tweaking the filters for a new set of songs to play.
Tomahawk::InfoSystem::ChartsPlugin
-
+
Top Overall
Top Overall
-
+
Artists
Artists
-
+
Albums
Albums
-
+
Tracks
Tracks
@@ -2291,12 +2352,12 @@ Try tweaking the filters for a new set of songs to play.
Tomahawk::InfoSystem::FdoNotifyPlugin
-
+
Tomahawk is playing "%1" by %2%3.
Tomahawk is playing "%1" by %2%3.
-
+
on "%1"
on "%1"
@@ -2304,31 +2365,47 @@ Try tweaking the filters for a new set of songs to play.
Tomahawk::InfoSystem::LastFmPlugin
-
+
Top Tracks
Top Tracks
-
+
Loved Tracks
Loved Tracks
-
+
Hyped Tracks
Hyped Tracks
-
+
Top Artists
Top Artists
-
+
Hyped Artists
Hyped Artists
+
+ Tomahawk::InfoSystem::NewReleasesPlugin
+
+
+ Albums
+ Albums
+
+
+
+ Tomahawk::InfoSystem::TwitterInfoPlugin
+
+
+ Listening to "%1" by %2 and loving it! %3
+ Listening to "%1" by %2 and loving it! %3
+
+
Tomahawk::ItunesParser
@@ -2478,7 +2555,7 @@ Try tweaking the filters for a new set of songs to play.
TomahawkApp
-
+
My Collection
My Collection
@@ -3120,17 +3197,17 @@ You can re-send a sync message at any time simply by sending another tweet using
ViewManager
-
+
SuperCollection
SuperCollection
-
+
Combined libraries of all your online friends
Combined libraries of all your online friends
-
+
All available albums
All available albums
@@ -3405,107 +3482,107 @@ Lyrics for "%1" by %2:
XmppSipPlugin
-
+
User Interaction
User Interaction
-
+
Host is unknown
Host is unknown
-
+
Item not found
Item not found
-
+
Authorization Error
Authorization Error
-
+
Remote Stream Error
Remote Stream Error
-
+
Remote Connection failed
Remote Connection failed
-
+
Internal Server Error
Internal Server Error
-
+
System shutdown
System shutdown
-
+
Conflict
Conflict
-
+
Unknown
Unknown
-
+
No Compression Support
No Compression Support
-
+
No Encryption Support
No Encryption Support
-
+
No Authorization Support
No Authorization Support
-
+
No Supported Feature
No Supported Feature
-
+
Add Friend
Add Friend
-
+
Enter Xmpp ID:
Enter Xmpp ID:
-
+
Add Friend...
Add Friend...
-
+
XML Console...
XML Console...
-
+
I'm sorry -- I'm just an automatic presence used by Tomahawk Player (http://gettomahawk.com). If you are getting this message, the person you are trying to reach is probably not signed on, so please try again later!
I'm sorry -- I'm just an automatic presence used by Tomahawk Player (http://gettomahawk.com). If you are getting this message, the person you are trying to reach is probably not signed on, so please try again later!
-
+
Authorize User
Authorize User
-
+
Do you want to grant <b>%1</b> access to your Collection?
Do you want to grant <b>%1</b> access to your Collection?
diff --git a/lang/tomahawk_es.ts b/lang/tomahawk_es.ts
index 74aa6b86b..bf8599e69 100644
--- a/lang/tomahawk_es.ts
+++ b/lang/tomahawk_es.ts
@@ -294,36 +294,41 @@ Remember: Only allow peers to connect if you trust who they are and if you have
+ social
+
+
+
+
love
favorita
-
+
Time
Duración
-
+
Time Left
Tiempo restante
-
+
Shuffle
Aleatorio
-
+
Repeat
Repetir
-
+
Low
Bajar volumen
-
+
High
Subir volumen
@@ -677,6 +682,14 @@ Remember: Only allow peers to connect if you trust who they are and if you have
Crear una nueva lista de reproducción
+
+ NewReleasesWidget
+
+
+ New Releases
+
+
+
PlaylistItemDelegate
@@ -1049,6 +1062,49 @@ Remember: Only allow peers to connect if you trust who they are and if you have
Pistas más reproducidas no disponibles
+
+ SocialWidget
+
+
+ Form
+
+
+
+
+ Facebook
+
+
+
+
+ Twitter
+
+
+
+
+ Cover
+
+
+
+
+ TextLabel
+
+
+
+
+ Listening to "%1" by %2 and loving it! %4
+
+
+
+
+ Listening to "%1" by %2 on "%3" and loving it! %4
+
+
+
+
+ %1 characters left
+
+
+
SourceDelegate
@@ -1262,6 +1318,11 @@ Remember: Only allow peers to connect if you trust who they are and if you have
+ New Releases
+
+
+
+
Friends
@@ -1404,7 +1465,7 @@ y estaciones basadas en sus gustos personales.
- Allow web browsers to interact with Tomahawk
+ Allow web browsers to interact with Tomahawk (recommended)
@@ -1528,7 +1589,7 @@ y estaciones basadas en sus gustos personales.
Tomahawk::Accounts::TwitterAccountFactory
-
+
Connect to your Twitter followers.
@@ -2260,22 +2321,22 @@ Try tweaking the filters for a new set of songs to play.
Tomahawk::InfoSystem::ChartsPlugin
-
+
Top Overall
Top total
-
+
Artists
Artistas
-
+
Albums
Álbumes
-
+
Tracks
Pistas
@@ -2283,12 +2344,12 @@ Try tweaking the filters for a new set of songs to play.
Tomahawk::InfoSystem::FdoNotifyPlugin
-
+
Tomahawk is playing "%1" by %2%3.
-
+
on "%1"
@@ -2296,31 +2357,47 @@ Try tweaking the filters for a new set of songs to play.
Tomahawk::InfoSystem::LastFmPlugin
-
+
Top Tracks
Pistas más escuchadas
-
+
Loved Tracks
Pistas favoritas
-
+
Hyped Tracks
Pistas en alza
-
+
Top Artists
Artistas más escuchados
-
+
Hyped Artists
Artistas en alza
+
+ Tomahawk::InfoSystem::NewReleasesPlugin
+
+
+ Albums
+
+
+
+
+ Tomahawk::InfoSystem::TwitterInfoPlugin
+
+
+ Listening to "%1" by %2 and loving it! %3
+
+
+
Tomahawk::ItunesParser
@@ -2470,7 +2547,7 @@ Try tweaking the filters for a new set of songs to play.
TomahawkApp
-
+
My Collection
Mi colección
@@ -3112,17 +3189,17 @@ Puede reenviar el mensaje de sincronización en cualquier momento simplemente en
ViewManager
-
+
SuperCollection
-
+
Combined libraries of all your online friends
-
+
All available albums
Todos los álbumes disponibles
@@ -3396,107 +3473,107 @@ Letras de "%1" por %2:
XmppSipPlugin
-
+
User Interaction
-
+
Host is unknown
-
+
Item not found
-
+
Authorization Error
-
+
Remote Stream Error
-
+
Remote Connection failed
-
+
Internal Server Error
-
+
System shutdown
-
+
Conflict
-
+
Unknown
-
+
No Compression Support
-
+
No Encryption Support
-
+
No Authorization Support
-
+
No Supported Feature
-
+
Add Friend
-
+
Enter Xmpp ID:
-
+
Add Friend...
-
+
XML Console...
-
+
I'm sorry -- I'm just an automatic presence used by Tomahawk Player (http://gettomahawk.com). If you are getting this message, the person you are trying to reach is probably not signed on, so please try again later!
-
+
Authorize User
-
+
Do you want to grant <b>%1</b> access to your Collection?
diff --git a/lang/tomahawk_fr.ts b/lang/tomahawk_fr.ts
new file mode 100644
index 000000000..2912e70ee
--- /dev/null
+++ b/lang/tomahawk_fr.ts
@@ -0,0 +1,3591 @@
+
+
+ ACLRegistry
+
+
+ Connect to Peer?
+ Se connecter ?
+
+
+
+ Another Tomahawk instance that claims to be owned by %1 is attempting to connect to you. Select whether to allow or deny this connection.
+
+Remember: Only allow peers to connect if you trust who they are and if you have the legal right for them to stream music from you.
+ Une autre instance de Tomahawk qui dit appartenir à %1 essaie de se connecter. Voulez vous accepter ou interdire cette connexion ?
+
+Note : N'autorisez à se connecter que les personnes en qui vous avez confiance et qui ont le droit de streamer votre musique.
+
+
+
+ Deny
+ Interdire
+
+
+
+ Allow
+ Accepter
+
+
+
+ AccountFactoryWrapper
+
+
+ Dialog
+ Dialog
+
+
+
+ Description goes here
+ ici la description
+
+
+
+ Add Account
+ Ajouter un compte
+
+
+
+ AccountFactoryWrapperDelegate
+
+
+ Online
+ En Ligne
+
+
+
+ Connecting...
+ Connexion en cours...
+
+
+
+ Offline
+ Hors ligne
+
+
+
+ ActionCollection
+
+
+ &Listen Along
+ &Ecouter avec
+
+
+
+ Stop &Listening Along
+ Arrêter d'&écouter avec
+
+
+
+ &Follow in real-time
+ &Suivre en temps réel
+
+
+
+
+ &Listen Privately
+ &Ecouter en privé
+
+
+
+
+ &Listen Publicly
+ &Ecouter publiquement
+
+
+
+ &Load Playlist
+ &Charger une liste de lecture
+
+
+
+ &Rename Playlist
+ &Renommer la liste de lecture
+
+
+
+ &Copy Playlist Link
+ &Copier le lien de la piste de lecture
+
+
+
+ &Play
+ &Lire
+
+
+
+ &Stop
+ &Stop
+
+
+
+ &Previous Track
+ Piste &Précédente
+
+
+
+ &Next Track
+ Piste &Suivante
+
+
+
+ &Quit
+ &Quitter
+
+
+
+ AlbumInfoWidget
+
+
+ Form
+ Form
+
+
+
+ Other Albums by Artist
+ Tous les albums par cet artiste
+
+
+
+
+ Click to show Official Tracks
+ Cliquer pour afficher les pistes officielles
+
+
+
+
+ Click to show SuperCollection Tracks
+ Cliquer pour afficher les pistes de la SuperCollectio,
+
+
+
+
+ Click to show SuperCollection Albums
+ Cliquer pour afficher les albums de la SuperCollection
+
+
+
+ Click to show Official Albums
+ Cliquer pour afficher les albums officiels
+
+
+
+ Other Albums by %1
+ Autres albums par %1
+
+
+
+ AlbumModel
+
+
+ Album
+ Album
+
+
+
+
+ All albums from %1
+ Tous les albums de %1
+
+
+
+ All albums
+ Tous les albums
+
+
+
+ AlbumView
+
+
+ After you have scanned your music collection you will find your latest album additions right here.
+ Après avoir scanné votre collection musicale, vous trouverez les derniers albums ajoutés ici.
+
+
+
+ This collection doesn't have any recent albums.
+ Cette collection n'a pas d'albums récents
+
+
+
+ ArtistInfoWidget
+
+
+ Form
+ Form
+
+
+
+ Top Hits
+ Top Hits
+
+
+
+ Related Artists
+ Artistes similaires
+
+
+
+ Albums
+ Albums
+
+
+
+
+ Click to show SuperCollection Albums
+ Cliquer pour afficher les albums de la SuperCollection
+
+
+
+ Click to show Official Albums
+ Cliquer pour afficher les albums officiels
+
+
+
+ ArtistView
+
+
+ After you have scanned your music collection you will find your tracks right here.
+ Après avoir scanné votre collection musicale, vous trouverez vos pistes ici.
+
+
+
+ This collection is currently empty.
+ La collection est vide actuellement.
+
+
+
+ Sorry, your filter '%1' did not match any results.
+ Désolé, votre filtre '%1' ne correspond à aucun résultat
+
+
+
+ AudioControls
+
+
+ Prev
+ Précédent
+
+
+
+ Play
+ Lecture
+
+
+
+ Pause
+ Pause
+
+
+
+ Next
+ Suivant
+
+
+
+ Artist
+ Artiste
+
+
+
+ Album
+ Album
+
+
+
+ Owner
+ Propriétaire
+
+
+
+ social
+
+
+
+
+ love
+ love
+
+
+
+ Time
+ Durée
+
+
+
+ Time Left
+ Durée restante
+
+
+
+ Shuffle
+ Lecture Aléatoire
+
+
+
+ Repeat
+ Répéter
+
+
+
+ Low
+ Bas
+
+
+
+ High
+ Haut
+
+
+
+ CategoryAddItem
+
+
+
+ New Playlist
+ Nouvelle liste de lecture
+
+
+
+
+
+
+ New Station
+ Nouvelle Station
+
+
+
+
+
+ %1 Station
+ Station %1
+
+
+
+ CategoryItem
+
+
+ Playlists
+ Listes de lecture
+
+
+
+ Stations
+ Stations
+
+
+
+ ClearButton
+
+
+ Clear
+ Vider
+
+
+
+ CollectionFlatModel
+
+
+ My Collection
+ Ma Collection
+
+
+
+ Collection of %1
+ Collection de %1
+
+
+
+ CollectionView
+
+
+ This collection is empty.
+ La collection est vide.
+
+
+
+ ContextWidget
+
+
+ InfoBar
+ Barre d'information
+
+
+
+
+ Show Footnotes
+ Afficher les notes
+
+
+
+ Hide Footnotes
+ Masquer les notes
+
+
+
+ CrashReporter
+
+
+ Tomahawk Crash Reporter
+ Tomahawk Crash Reporter
+
+
+
+ <p><b>Sorry!</b> Tomahawk crashed. Information about the crash is now being sent to Tomahawk HQ so that we can fix the bug.</p>
+ <p><b>Désolé !</b> Tomahawk a planté. Les informations du plantage sont maintenant envoyés au siège de Tomahawk pour que nous puissions corriger le bug.</p>
+
+
+
+ Abort
+ Abandonner
+
+
+
+ You can disable sending crash reports in the configuration dialog.
+ Vous pouvez désactiver l'envoi des rapports de plantage dans la boite de dialogue de configuration.
+
+
+
+ Uploaded %L1 of %L2 KB.
+ Chargement %L1 de %L2 ko.
+
+
+
+
+ Close
+ Fermer
+
+
+
+ Sent! <b>Many thanks</b>.
+ Envoyé ! <b>Merci beaucoup</b>.
+
+
+
+ Failed to send crash info.
+ Échec de l'envoi des informations de plantage
+
+
+
+ DatabaseCommand_AllAlbums
+
+
+ Unknown
+ Inconnu
+
+
+
+ DelegateConfigWrapper
+
+
+ Delete Account
+ Supprimer le compte
+
+
+
+ DiagnosticsDialog
+
+
+ Tomahawk Diagnostics
+ Diagnostics de Tomahawk
+
+
+
+ Update
+ Mettre à jour
+
+
+
+ Copy to Clipboard
+ Copier dans le presse papier
+
+
+
+ DropJob
+
+
+ No tracks found for given %1
+ Aucune piste trouvée pour %1
+
+
+
+ GlobalSearchWidget
+
+
+ Form
+ Form
+
+
+
+ IndexingJobItem
+
+
+ Indexing database
+ Indexation de la base de données
+
+
+
+ InfoBar
+
+
+ InfoBar
+ Barre d'information
+
+
+
+ Automatically update
+
+
+
+
+ Filter...
+ Filtre...
+
+
+
+ JobStatusView
+
+
+ Searching For
+ Recherche de
+
+
+
+ Pending
+
+
+
+
+ Idle
+
+
+
+
+ LastFmConfig
+
+
+ Form
+ Form
+
+
+
+ Scrobble tracks to Last.fm
+ Scrobbler les pistes sur Last.fm
+
+
+
+ Username:
+ Nom d'utilisateur :
+
+
+
+ Password:
+ Mot de passe :
+
+
+
+ Test Login
+
+
+
+
+ LastfmContext
+
+
+ Last.fm
+ Last.fm
+
+
+
+ LatchedStatusItem
+
+
+ %1 is listening along to you!
+ %1 écoute avec vous
+
+
+
+ LoadXSPF
+
+
+ Load XSPF
+ Charger XSPF
+
+
+
+ Playlist URL
+ URL de la liste de lecture
+
+
+
+ Enter URL...
+ Saisir une URL...
+
+
+
+ ...
+ ...
+
+
+
+ Automatically update
+
+
+
+
+ LoadXSPFDialog
+
+
+ Load XSPF File
+ Charger un fichier XSPF
+
+
+
+ XSPF Files (*.xspf)
+ Fichiers XSPF (*.xspf)
+
+
+
+ LocalCollection
+
+
+ Bookmarks
+
+
+
+
+ Saved tracks
+ Pistes sauvegardés
+
+
+
+ NewPlaylistWidget
+
+
+ Enter a title for the new playlist:
+ Entrer un titre pour la nouvelle liste de lecture
+
+
+
+ Tomahawk offers a variety of ways to help you create playlists and find music you enjoy!
+ Tomahawk offre plusieurs façons de créer des listes de lecture et de trouver la musique que vous aimerez !
+
+
+
+ Just enter a genre or tag name and Tomahawk will suggest a few songs to get you started with your new playlist:
+ Entrez un genre ou un tag et Tomahawk vous suggérera quelques morceaux pour commencer votre nouvelle liste de lecture :
+
+
+
+ &Create Playlist
+ &Créer une liste de lecture
+
+
+
+ Create a new playlist
+ Créer une nouvelle liste de lecture
+
+
+
+ NewReleasesWidget
+
+
+ New Releases
+
+
+
+
+ PlaylistItemDelegate
+
+
+ played %1 by you
+ joué %1 par vous
+
+
+
+ played %1 by %2
+ joué %1 par %2
+
+
+
+ PlaylistLargeItemDelegate
+
+
+ played %1 by you
+ joué %1 par vous
+
+
+
+ played %1 by %2
+ joué %1 par %2
+
+
+
+ added %1
+
+
+
+
+ PlaylistModel
+
+
+ A playlist by %1, created %2
+ Une liste de lecture par %1, créée %2
+
+
+
+ you
+ vous
+
+
+
+ All tracks by %1 on album %2
+ Toutes les pistes par %1 sur l'album %2
+
+
+
+ All tracks by %1
+ Toutes les pistes par %1
+
+
+
+ PlaylistTypeSelectorDlg
+
+
+ New Playlist
+ Nouvelle liste de lecture
+
+
+
+ Just a regular old playlist... Give it a name, drag in some tracks, and go!
+ Juste une liste de lecture normale... Donnez lui un nom, faites glisser quelques pistes et c'est parti !
+
+
+
+ Don't know exactly what you want? Give Tomahawk a few pointers and let it build a playlist for you!
+ Vous ne savez pas ce que vous voulez exactement ? Donnez quelques idées à Tomahawk et laissez le créer une liste de lecture pour vous.
+
+
+
+ Name:
+ Nom :
+
+
+
+ New Playlist...
+ Nouvelle liste de lecture...
+
+
+
+ Create Manual Playlist
+ Créer une liste de lecture manuellement
+
+
+
+ Create Automatic Playlist
+ Créer une liste de lecture automatiquement
+
+
+
+ PlaylistView
+
+
+ This playlist is currently empty. Add some tracks to it and enjoy the music!
+ La liste de lecture est vide. Ajoutez des pistes et profitez de la musique !
+
+
+
+ ProxyDialog
+
+
+ Proxy Settings
+ Paramètres de proxy
+
+
+
+ Hostname of proxy server
+ Nom d'hôte du serveur proxy
+
+
+
+ Host
+ Hôte
+
+
+
+ Port
+ Port
+
+
+
+ Proxy login
+ Login du proxy
+
+
+
+ User
+ Utilisateur
+
+
+
+ Password
+ Mot de passe
+
+
+
+ Proxy password
+ Mot de passe du proxy
+
+
+
+ Type
+ Type
+
+
+
+ No Proxy Hosts:
+(Overrides system proxy)
+ Pas de proxy pour :
+(remplace les paramètres système)
+
+
+
+ localhost *.example.com (space separated)
+ localhost *.example.com (séparé par espace)
+
+
+
+ Use proxy for DNS lookups?
+ Utiliser le proxy pour les requêtes DNS ?
+
+
+
+ QObject
+
+
+ %n year(s) ago
+ il y a %n anil y a %n ans
+
+
+
+ %n year(s)
+ %n an%n ans
+
+
+
+ %n month(s) ago
+ il y a %n moisil y a %n mois
+
+
+
+ %n month(s)
+ %n mois%n mois
+
+
+
+ %n week(s) ago
+ il y a %n semaineil y a %n semaines
+
+
+
+ %n week(s)
+ %n semaine%n semaines
+
+
+
+ %n day(s) ago
+ il y a %n jouril y a %n jours
+
+
+
+ %n day(s)
+ %n jour%n jours
+
+
+
+ %n hour(s) ago
+ il y a %n heureil y a %n heures
+
+
+
+ %n hour(s)
+ %n heure%n heures
+
+
+
+ %1 minutes ago
+ il y a %1 minutes
+
+
+
+ %1 minutes
+ %1 minutes
+
+
+
+ just now
+ à l'instant
+
+
+
+ Friend Finders
+
+
+
+
+ Music Finders
+
+
+
+
+ Status Updaters
+
+
+
+
+ QuaZipFilePrivate
+
+
+ ZIP/UNZIP API error %1
+
+
+
+
+ QueueView
+
+
+ InfoBar
+ Barre d'information
+
+
+
+
+ Show Queue
+
+
+
+
+ Hide Queue
+
+
+
+
+ RelatedArtistsContext
+
+
+ Related Artists
+
+
+
+
+ ResolverConfigDelegate
+
+
+ Not found: %1
+
+
+
+
+ Failed to load: %1
+
+
+
+
+ SearchLineEdit
+
+
+ Search
+
+
+
+
+ SearchWidget
+
+
+ Search: %1
+
+
+
+
+ Results for '%1'
+
+
+
+
+ SettingsDialog
+
+
+ Collection
+ Collection
+
+
+
+ Advanced
+ Avancés
+
+
+
+ All
+
+
+
+
+ Services
+
+
+
+
+ Install resolver from file
+
+
+
+
+ Information
+
+
+
+
+ Changing this setting requires a restart of Tomahawk!
+
+
+
+
+ SocialPlaylistWidget
+
+
+ Popular New Albums From Your Friends
+ Nouveaux Albums Populaires de vos Amis
+
+
+
+ Most Played Playlists
+ Liste de lecture les plus jouées
+
+
+
+ Most Played Tracks You Don't Have
+ Pistes les plus joués que vous n'avez pas
+
+
+
+ SocialWidget
+
+
+ Form
+ Form
+
+
+
+ Facebook
+ Facebook
+
+
+
+ Twitter
+ Twitter
+
+
+
+ Cover
+
+
+
+
+ TextLabel
+ TextLabel
+
+
+
+ Listening to "%1" by %2 and loving it! %4
+ J'écoute "%1" par %2 et j'adore ! %4
+
+
+
+ Listening to "%1" by %2 on "%3" and loving it! %4
+ J'écoute "%1" par %2 sur "%3" et j'adore ! %4
+
+
+
+ %1 characters left
+ %1 caractères restants
+
+
+
+ SourceDelegate
+
+
+ Track
+ Piste
+
+
+
+ Album
+ Album
+
+
+
+ Artist
+ Artiste
+
+
+
+ Local
+ Local
+
+
+
+ Top 10
+ Top 10
+
+
+
+ Offline
+ Hors ligne
+
+
+
+ All available tracks
+ Toutes les pistes disponibles
+
+
+
+ Online
+ En Ligne
+
+
+
+
+ Show
+ Afficher
+
+
+
+
+ Hide
+ Masquer
+
+
+
+ SourceInfoWidget
+
+
+ Recent Albums
+ Derniers Albums
+
+
+
+ Latest Additions
+ Derniers ajouts
+
+
+
+ Recently Played Tracks
+ Dernières pistes jouées
+
+
+
+ New Additions
+ Nouveaux ajouts
+
+
+
+ My recent activity
+ Mon activité récente
+
+
+
+ Recent activity from %1
+ Activité récente de %1
+
+
+
+ SourceItem
+
+
+ Collection
+ Collection
+
+
+
+ Latest Additions
+ Derniers ajouts
+
+
+
+ Recently Played
+ Joués récemment
+
+
+
+ Loved Tracks
+
+
+
+
+ SuperCollection
+ SuperCollection
+
+
+
+ SourceTreeView
+
+
+ &Copy Link
+ &Copier le lien
+
+
+
+ &Delete %1
+ &Supprimer %1
+
+
+
+ &Export Playlist
+ &Exporter la liste de lecture
+
+
+
+ Save XSPF
+ Enregistrer XSPF
+
+
+
+ Playlists (*.xspf)
+ Listes de lecture (*.xspf)
+
+
+
+ SourcesModel
+
+
+ Group
+ Groupe
+
+
+
+ Collection
+ Collection
+
+
+
+ Playlist
+ Liste de lecture
+
+
+
+ Automatic Playlist
+ Liste de lecture automatique
+
+
+
+ Station
+ Station
+
+
+
+ Browse
+ Parcourir
+
+
+
+ Search History
+
+
+
+
+ My Music
+ Ma Musique
+
+
+
+ SuperCollection
+ SuperCollection
+
+
+
+ Top Loved Tracks
+
+
+
+
+ Dashboard
+ Tableau de bord
+
+
+
+ Recently Played
+ Joués récemment
+
+
+
+ Charts
+
+
+
+
+ New Releases
+
+
+
+
+ Friends
+ Amis
+
+
+
+ SpotifyConfig
+
+
+ Form
+
+
+
+
+ Configure your Spotify credentials
+
+
+
+
+ Username:
+ Nom d'utilisateur :
+
+
+
+ placeholderUsername
+ placeholderUsername
+
+
+
+ Password:
+
+
+
+
+ placeholderPw
+
+
+
+
+ High Quality Streaming
+
+
+
+
+ This product uses SPOTIFY(R) CORE but is not endorsed, certified or otherwise approved in any way by Spotify. Spotify is the registered trade mark of the Spotify Group.
+
+
+
+
+ StackedSettingsDialog
+
+
+ Tomahawk Settings
+
+
+
+
+ Local Music Information
+
+
+
+
+ Path to scan for music files:
+ Chemin à scanner pour des fichiers musicaux :
+
+
+
+ The Echo Nest supports keeping track of your catalog metadata
+ and using it to craft personalized radios. Enabling this option
+ will allow you (and all your friends) to create automatic playlists
+ and stations based on your personal taste profile.
+ The Echo Nest peut garder les métadonnées de votre catalogue
+et l'utiliser pour créer des radios personnalisées. En activant cette option
+vous (et vos amis) pourrez créer des listes de lecture automatiquement
+et des stations basés sur vos goûts.
+
+
+
+ Upload collection list to The Echo Nest to enable user radio
+ Envoyer la collection à The Echo Nest pour activer la radio utilisateur
+
+
+
+ Watch for changes
+
+
+
+
+ Time between scans, in seconds:
+ Période de scan, en secondes :
+
+
+
+ Internet Services
+
+
+
+
+ Install from file...
+
+
+
+
+ Filter by capability:
+
+
+
+
+ Advanced Network Settings
+ Paramètres réseaux avancés
+
+
+
+ If you're having difficulty connecting to peers, try setting this to your external IP address/host name and a port number (default 50210). Make sure to forward that port to this machine!
+ Si vous rencontrez des difficultés à vous connecter, essayez de saisir ici votre adresse IP externe et un port (défaut 50210). Vérifiez que vous redirigez ce port vers cette machine !
+
+
+
+ Static Host Name:
+ Nom d'hôte statique :
+
+
+
+ Static Port:
+
+
+
+
+ Always use static host name/port? (Overrides UPnP discovery/port forwarding)
+ Toujours utiliser un nom d'hôte/port statique? (remplace la découverte UPnP/le transfer de port)
+
+
+
+ Proxy Settings...
+
+
+
+
+ Send reports after Tomahawk crashed
+
+
+
+
+ Allow web browsers to interact with Tomahawk (recommended)
+
+
+
+
+ Use UPnP to establish port forward
+
+
+
+
+ Tomahawk::Accounts::AccountDelegate
+
+
+ Add Account
+ Ajouter un compte
+
+
+
+ Remove Account
+ Supprimer le compte
+
+
+
+ %1 downloads
+
+
+
+
+ Online
+ En Ligne
+
+
+
+ Connecting...
+ Connexion en cours...
+
+
+
+ Offline
+ Hors ligne
+
+
+
+ Tomahawk::Accounts::GoogleWrapper
+
+
+ Configure this Google Account
+ Configurer le compte Google
+
+
+
+ Google Address
+ Adresse Google
+
+
+
+ Enter your Google login to connect with your friends using Tomahawk!
+ Entrer votre login Google pour vous connecter avec vos amis qui utilisent Tomahawk !
+
+
+
+ username@gmail.com
+ utilisateur@gmail.com
+
+
+
+ Tomahawk::Accounts::GoogleWrapperFactory
+
+
+ Connect to Google Talk to find your friends
+ Connectez vous à Google Talk pour trouver vos amis
+
+
+
+ Tomahawk::Accounts::GoogleWrapperSip
+
+
+ Add Friend
+
+
+
+
+ Enter Google Address:
+
+
+
+
+ Tomahawk::Accounts::LastFmAccountFactory
+
+
+ Scrobble your tracks to last.fm, and find freely downloadable tracks to play
+ Scrobbler vos écoutes sur Last.fm et trouver des morceaux téléchargeables gratuitement
+
+
+
+ Tomahawk::Accounts::LastFmConfig
+
+
+
+ Failed
+ Échec
+
+
+
+ Success
+ Succès
+
+
+
+ Could not contact server
+ Impossible de contacter le serveur
+
+
+
+ Tomahawk::Accounts::SpotifyAccountFactory
+
+
+ Play music from and sync your playlists with Spotify Premium
+ Jouer la musique et synchroniser vos listes avec Spotify Premium
+
+
+
+ Tomahawk::Accounts::TwitterAccountFactory
+
+
+ Connect to your Twitter followers.
+
+
+
+
+ Tomahawk::Accounts::TwitterConfigWidget
+
+
+
+
+ Tweet!
+ Tweet!
+
+
+
+
+ Status: No saved credentials
+
+
+
+
+
+
+ Authenticate
+
+
+
+
+
+ Status: Credentials saved for %1
+
+
+
+
+
+ De-authenticate
+
+
+
+
+
+
+
+
+
+
+ Tweetin' Error
+
+
+
+
+ The credentials could not be verified.
+You may wish to try re-authenticating.
+
+
+
+
+ Status: Error validating credentials
+
+
+
+
+ Global Tweet
+ Tweet Global
+
+
+
+ Direct Message
+
+
+
+
+ Send Message!
+
+
+
+
+ @Mention
+
+
+
+
+ Send Mention!
+
+
+
+
+ You must enter a user name for this type of tweet.
+ Vous devez saisir un nom d'utilisateur pour ce type de tweet.
+
+
+
+ Your saved credentials could not be loaded.
+You may wish to try re-authenticating.
+
+
+
+
+ Your saved credentials could not be verified.
+You may wish to try re-authenticating.
+
+
+
+
+
+ There was an error posting your status -- sorry!
+
+
+
+
+
+ Tweeted!
+
+
+
+
+ Your tweet has been posted!
+
+
+
+
+ There was an error posting your direct message -- sorry!
+
+
+
+
+ Your message has been posted!
+
+
+
+
+ Tomahawk::Accounts::XmppAccountFactory
+
+
+ Log on to your Jabber/XMPP account to connect to your friends
+ Connectez vous à votre compte Jabber/XMPP pour vous connecter avec vos amis
+
+
+
+ Tomahawk::Accounts::ZeroconfFactory
+
+
+ Automatically connect to Tomahawks on the local network
+ Se connecter automatiquement aux Tomahawks sur le réseau local
+
+
+
+ Tomahawk::ContextMenu
+
+
+ &Play
+
+
+
+
+
+
+ Add to &Queue
+
+
+
+
+
+ &Love
+
+
+
+
+ &Copy Track Link
+ &Copier le lien de la piste
+
+
+
+ Show &Album page
+ Afficher la page de l'&album
+
+
+
+ Show &Artist page
+
+
+
+
+ Un-&Love
+
+
+
+
+ &Delete Items
+
+
+
+
+ &Continue Playback after this Track
+ &Continuer la lecture après cette piste
+
+
+
+ &Stop Playback after this Track
+ &Stopper la lecture après cette piste
+
+
+
+ &Delete Item
+
+
+
+
+ Tomahawk::CustomPlaylistView
+
+
+ Top Loved Tracks
+
+
+
+
+ Your loved tracks
+
+
+
+
+ %1's loved tracks
+
+
+
+
+ The most loved tracks from all your friends
+
+
+
+
+ All of your loved tracks
+
+
+
+
+ All of %1's loved tracks
+
+
+
+
+ Tomahawk::DropJobNotifier
+
+
+ Fetching %1 from database
+
+
+
+
+ Parsing %1 %2
+
+
+
+
+ Tomahawk::DynamicControlList
+
+
+ Click to collapse
+
+
+
+
+ Tomahawk::DynamicModel
+
+
+
+ Could not find a playable track.
+
+Please change the filters or try again.
+
+
+
+
+ Failed to generate preview with the desired filters
+ Échec de la génération de l'aperçu avec ces filtres
+
+
+
+ Tomahawk::DynamicSetupWidget
+
+
+ Type:
+
+
+
+
+ Generate
+ Générer
+
+
+
+ Tomahawk::DynamicView
+
+
+ Add some filters above to seed this station!
+ Ajoutez des filtres ci dessus pour commencer une station !
+
+
+
+ Press Generate to get started!
+ Appuyez sur Générer pour commencer !
+
+
+
+ Add some filters above, and press Generate to get started!
+ Ajoutez des filtres ci dessus et appuyez sur "Générer" pour commencer !
+
+
+
+ Tomahawk::DynamicWidget
+
+
+ Station ran out of tracks!
+
+Try tweaking the filters for a new set of songs to play.
+
+
+
+
+ Tomahawk::EchonestControl
+
+
+
+
+
+
+
+ is
+
+
+
+
+ from user
+
+
+
+
+
+ No users with Echo Nest Catalogs enabled. Try enabling option in Collection settings
+ Aucun utilisateur avec un Catalogue The Echo Nest actif. Essayez d'activer l'option dans les préférences de Collection.
+
+
+
+ similar to
+
+
+
+
+
+
+
+
+
+
+ Less
+ Moins
+
+
+
+
+
+
+
+
+
+ More
+ Plus
+
+
+
+ 0 BPM
+ 0 BPM
+
+
+
+ 500 BPM
+ 500 BPM
+
+
+
+ 0 secs
+ 0 secs
+
+
+
+ 3600 secs
+ 3600 secs
+
+
+
+ -100 dB
+ -100 dB
+
+
+
+ 100 dB
+ 100 dB
+
+
+
+ Major
+ Majeur
+
+
+
+ Minor
+ Mineur
+
+
+
+ C
+ Do
+
+
+
+ C Sharp
+ Do dièse
+
+
+
+ D
+ Ré
+
+
+
+ E Flat
+ Mi bémol
+
+
+
+ E
+ Mi
+
+
+
+ F
+ Fa
+
+
+
+ F Sharp
+ Fa dièse
+
+
+
+ G
+ Sol
+
+
+
+ A Flat
+ La bémol
+
+
+
+ A
+ La
+
+
+
+ B Flat
+ Si bémol
+
+
+
+ B
+ Si
+
+
+
+ Ascending
+ Croissant
+
+
+
+ Descending
+ Décroissant
+
+
+
+ Tempo
+ Tempo
+
+
+
+ Duration
+ Durée
+
+
+
+ Loudness
+ Intensité
+
+
+
+ Artist Familiarity
+
+
+
+
+ Artist Hotttnesss
+
+
+
+
+ Song Hotttnesss
+
+
+
+
+ Latitude
+ Latitude
+
+
+
+ Longitude
+ Longitude
+
+
+
+ Mode
+ Mode
+
+
+
+ Key
+ Tonalité
+
+
+
+ Energy
+ Energie
+
+
+
+ Danceability
+ Dansabilité
+
+
+
+ only by ~%1
+
+
+
+
+ similar to ~%1
+
+
+
+
+ with genre ~%1
+
+
+
+
+
+ from no one
+
+
+
+
+ My Collection
+ Ma Collection
+
+
+
+ from %1 radio
+
+
+
+
+ with %1 %2
+
+
+
+
+ about %1 BPM
+ environ %1 BPM
+
+
+
+ about %n minute(s) long
+ environ %n minuteenviron %n minutes
+
+
+
+ about %1 dB
+ environ %1 dB
+
+
+
+ at around %1%2 %3
+
+
+
+
+ in %1
+
+
+
+
+ in a %1 key
+
+
+
+
+ sorted in %1 %2 order
+
+
+
+
+ with a %1 mood
+
+
+
+
+ in a %1 style
+
+
+
+
+ Tomahawk::EchonestSteerer
+
+
+ Steer this station:
+
+
+
+
+ Much less
+ Beaucoup moins
+
+
+
+ Less
+ Moins
+
+
+
+ A bit less
+ Un peu moins
+
+
+
+ Keep at current
+ Garder le même
+
+
+
+ A bit more
+ Un peu plus
+
+
+
+ More
+ Plus
+
+
+
+ Much more
+ Beaucoup plus
+
+
+
+ Tempo
+ Tempo
+
+
+
+ Loudness
+ Intensité
+
+
+
+ Danceability
+ Dansabilité
+
+
+
+ Energy
+ Energie
+
+
+
+ Song Hotttnesss
+ Hotttnesss du morceau
+
+
+
+ Artist Hotttnesss
+ Hotttnesss de l'artiste
+
+
+
+ Artist Familiarity
+
+
+
+
+ By Description
+ Par description
+
+
+
+ Enter a description
+ Entrer une description
+
+
+
+ Apply steering command
+
+
+
+
+ Reset all steering commands
+
+
+
+
+ Tomahawk::GroovesharkParser
+
+
+ Error fetching Grooveshark information from the network!
+ Échec du chargement des informations Grooveshark depuis le réseau!
+
+
+
+ Tomahawk::InfoSystem::ChartsPlugin
+
+
+ Top Overall
+
+
+
+
+ Artists
+
+
+
+
+ Albums
+ Albums
+
+
+
+ Tracks
+ Pistes
+
+
+
+ Tomahawk::InfoSystem::FdoNotifyPlugin
+
+
+ Tomahawk is playing "%1" by %2%3.
+ Tomahawk joue "%1" par %2%3.
+
+
+
+ on "%1"
+
+
+
+
+ Tomahawk::InfoSystem::LastFmPlugin
+
+
+ Top Tracks
+
+
+
+
+ Loved Tracks
+
+
+
+
+ Hyped Tracks
+
+
+
+
+ Top Artists
+
+
+
+
+ Hyped Artists
+
+
+
+
+ Tomahawk::InfoSystem::NewReleasesPlugin
+
+
+ Albums
+
+
+
+
+ Tomahawk::InfoSystem::TwitterInfoPlugin
+
+
+ Listening to "%1" by %2 and loving it! %3
+ J'écoute "%1" par %2 et j'adore ! %3
+
+
+
+ Tomahawk::ItunesParser
+
+
+ Error fetching iTunes information from the network!
+ Échec du chargement des informations iTunes depuis le réseau!
+
+
+
+ Tomahawk::JSPFLoader
+
+
+ New Playlist
+ Nouvelle liste de lecture
+
+
+
+ Failed to save tracks
+
+
+
+
+ Some tracks in the playlist do not contain an artist and a title. They will be ignored.
+ Certaines pistes dans la liste de lecture ne contiennent pas d'artiste ou de titre. Elles seront ignorées.
+
+
+
+ XSPF Error
+ Erreur XSPF
+
+
+
+ This is not a valid XSPF playlist.
+ Ceci n'est pas une liste de lecture XSPF valide.
+
+
+
+ Tomahawk::LatchManager
+
+
+ &Catch Up
+
+
+
+
+
+ &Listen Along
+ &Ecouter avec
+
+
+
+ Tomahawk::Query
+
+
+ and
+ et
+
+
+
+ You
+ Vous
+
+
+
+ you
+ vous
+
+
+
+ and
+ et
+
+
+
+ %n other(s)
+ %n autre%n autres
+
+
+
+ %1 people
+ %1 personnes
+
+
+
+ loved this track
+
+
+
+
+ Tomahawk::RdioParser
+
+
+ Error fetching Rdio information from the network!
+ Échec du chargement des informations Rdio depuis le réseau!
+
+
+
+ Tomahawk::ShortenedLinkParser
+
+
+ Network error parsing shortened link!
+ Erreur réseau lors du décodage de l'URL courte!
+
+
+
+ Tomahawk::Source
+
+
+
+ Scanning (%L1 tracks)
+ Scan en cours (%L1 pistes)
+
+
+
+ Scanning
+ Scan en cours
+
+
+
+ Checking
+
+
+
+
+ Fetching
+
+
+
+
+ Parsing
+
+
+
+
+ Saving (%1%)
+
+
+
+
+ Tomahawk::SpotifyParser
+
+
+ Error fetching Spotify information from the network!
+ Échec du chargement des informations Spotify depuis le réseau!
+
+
+
+ TomahawkApp
+
+
+ My Collection
+ Ma Collection
+
+
+
+ TomahawkOAuthTwitter
+
+
+ Twitter PIN
+
+
+
+
+ After authenticating on Twitter's web site,
+enter the displayed PIN number here:
+ Après vous être authentifier sur le site de Twitter,
+saisissez le numéro PIN ici :
+
+
+
+ TomahawkTrayIcon
+
+
+
+ Hide Tomahawk Window
+ Masquer la fenêtre Tomahawk
+
+
+
+ Show Tomahawk Window
+ Afficher la fenêtre Tomahawk
+
+
+
+ Currently not playing.
+ Pas de lecture en cours
+
+
+
+ Play
+ Lecture
+
+
+
+ Pause
+ Pause
+
+
+
+ TomahawkWindow
+
+
+ Tomahawk
+ Tomahawk
+
+
+
+ &Settings
+
+
+
+
+ &Controls
+ &Contrôles
+
+
+
+ &Network
+ &Réseau
+
+
+
+ &Window
+ &Fenêtre
+
+
+
+ &Help
+ &Aide
+
+
+
+ &Quit
+ &Quitter
+
+
+
+ Ctrl+Q
+ Ctrl+Q
+
+
+
+ Go &Online
+ Se c&onnecter
+
+
+
+ Add &Friend...
+ Ajouter un &ami...
+
+
+
+ U&pdate Collection
+ Mettre à Jo&ur la Collection
+
+
+
+ Update Collection
+ Mettre à Jour la Collection
+
+
+
+ &Configure Tomahawk...
+ &Configurer Tomahawk...
+
+
+
+ Load &XSPF...
+ Charger &XSPF
+
+
+
+ Create &New Playlist...
+ Créer une &nouvelle liste de lecture...
+
+
+
+ About &Tomahawk...
+ A propos de &Tomahawk
+
+
+
+ Create New &Automatic Playlist
+ Créer une nouvelle liste de lecture automatique
+
+
+
+ Create New &Station
+ Créer une nouvelle &Station
+
+
+
+ Show Offline Sources
+ Afficher les sources hors ligne
+
+
+
+ Hide Offline Sources
+ Masquer les sources hors ligne
+
+
+
+ Minimize
+ Réduire
+
+
+
+ Ctrl+M
+ Ctrl+M
+
+
+
+ Zoom
+ Zoom
+
+
+
+ Meta+Ctrl+Z
+ Meta+Ctrl+Z
+
+
+
+ Diagnostics...
+ Diagnostics...
+
+
+
+ Fully &Rescan Collection
+ &Rescanner la collection entièrement
+
+
+
+ Fully Rescan Collection
+ Rescanner la collection entièrement
+
+
+
+
+ Play
+ Lecture
+
+
+
+ Space
+ Espace
+
+
+
+ Previous
+ Précédent
+
+
+
+ Next
+ Suivant
+
+
+
+ Global Search...
+ Recherche Globale...
+
+
+
+
+ Check For Updates...
+ Rechercher une mise à jour...
+
+
+
+
+
+ Connect To Peer
+
+
+
+
+ Enter peer address:
+
+
+
+
+ Enter peer port:
+
+
+
+
+ Enter peer key:
+
+
+
+
+ XSPF Error
+ Erreur XSPF
+
+
+
+ This is not a valid XSPF playlist.
+ Ceci n'est pas une liste de lecture XSPF valide.
+
+
+
+ Failed to save tracks
+ Échec de la sauvegarde des pistes
+
+
+
+ Some tracks in the playlist do not contain an artist and a title. They will be ignored.
+ Certaines pistes dans la liste de lecture ne contiennent pas d'artiste ou de titre. Elles seront ignorées.
+
+
+
+ Sorry, there is a problem accessing your audio device or the desired track, current track will be skipped. Make sure you have a suitable Phonon backend and required plugins installed.
+ Désolé, il y a un problème d'accès à votre matériel audio ou la piste en cours va être sauter. Vérifiez que vous avez un backend Phonon et les plugins requis installés.
+
+
+
+ Sorry, there is a problem accessing your audio device or the desired track, current track will be skipped.
+ Désolé, il y a un problème d'accès à votre matériel audio ou la piste en cours va être sauter.
+
+
+
+ Create New Station
+ Créer une nouvelle station
+
+
+
+ Name:
+ Nom :
+
+
+
+ New Station
+ Nouvelle station
+
+
+
+ New Playlist
+ Nouvelle liste de lecture
+
+
+
+ Pause
+ Pause
+
+
+
+ Go &offline
+ Se &déconnecter
+
+
+
+ Go &online
+ Se c&onnecter
+
+
+
+ Authentication Error
+ Erreur d'authentification
+
+
+
+ %1 by %2
+ track, artist name
+ %1 par %2
+
+
+
+ %1 - %2
+ current track, some window title
+ %1 - %2
+
+
+
+ <h2><b>Tomahawk %1<br/>(%2)</h2>
+ <h2><b>Tomahawk %1<br/>(%2)</h2>
+
+
+
+ <h2><b>Tomahawk %1</h2>
+ <h2><b>Tomahawk %1</h2>
+
+
+
+ Copyright 2010 - 2012<br/>Christian Muehlhaeuser <muesli@tomahawk-player.org><br/><br/>Thanks to: Leo Franchi, Jeff Mitchell, Dominik Schmidt, Jason Herskowitz, Alejandro Wainzinger, Hugo Lindström, Michael Zanetti, Harald Sitter and Steve Robertson
+ Copyright 2010 - 2012<br/>Christian Muehlhaeuser <muesli@tomahawk-player.org><br/><br/>Thanks to: Leo Franchi, Jeff Mitchell, Dominik Schmidt, Jason Herskowitz, Alejandro Wainzinger, Hugo Lindström, Michael Zanetti, Harald Sitter and Steve Robertson
+
+
+
+ About Tomahawk
+ A propos de Tomahawk
+
+
+
+ TopBar
+
+
+ Form
+ Form
+
+
+
+ 0 Sources
+ 0 Source
+
+
+
+ 0 Tracks
+ 0 piste
+
+
+
+ 0 Artists
+ 0 Artist
+
+
+
+ 0 Shown
+ 0 Affiché
+
+
+
+ Tracks
+ Pistes
+
+
+
+ Artists
+ Artistes
+
+
+
+ Filter
+ Filtre
+
+
+
+ Artist View
+
+
+
+
+ Flat View
+
+
+
+
+ Sources
+
+
+
+
+ Shown
+ Affiché
+
+
+
+ TopTracksContext
+
+
+ Top Hits
+
+
+
+
+ TrackModel
+
+
+ Artist
+ Artiste
+
+
+
+ Title
+ Titre
+
+
+
+ Album
+ Album
+
+
+
+ Track
+ Piste
+
+
+
+ Duration
+ Durée
+
+
+
+ Bitrate
+
+
+
+
+ Age
+ Age
+
+
+
+ Year
+ Année
+
+
+
+ Size
+ Taille
+
+
+
+ Origin
+ Origine
+
+
+
+ Score
+ Score
+
+
+
+ Composer
+ Compositeur
+
+
+
+ TrackView
+
+
+ Sorry, your filter '%1' did not match any results.
+ Désolé, votre filtre '%1' ne correspond à aucun résultat
+
+
+
+ TransferStatusItem
+
+
+ from
+
+
+
+
+ to
+
+
+
+
+ TreeItemDelegate
+
+
+ Unknown
+ Inconnu
+
+
+
+ TreeModel
+
+
+ Name
+ Nom
+
+
+
+ Duration
+
+
+
+
+ Bitrate
+
+
+
+
+ Age
+
+
+
+
+ Year
+
+
+
+
+ Size
+
+
+
+
+ Origin
+
+
+
+
+ Composer
+
+
+
+
+ All Artists
+
+
+
+
+
+ My Collection
+ Ma Collection
+
+
+
+
+ Collection of %1
+ Collection de %1
+
+
+
+ TwitterConfigWidget
+
+
+ Configure this Twitter account
+ Configurer ce compte Twitter
+
+
+
+ The Twitter plugin allows you to discover and play music from your Twitter friends running Tomahawk and post messages to your account.
+ Le plugin Twitter vous permet de découvrir et jouer de la musique de vos amis Twitter qui utilisent Tomahawk et de poster des messages sur votre compte.
+
+
+
+ Status: No saved credentials
+
+
+
+
+ Authenticate with Twitter
+
+
+
+
+ Twitter Connections
+
+
+
+
+
+If you only want to post tweets, you're done.
+
+If you want to connect Tomahawk to your friends using Twitter, select the type of tweet and press the button below to send a sync message. You must both be following each other as Direct Messages are used. Then be (very) patient -- it can take several minutes!
+
+You can re-send a sync message at any time simply by sending another tweet using the button.
+
+
+
+
+ Select the kind of tweet you would like, then press the button to post it:
+
+
+
+
+ Global Tweet
+ Tweet Global
+
+
+
+ @Mention
+
+
+
+
+ Direct Message
+
+
+
+
+ e.g. @tomahawk
+
+
+
+
+ Send Message
+
+
+
+
+ ViewManager
+
+
+ SuperCollection
+ SuperCollection
+
+
+
+ Combined libraries of all your online friends
+ Collections regroupant toutes celles de vos amis en ligne
+
+
+
+ All available albums
+ Tous les albums disponibles
+
+
+
+ WelcomeWidget
+
+
+ Recent Additions
+ Derniers Ajouts
+
+
+
+ Newest Stations & Playlists
+ Dernières stations & listes de lecture
+
+
+
+ Recently Played Tracks
+ Joués récemment
+
+
+
+ No recently created playlists in your network.
+ Pas de liste de lecture créée récemment sur votre réseau.
+
+
+
+ Welcome to Tomahawk
+
+
+
+
+ WhatsHotWidget
+
+
+ Charts
+
+
+
+
+ WikipediaContext
+
+
+ Wikipedia
+ Wikipedia
+
+
+
+ XMPPBot
+
+
+
+Terms for %1:
+
+
+
+
+
+ No terms found, sorry.
+
+
+
+
+
+Hotttness for %1: %2
+
+
+
+
+
+
+Familiarity for %1: %2
+
+
+
+
+
+
+Lyrics for "%1" by %2:
+
+%3
+
+
+
+
+
+ XSPFLoader
+
+
+ Failed to parse contents of XSPF playlist
+ Échec du décodage de la liste de lecture XSPF
+
+
+
+ Some playlist entries were found without artist and track name, they will be omitted
+ Certaines entrées de la liste de lecture n'ont pas d'artiste ou de titre, elles seront omises.
+
+
+
+ Failed to fetch the desired playlist from the network, or the desired file does not exist
+ Échec du chargement de la liste de lecture depuis le réseau, ou le fichier n'existe pas
+
+
+
+ New Playlist
+ Nouvelle liste de lecture
+
+
+
+ XmlConsole
+
+
+ Xml stream console
+
+
+
+
+
+ Filter
+ Filtre
+
+
+
+ Save log
+
+
+
+
+ Disabled
+
+
+
+
+ By JID
+
+
+
+
+ By namespace uri
+ Par namespace uri
+
+
+
+ By all attributes
+
+
+
+
+ Visible stanzas
+
+
+
+
+ Information query
+
+
+
+
+ Message
+
+
+
+
+ Presence
+
+
+
+
+ Custom
+
+
+
+
+ Close
+
+
+
+
+ Save XMPP log to file
+
+
+
+
+ OpenDocument Format (*.odf);;HTML file (*.html);;Plain text (*.txt)
+ Format OpenDocument (*.odf);;Fichiers HTML (*.html);;Texte (*.txt)
+
+
+
+ XmppConfigWidget
+
+
+ Xmpp Configuration
+ Configuration XMPP
+
+
+
+ Configure this Xmpp account
+ Configurer ce compte XMPP
+
+
+
+ Enter your Xmpp login to connect with your friends using Tomahawk!
+
+
+
+
+ Login Information
+
+
+
+
+ Xmpp ID:
+
+
+
+
+ e.g. user@example.com
+
+
+
+
+ Password:
+
+
+
+
+ An account with this name already exists!
+ Un compte avec ce nom existe déjà !
+
+
+
+ Advanced Xmpp Settings
+ Paramètres XMPP avancés
+
+
+
+ Server:
+
+
+
+
+ Port:
+
+
+
+
+ Lots of servers don't support this (e.g. GTalk, jabber.org)
+
+
+
+
+ Publish currently playing track
+ Publier la piste en cours de lecture
+
+
+
+ Enforce secure connection
+
+
+
+
+ XmppSipPlugin
+
+
+ User Interaction
+
+
+
+
+ Host is unknown
+
+
+
+
+ Item not found
+
+
+
+
+ Authorization Error
+
+
+
+
+ Remote Stream Error
+
+
+
+
+ Remote Connection failed
+
+
+
+
+ Internal Server Error
+
+
+
+
+ System shutdown
+
+
+
+
+ Conflict
+
+
+
+
+ Unknown
+ Ajouter un &ami...
+
+
+
+ No Compression Support
+
+
+
+
+ No Encryption Support
+
+
+
+
+ No Authorization Support
+
+
+
+
+ No Supported Feature
+
+
+
+
+ Add Friend
+
+
+
+
+ Enter Xmpp ID:
+
+
+
+
+ Add Friend...
+
+
+
+
+ XML Console...
+
+
+
+
+ I'm sorry -- I'm just an automatic presence used by Tomahawk Player (http://gettomahawk.com). If you are getting this message, the person you are trying to reach is probably not signed on, so please try again later!
+
+
+
+
+ Authorize User
+
+
+
+
+ Do you want to grant <b>%1</b> access to your Collection?
+ Voulez vous donner accès à votre collection à %1 ?
+
+
+
+ ZeroconfConfig
+
+
+ Form
+
+
+
+
+ Local Network configuration
+ Configuration réseau local
+
+
+
+ This plugin will automatically find other users running Tomahawk on your local network
+ Ce plugin va automatiquement trouver les autres utilisateurs de Tomahawk sur votre réseau local
+
+
+
+ Connect automatically when Tomahawk starts
+
+
+
+
\ No newline at end of file
diff --git a/lang/tomahawk_ja.ts b/lang/tomahawk_ja.ts
index f3fdaa4dc..f35372285 100644
--- a/lang/tomahawk_ja.ts
+++ b/lang/tomahawk_ja.ts
@@ -294,36 +294,41 @@ Remember: Only allow peers to connect if you trust who they are and if you have
+ social
+
+
+
+
love
Love
-
+
Time
時間
-
+
Time Left
残り時間
-
+
Shuffle
シャッフル
-
+
Repeat
リピート
-
+
Low
-
+
High
@@ -677,6 +682,14 @@ Remember: Only allow peers to connect if you trust who they are and if you have
新規プレイリストを作成
+
+ NewReleasesWidget
+
+
+ New Releases
+
+
+
PlaylistItemDelegate
@@ -1051,6 +1064,49 @@ other: %n年前
+
+ SocialWidget
+
+
+ Form
+
+
+
+
+ Facebook
+
+
+
+
+ Twitter
+
+
+
+
+ Cover
+
+
+
+
+ TextLabel
+
+
+
+
+ Listening to "%1" by %2 and loving it! %4
+
+
+
+
+ Listening to "%1" by %2 on "%3" and loving it! %4
+
+
+
+
+ %1 characters left
+
+
+
SourceDelegate
@@ -1264,6 +1320,11 @@ other: %n年前
+ New Releases
+
+
+
+
Friends
@@ -1403,7 +1464,7 @@ other: %n年前
- Allow web browsers to interact with Tomahawk
+ Allow web browsers to interact with Tomahawk (recommended)
@@ -1527,7 +1588,7 @@ other: %n年前
Tomahawk::Accounts::TwitterAccountFactory
-
+
Connect to your Twitter followers.
@@ -2257,22 +2318,22 @@ Try tweaking the filters for a new set of songs to play.
Tomahawk::InfoSystem::ChartsPlugin
-
+
Top Overall
-
+
Artists
-
+
Albums
-
+
Tracks
@@ -2280,12 +2341,12 @@ Try tweaking the filters for a new set of songs to play.
Tomahawk::InfoSystem::FdoNotifyPlugin
-
+
Tomahawk is playing "%1" by %2%3.
-
+
on "%1"
@@ -2293,31 +2354,47 @@ Try tweaking the filters for a new set of songs to play.
Tomahawk::InfoSystem::LastFmPlugin
-
+
Top Tracks
-
+
Loved Tracks
-
+
Hyped Tracks
-
+
Top Artists
-
+
Hyped Artists
+
+ Tomahawk::InfoSystem::NewReleasesPlugin
+
+
+ Albums
+
+
+
+
+ Tomahawk::InfoSystem::TwitterInfoPlugin
+
+
+ Listening to "%1" by %2 and loving it! %3
+
+
+
Tomahawk::ItunesParser
@@ -2467,7 +2544,7 @@ Try tweaking the filters for a new set of songs to play.
TomahawkApp
-
+
My Collection
@@ -3103,17 +3180,17 @@ You can re-send a sync message at any time simply by sending another tweet using
ViewManager
-
+
SuperCollection
-
+
Combined libraries of all your online friends
-
+
All available albums
@@ -3378,107 +3455,107 @@ Lyrics for "%1" by %2:
XmppSipPlugin
-
+
User Interaction
-
+
Host is unknown
-
+
Item not found
-
+
Authorization Error
-
+
Remote Stream Error
-
+
Remote Connection failed
-
+
Internal Server Error
-
+
System shutdown
-
+
Conflict
-
+
Unknown
-
+
No Compression Support
-
+
No Encryption Support
-
+
No Authorization Support
-
+
No Supported Feature
-
+
Add Friend
-
+
Enter Xmpp ID:
-
+
Add Friend...
-
+
XML Console...
-
+
I'm sorry -- I'm just an automatic presence used by Tomahawk Player (http://gettomahawk.com). If you are getting this message, the person you are trying to reach is probably not signed on, so please try again later!
-
+
Authorize User
-
+
Do you want to grant <b>%1</b> access to your Collection?
diff --git a/lang/tomahawk_pl.ts b/lang/tomahawk_pl.ts
index 36ad68d04..bfc1a3ab8 100644
--- a/lang/tomahawk_pl.ts
+++ b/lang/tomahawk_pl.ts
@@ -34,7 +34,7 @@ Remember: Only allow peers to connect if you trust who they are and if you have
Description goes here
-
+ Tutaj pojawi się opis
@@ -75,7 +75,7 @@ Remember: Only allow peers to connect if you trust who they are and if you have
&Follow in real-time
-
+ &Podążaj na bieżąco
@@ -195,7 +195,7 @@ Remember: Only allow peers to connect if you trust who they are and if you have
After you have scanned your music collection you will find your latest album additions right here.
- Po zeskanowaniu swojej kolekcji muzycznej znajdziesz ostatnio dodane albumy właśnie tutaj.
+ Po zeskanowaniu swojej kolekcji muzycznej w tym miejscu znajdziesz ostatnio dodane albumy.
@@ -242,7 +242,7 @@ Remember: Only allow peers to connect if you trust who they are and if you have
After you have scanned your music collection you will find your tracks right here.
- Po zeskanowaniu swojej kolekcji muzycznej znajdziesz utwory właśnie tutaj.
+ Po zeskanowaniu swojej kolekcji muzycznej utwory znajdziesz w tym miejscu.
@@ -252,7 +252,7 @@ Remember: Only allow peers to connect if you trust who they are and if you have
Sorry, your filter '%1' did not match any results.
- Przepraszamy, twój filtr %1' nie pasuje do żadnych wyników.
+ Przepraszamy, twój filtr '%1' nie pasuje do żadnych wyników.
@@ -294,36 +294,41 @@ Remember: Only allow peers to connect if you trust who they are and if you have
+ social
+
+
+
+
love
ulubione
-
+
Time
Czas
-
+
Time Left
Pozostały czas
-
+
Shuffle
Losowo
-
+
Repeat
Powtarzaj
-
+
Low
Nisko
-
+
High
Wysoko
@@ -423,7 +428,7 @@ Remember: Only allow peers to connect if you trust who they are and if you have
<p><b>Sorry!</b> Tomahawk crashed. Information about the crash is now being sent to Tomahawk HQ so that we can fix the bug.</p>
- <p><b>Przepraszamy!</b> Tomahawk uległ awarii. Informacja o incydencie zostanie teraz wysłana do kwatery głównej programu, abyśmy mogli poprawić błędy.</p>
+ <p><b>Przepraszamy!</b> Tomahawk uległ awarii. Abyśmy mogli poprawić błędy, informacja o incydencie zostanie wysłana do kwatery głównej programu.</p>
@@ -659,12 +664,12 @@ Remember: Only allow peers to connect if you trust who they are and if you have
Tomahawk offers a variety of ways to help you create playlists and find music you enjoy!
- Tomahawk oferuje różne sposoby pomocy w tworzeniu list i poszukiwaniu muzyki, którą lubisz!
+ Tomahawk oferuje różne sposoby pomocy w tworzeniu list i poszukiwaniu twojej ulubionej muzyki!
Just enter a genre or tag name and Tomahawk will suggest a few songs to get you started with your new playlist:
- Podaj tylko tag lub gatunek, a Tomahawk zasugeruje kilka piosenek, żeby pomóc ci zacząć z nową listą:
+ Jeśli podasz chociaż jeden tag lub gatunek, Tomahawk postara się zasugerować ci kilka piosenek na dobry początek:
@@ -677,6 +682,14 @@ Remember: Only allow peers to connect if you trust who they are and if you have
Utwórz nową listę
+
+ NewReleasesWidget
+
+
+ New Releases
+ Nowe Wydania
+
+
PlaylistItemDelegate
@@ -695,7 +708,7 @@ Remember: Only allow peers to connect if you trust who they are and if you have
played %1 by you
-
+ odtworzone %1 przez ciebie
@@ -705,7 +718,7 @@ Remember: Only allow peers to connect if you trust who they are and if you have
added %1
-
+ dodano %1
@@ -713,12 +726,12 @@ Remember: Only allow peers to connect if you trust who they are and if you have
A playlist by %1, created %2
- Lista %1, utworzona %2
+ %1 lista, utworzona %2
you
- ty
+ Twoja
@@ -741,7 +754,7 @@ Remember: Only allow peers to connect if you trust who they are and if you have
Just a regular old playlist... Give it a name, drag in some tracks, and go!
- Po prostu zwykła stara lista... Nazwij, upuść na nią trochę piosenek i gotowe!
+ Po prostu zwykła stara lista... Nazwij ją, upuść na nią trochę piosenek i gotowe!
@@ -787,7 +800,7 @@ Remember: Only allow peers to connect if you trust who they are and if you have
Hostname of proxy server
- Nazwa hosta serwera proxy
+ Host serwera proxy
@@ -948,7 +961,7 @@ Remember: Only allow peers to connect if you trust who they are and if you have
Hide Queue
- Schowaj Kolejkę
+ Ukryj Kolejkę
@@ -964,7 +977,7 @@ Remember: Only allow peers to connect if you trust who they are and if you have
Not found: %1
- Nie znaleziono %1
+ Nie znaleziono: %1
@@ -1008,12 +1021,12 @@ Remember: Only allow peers to connect if you trust who they are and if you have
All
-
+ Wszystkie
Services
-
+ Usługi
@@ -1049,6 +1062,49 @@ Remember: Only allow peers to connect if you trust who they are and if you have
Najczęściej odtwarzane utwory, których nie masz
+
+ SocialWidget
+
+
+ Form
+
+
+
+
+ Facebook
+ Facebook
+
+
+
+ Twitter
+ Twitter
+
+
+
+ Cover
+ Okładka
+
+
+
+ TextLabel
+
+
+
+
+ Listening to "%1" by %2 and loving it! %4
+
+
+
+
+ Listening to "%1" by %2 on "%3" and loving it! %4
+
+
+
+
+ %1 characters left
+ pozostało znaków: %1
+
+
SourceDelegate
@@ -1101,7 +1157,7 @@ Remember: Only allow peers to connect if you trust who they are and if you have
Hide
- Schowaj
+ Ukryj
@@ -1142,12 +1198,12 @@ Remember: Only allow peers to connect if you trust who they are and if you have
Collection
-
+ Kolekcja
Latest Additions
-
+ Ostatnio Dodane
@@ -1198,7 +1254,7 @@ Remember: Only allow peers to connect if you trust who they are and if you have
Group
-
+ Grupa
@@ -1223,7 +1279,7 @@ Remember: Only allow peers to connect if you trust who they are and if you have
Browse
-
+ Przeglądaj
@@ -1253,17 +1309,22 @@ Remember: Only allow peers to connect if you trust who they are and if you have
Recently Played
-
+ Ostatnio Odtworzone
Charts
-
+ Listy Przebojów
+ New Releases
+ Nowe Wydania
+
+
+
Friends
-
+ Znajomi
@@ -1301,7 +1362,7 @@ Remember: Only allow peers to connect if you trust who they are and if you have
High Quality Streaming
- Strumieniowanie w wysokiej jakości
+ Muzyka w wysokiej jakości
@@ -1319,7 +1380,7 @@ Remember: Only allow peers to connect if you trust who they are and if you have
Local Music Information
- Lokalne Informacje o Muzyce
+ Informacje o Lokalnej Muzyce
@@ -1346,7 +1407,7 @@ indywidualnego profilu gustu.
Watch for changes
- Obserwuj pod kątem zmian
+ Obserwuj zmiany
@@ -1405,7 +1466,7 @@ indywidualnego profilu gustu.
- Allow web browsers to interact with Tomahawk
+ Allow web browsers to interact with Tomahawk (recommended)
@@ -1429,7 +1490,7 @@ indywidualnego profilu gustu.
%1 downloads
-
+ pobrań: %1
@@ -1452,7 +1513,7 @@ indywidualnego profilu gustu.
Configure this Google Account
-
+ Konfiguruj to Konto Google
@@ -1475,7 +1536,7 @@ indywidualnego profilu gustu.
Connect to Google Talk to find your friends
-
+ Połącz z Google Talk aby znaleźć znajomych
@@ -1488,7 +1549,7 @@ indywidualnego profilu gustu.
Enter Google Address:
-
+ Podaj Adres Google
@@ -1529,9 +1590,9 @@ indywidualnego profilu gustu.
Tomahawk::Accounts::TwitterAccountFactory
-
+
Connect to your Twitter followers.
-
+ Łącz się z osobami śledzącymi cię na Twitterze.
@@ -1657,7 +1718,7 @@ You may wish to try re-authenticating.
Your message has been posted!
-
+ Twoja wiadomość została wysłana!
@@ -1688,13 +1749,13 @@ You may wish to try re-authenticating.
Add to &Queue
- Dodaj do &Kolejki
+ Dodaj do &kolejki
&Love
-
+ &Uwielbiam
@@ -1724,12 +1785,12 @@ You may wish to try re-authenticating.
&Continue Playback after this Track
-
+ &Kontynuuj odtwarzanie po tym utworze
&Stop Playback after this Track
-
+ &Zatrzymaj odtwarzanie po tym utworze
@@ -1827,17 +1888,17 @@ Proszę zmienić filtry lub spróbować ponownie.
Add some filters above to seed this station!
- Dodaj trochę filtrów powyżej, aby załączyć tą stację!
+ Dodaj powyżej trochę filtrów, a Tomahawk utworzy stację z podobną muzyką!
Press Generate to get started!
- Naciśnij Generuj, aby zacząć!
+ Naciśnij Generuj aby zacząć!
Add some filters above, and press Generate to get started!
- Dodaj trochę filtrów powyżej i naciśnij Generuj, aby zacząć!
+ Dodaj powyżej trochę filtrów i naciśnij Generuj aby zacząć!
@@ -2261,22 +2322,22 @@ Try tweaking the filters for a new set of songs to play.
Tomahawk::InfoSystem::ChartsPlugin
-
+
Top Overall
Top Wszechczasów
-
+
Artists
Artyści
-
+
Albums
Albumy
-
+
Tracks
Utwory
@@ -2284,44 +2345,60 @@ Try tweaking the filters for a new set of songs to play.
Tomahawk::InfoSystem::FdoNotifyPlugin
-
+
Tomahawk is playing "%1" by %2%3.
-
+
on "%1"
-
+ z "%1"
Tomahawk::InfoSystem::LastFmPlugin
-
+
Top Tracks
-
+
Loved Tracks
-
+
Hyped Tracks
-
+
Top Artists
-
+
Hyped Artists
+
+ Tomahawk::InfoSystem::NewReleasesPlugin
+
+
+ Albums
+ Albumy
+
+
+
+ Tomahawk::InfoSystem::TwitterInfoPlugin
+
+
+ Listening to "%1" by %2 and loving it! %3
+
+
+
Tomahawk::ItunesParser
@@ -2377,27 +2454,27 @@ Try tweaking the filters for a new set of songs to play.
and
-
+ i
You
-
+ Ty
you
-
+ ty
and
-
+ i
%n other(s)
-
+ %n inny%n inne%n innych
@@ -2471,7 +2548,7 @@ Try tweaking the filters for a new set of songs to play.
TomahawkApp
-
+
My Collection
Moja Kolekcja
@@ -2481,7 +2558,7 @@ Try tweaking the filters for a new set of songs to play.
Twitter PIN
- PIN Twitter
+ Twitter PIN
@@ -2806,7 +2883,7 @@ wprowadź pokazany numer PIN tutaj:
Copyright 2010 - 2012<br/>Christian Muehlhaeuser <muesli@tomahawk-player.org><br/><br/>Thanks to: Leo Franchi, Jeff Mitchell, Dominik Schmidt, Jason Herskowitz, Alejandro Wainzinger, Hugo Lindström, Michael Zanetti, Harald Sitter and Steve Robertson
-
+ Copyright 2010 - 2012<br/>Christian Muehlhaeuser <muesli@tomahawk-player.org><br/><br/>Podziękowania dla: Leo Franchi, Jeff Mitchell, Dominik Schmidt, Jason Herskowitz, Alejandro Wainzinger, Hugo Lindström, Michael Zanetti, Harald Sitter oraz Steve Robertson
@@ -2945,7 +3022,7 @@ wprowadź pokazany numer PIN tutaj:
Composer
-
+ Kompozytor
@@ -3017,7 +3094,7 @@ wprowadź pokazany numer PIN tutaj:
Composer
-
+ Kompozytor
@@ -3042,12 +3119,12 @@ wprowadź pokazany numer PIN tutaj:
Configure this Twitter account
- Konfiguruj to konto Twitter
+ Konfiguruj konto na Twitter
The Twitter plugin allows you to discover and play music from your Twitter friends running Tomahawk and post messages to your account.
- Wtyczka Twittera pozwala ci odkrywać i odtwarzać muzykę znajomych z Twittera, którzy używają Tomahawka i wysyłać wiadomości ze swojego konta.
+ Wtyczka Twittera pozwala ci odkrywać i odtwarzać muzykę znajomych z Twittera, którzy używają Tomahawka oraz wysyłać wiadomości ze swojego konta.
@@ -3075,14 +3152,14 @@ You can re-send a sync message at any time simply by sending another tweet using
Jeśli chcesz jedynie wysyłać tweety, wszystko gotowe.
-Jeśli chcesz, aby Tomahawk łączył się z twoimi znajomymi używając Twittera, wybierz rodzaj tweeta i naciśnij przycisk poniżej by wysłać wiadomość synchronizacyjną. Obie strony muszą śledzić się nawzajem, ponieważ używane są Wiadomości Prywatne. Teraz miej (dużo) cierpliwości - może to zająć kilka minut!
+Jeśli chcesz, aby Tomahawk łączył się z twoimi znajomymi używając Twittera, wybierz rodzaj tweeta i naciśnij przycisk poniżej by wysłać wiadomość synchronizacyjną. Obie strony muszą śledzić się nawzajem, ponieważ używane są Wiadomości Prywatne. Miej (bardzo) dużo cierpliwości - może to zająć kilka minut!
-Możesz wysłać wiadomość synchronizacyjną ponownie kiedykolwiek, po prostu wyślij kolejnego tweeta używając przycisku.
+Zawsze możesz ponownie wysłać wiadomość synchronizacyjną - po prostu wyślij kolejnego tweeta używając przycisku.
Select the kind of tweet you would like, then press the button to post it:
- Wybierz rodzaj tweeta, który ci odpowiada, a następnie naciśnij przycisk, aby go wysłać:
+ Wybierz rodzaj tweeta który ci odpowiada, a następnie naciśnij przycisk aby go wysłać:
@@ -3113,17 +3190,17 @@ Możesz wysłać wiadomość synchronizacyjną ponownie kiedykolwiek, po prostu
ViewManager
-
+
SuperCollection
-
+ SuperKolekcja
-
+
Combined libraries of all your online friends
-
+ Połączone biblioteki wszystkich twoich znajomych online
-
+
All available albums
Wszystkie dostępne albumy
@@ -3348,12 +3425,12 @@ Tekst dla "%1" wykonawcy %2:
e.g. user@example.com
-
+ n.p. uzytkownik@example.com
Password:
-
+ Hasło:
@@ -3368,12 +3445,12 @@ Tekst dla "%1" wykonawcy %2:
Server:
-
+ Serwer:
Port:
-
+ Port:
@@ -3388,115 +3465,115 @@ Tekst dla "%1" wykonawcy %2:
Enforce secure connection
-
+ Wymuś bezpieczne połączenie
XmppSipPlugin
-
+
User Interaction
-
+
Host is unknown
-
+ Nieznany Host
-
+
Item not found
-
+
Authorization Error
-
+
Remote Stream Error
-
-
- Remote Connection failed
-
-
-
-
- Internal Server Error
-
-
-
-
- System shutdown
-
-
-
-
- Conflict
-
-
-
-
- Unknown
-
-
-
-
- No Compression Support
-
-
+ Remote Connection failed
+ Połączenie sieciowe się nie powiodło
+
+
+
+ Internal Server Error
+ Wewnętrzny błąd serwera
+
+
+
+ System shutdown
+ Wyłączenie systemu
+
+
+
+ Conflict
+ Konflikt
+
+
+
+ Unknown
+ Nieznany
+
+
+
+ No Compression Support
+ Brak obsługi kompresji
+
+
+
No Encryption Support
-
+ Brak obsługi szyfrowania
-
+
No Authorization Support
-
+ Brak obsługi autoryzacji
-
+
No Supported Feature
-
+ Brak obsługi danej funkcji
-
+
Add Friend
-
+ Dodaj Znajomego
-
+
Enter Xmpp ID:
-
+
Add Friend...
-
+ Dodaj Znajomego...
-
+
XML Console...
-
+ Konsola XML...
-
+
I'm sorry -- I'm just an automatic presence used by Tomahawk Player (http://gettomahawk.com). If you are getting this message, the person you are trying to reach is probably not signed on, so please try again later!
-
+
Authorize User
-
+ Autoryzuj Użytkownika
-
+
Do you want to grant <b>%1</b> access to your Collection?
-
+ Czy chcesz udzielić dostępu do swojej kolekcji <b>%1</b>?
diff --git a/lang/tomahawk_pt_BR.ts b/lang/tomahawk_pt_BR.ts
index 5075b0e7d..d5dec97d5 100644
--- a/lang/tomahawk_pt_BR.ts
+++ b/lang/tomahawk_pt_BR.ts
@@ -294,36 +294,41 @@ Remember: Only allow peers to connect if you trust who they are and if you have
+ social
+
+
+
+
love
Favorita
-
+
Time
Tempo
-
+
Time Left
Tempo restante
-
+
Shuffle
Embaralhar
-
+
Repeat
Repetir
-
+
Low
Diminuir
-
+
High
Aumentar
@@ -677,6 +682,14 @@ Remember: Only allow peers to connect if you trust who they are and if you have
Criar uma nova lista de reprodução
+
+ NewReleasesWidget
+
+
+ New Releases
+
+
+
PlaylistItemDelegate
@@ -1049,6 +1062,49 @@ Remember: Only allow peers to connect if you trust who they are and if you have
Faixas mais reproduzidas que você não possui
+
+ SocialWidget
+
+
+ Form
+
+
+
+
+ Facebook
+
+
+
+
+ Twitter
+
+
+
+
+ Cover
+
+
+
+
+ TextLabel
+
+
+
+
+ Listening to "%1" by %2 and loving it! %4
+
+
+
+
+ Listening to "%1" by %2 on "%3" and loving it! %4
+
+
+
+
+ %1 characters left
+
+
+
SourceDelegate
@@ -1262,6 +1318,11 @@ Remember: Only allow peers to connect if you trust who they are and if you have
+ New Releases
+
+
+
+
Friends
Amigos
@@ -1404,7 +1465,7 @@ Remember: Only allow peers to connect if you trust who they are and if you have
- Allow web browsers to interact with Tomahawk
+ Allow web browsers to interact with Tomahawk (recommended)
@@ -1528,7 +1589,7 @@ Remember: Only allow peers to connect if you trust who they are and if you have
Tomahawk::Accounts::TwitterAccountFactory
-
+
Connect to your Twitter followers.
@@ -2260,22 +2321,22 @@ Try tweaking the filters for a new set of songs to play.
Tomahawk::InfoSystem::ChartsPlugin
-
+
Top Overall
Classificação geral
-
+
Artists
Artistas
-
+
Albums
Álbuns
-
+
Tracks
Faixas
@@ -2283,12 +2344,12 @@ Try tweaking the filters for a new set of songs to play.
Tomahawk::InfoSystem::FdoNotifyPlugin
-
+
Tomahawk is playing "%1" by %2%3.
-
+
on "%1"
@@ -2296,31 +2357,47 @@ Try tweaking the filters for a new set of songs to play.
Tomahawk::InfoSystem::LastFmPlugin
-
+
Top Tracks
Faixas principais
-
+
Loved Tracks
Faixas favoritas
-
+
Hyped Tracks
Faixas mais populares
-
+
Top Artists
Artistas principais
-
+
Hyped Artists
Artistas mais populares
+
+ Tomahawk::InfoSystem::NewReleasesPlugin
+
+
+ Albums
+
+
+
+
+ Tomahawk::InfoSystem::TwitterInfoPlugin
+
+
+ Listening to "%1" by %2 and loving it! %3
+
+
+
Tomahawk::ItunesParser
@@ -2470,7 +2547,7 @@ Try tweaking the filters for a new set of songs to play.
TomahawkApp
-
+
My Collection
Minha biblioteca
@@ -3112,17 +3189,17 @@ Você pode enviar uma outra mensagem de sincronia a qualquer momento simplesment
ViewManager
-
+
SuperCollection
-
+
Combined libraries of all your online friends
-
+
All available albums
Todos os álbuns disponíveis
@@ -3394,107 +3471,107 @@ Letras de "%1" por %2:
XmppSipPlugin
-
+
User Interaction
-
+
Host is unknown
-
+
Item not found
-
+
Authorization Error
-
+
Remote Stream Error
-
+
Remote Connection failed
-
+
Internal Server Error
-
+
System shutdown
-
+
Conflict
-
+
Unknown
-
+
No Compression Support
-
+
No Encryption Support
-
+
No Authorization Support
-
+
No Supported Feature
-
+
Add Friend
-
+
Enter Xmpp ID:
-
+
Add Friend...
-
+
XML Console...
-
+
I'm sorry -- I'm just an automatic presence used by Tomahawk Player (http://gettomahawk.com). If you are getting this message, the person you are trying to reach is probably not signed on, so please try again later!
-
+
Authorize User
-
+
Do you want to grant <b>%1</b> access to your Collection?
diff --git a/lang/tomahawk_ru.ts b/lang/tomahawk_ru.ts
index 21b1eb9b0..f3a580596 100644
--- a/lang/tomahawk_ru.ts
+++ b/lang/tomahawk_ru.ts
@@ -294,36 +294,41 @@ Remember: Only allow peers to connect if you trust who they are and if you have
+ social
+
+
+
+
love
Любимая
-
+
Time
Прошло
-
+
Time Left
Осталось
-
+
Shuffle
Случаная
-
+
Repeat
Повторять
-
+
Low
Тише
-
+
High
Громче
@@ -677,6 +682,14 @@ Remember: Only allow peers to connect if you trust who they are and if you have
Создать Новый Плейлист
+
+ NewReleasesWidget
+
+
+ New Releases
+
+
+
PlaylistItemDelegate
@@ -1049,6 +1062,49 @@ Remember: Only allow peers to connect if you trust who they are and if you have
Популярные проигрываемые песни которых у вас нет
+
+ SocialWidget
+
+
+ Form
+
+
+
+
+ Facebook
+
+
+
+
+ Twitter
+
+
+
+
+ Cover
+
+
+
+
+ TextLabel
+
+
+
+
+ Listening to "%1" by %2 and loving it! %4
+
+
+
+
+ Listening to "%1" by %2 on "%3" and loving it! %4
+
+
+
+
+ %1 characters left
+
+
+
SourceDelegate
@@ -1262,6 +1318,11 @@ Remember: Only allow peers to connect if you trust who they are and if you have
+ New Releases
+
+
+
+
Friends
Друзья
@@ -1401,7 +1462,7 @@ Remember: Only allow peers to connect if you trust who they are and if you have
- Allow web browsers to interact with Tomahawk
+ Allow web browsers to interact with Tomahawk (recommended)
@@ -1525,7 +1586,7 @@ Remember: Only allow peers to connect if you trust who they are and if you have
Tomahawk::Accounts::TwitterAccountFactory
-
+
Connect to your Twitter followers.
@@ -2257,22 +2318,22 @@ Try tweaking the filters for a new set of songs to play.
Tomahawk::InfoSystem::ChartsPlugin
-
+
Top Overall
-
+
Artists
Исполнители
-
+
Albums
Альбомы
-
+
Tracks
Песни
@@ -2280,12 +2341,12 @@ Try tweaking the filters for a new set of songs to play.
Tomahawk::InfoSystem::FdoNotifyPlugin
-
+
Tomahawk is playing "%1" by %2%3.
-
+
on "%1"
@@ -2293,31 +2354,47 @@ Try tweaking the filters for a new set of songs to play.
Tomahawk::InfoSystem::LastFmPlugin
-
+
Top Tracks
Топ песен
-
+
Loved Tracks
Любимые песни
-
+
Hyped Tracks
-
+
Top Artists
Любимые исполнители
-
+
Hyped Artists
+
+ Tomahawk::InfoSystem::NewReleasesPlugin
+
+
+ Albums
+
+
+
+
+ Tomahawk::InfoSystem::TwitterInfoPlugin
+
+
+ Listening to "%1" by %2 and loving it! %3
+
+
+
Tomahawk::ItunesParser
@@ -2467,7 +2544,7 @@ Try tweaking the filters for a new set of songs to play.
TomahawkApp
-
+
My Collection
Моя коллекция
@@ -3107,17 +3184,17 @@ You can re-send a sync message at any time simply by sending another tweet using
ViewManager
-
+
SuperCollection
Общая коллекция
-
+
Combined libraries of all your online friends
Комбинированные библиотек всех ваших друзей онлайн
-
+
All available albums
Доступные альбомы
@@ -3388,107 +3465,107 @@ Lyrics for "%1" by %2:
XmppSipPlugin
-
+
User Interaction
Взаимодействие с пользователем
-
+
Host is unknown
Неизвестный хост
-
+
Item not found
Песня не найдена
-
+
Authorization Error
-
+
Remote Stream Error
-
+
Remote Connection failed
-
+
Internal Server Error
-
+
System shutdown
-
+
Conflict
-
+
Unknown
-
+
No Compression Support
-
+
No Encryption Support
-
+
No Authorization Support
-
+
No Supported Feature
-
+
Add Friend
-
+
Enter Xmpp ID:
-
+
Add Friend...
-
+
XML Console...
-
+
I'm sorry -- I'm just an automatic presence used by Tomahawk Player (http://gettomahawk.com). If you are getting this message, the person you are trying to reach is probably not signed on, so please try again later!
-
+
Authorize User
-
+
Do you want to grant <b>%1</b> access to your Collection?
diff --git a/lang/tomahawk_sv.ts b/lang/tomahawk_sv.ts
index 3b3be3ab1..e1e3bddea 100644
--- a/lang/tomahawk_sv.ts
+++ b/lang/tomahawk_sv.ts
@@ -296,36 +296,41 @@ Kom ihåg: Tillåt endast anslutning från klienter du litar på, och som har la
+ social
+
+
+
+
love
älska
-
+
Time
Tid
-
+
Time Left
Tid kvar
-
+
Shuffle
Blanda
-
+
Repeat
Upprepa
-
+
Low
Låg
-
+
High
Hög
@@ -679,6 +684,14 @@ Kom ihåg: Tillåt endast anslutning från klienter du litar på, och som har la
Erstelle eine neue Playliste
+
+ NewReleasesWidget
+
+
+ New Releases
+
+
+
PlaylistItemDelegate
@@ -1052,6 +1065,49 @@ Kom ihåg: Tillåt endast anslutning från klienter du litar på, och som har la
Mest spelade spår som du inte har
+
+ SocialWidget
+
+
+ Form
+
+
+
+
+ Facebook
+
+
+
+
+ Twitter
+
+
+
+
+ Cover
+
+
+
+
+ TextLabel
+
+
+
+
+ Listening to "%1" by %2 and loving it! %4
+
+
+
+
+ Listening to "%1" by %2 on "%3" and loving it! %4
+
+
+
+
+ %1 characters left
+
+
+
SourceDelegate
@@ -1265,6 +1321,11 @@ Kom ihåg: Tillåt endast anslutning från klienter du litar på, och som har la
+ New Releases
+
+
+
+
Friends
@@ -1404,7 +1465,7 @@ Kom ihåg: Tillåt endast anslutning från klienter du litar på, och som har la
- Allow web browsers to interact with Tomahawk
+ Allow web browsers to interact with Tomahawk (recommended)
@@ -1528,7 +1589,7 @@ Kom ihåg: Tillåt endast anslutning från klienter du litar på, och som har la
Tomahawk::Accounts::TwitterAccountFactory
-
+
Connect to your Twitter followers.
@@ -2258,22 +2319,22 @@ Try tweaking the filters for a new set of songs to play.
Tomahawk::InfoSystem::ChartsPlugin
-
+
Top Overall
-
+
Artists
Artister
-
+
Albums
Album
-
+
Tracks
Spår
@@ -2281,12 +2342,12 @@ Try tweaking the filters for a new set of songs to play.
Tomahawk::InfoSystem::FdoNotifyPlugin
-
+
Tomahawk is playing "%1" by %2%3.
-
+
on "%1"
@@ -2294,31 +2355,47 @@ Try tweaking the filters for a new set of songs to play.
Tomahawk::InfoSystem::LastFmPlugin
-
+
Top Tracks
-
+
Loved Tracks
-
+
Hyped Tracks
-
+
Top Artists
-
+
Hyped Artists
+
+ Tomahawk::InfoSystem::NewReleasesPlugin
+
+
+ Albums
+
+
+
+
+ Tomahawk::InfoSystem::TwitterInfoPlugin
+
+
+ Listening to "%1" by %2 and loving it! %3
+
+
+
Tomahawk::ItunesParser
@@ -2468,7 +2545,7 @@ Try tweaking the filters for a new set of songs to play.
TomahawkApp
-
+
My Collection
@@ -3104,17 +3181,17 @@ You can re-send a sync message at any time simply by sending another tweet using
ViewManager
-
+
SuperCollection
-
+
Combined libraries of all your online friends
-
+
All available albums
Alla tillgängliga album
@@ -3379,107 +3456,107 @@ Lyrics for "%1" by %2:
XmppSipPlugin
-
+
User Interaction
-
+
Host is unknown
-
+
Item not found
-
+
Authorization Error
-
+
Remote Stream Error
-
+
Remote Connection failed
-
+
Internal Server Error
-
+
System shutdown
-
+
Conflict
-
+
Unknown
-
+
No Compression Support
-
+
No Encryption Support
-
+
No Authorization Support
-
+
No Supported Feature
-
+
Add Friend
-
+
Enter Xmpp ID:
-
+
Add Friend...
-
+
XML Console...
-
+
I'm sorry -- I'm just an automatic presence used by Tomahawk Player (http://gettomahawk.com). If you are getting this message, the person you are trying to reach is probably not signed on, so please try again later!
-
+
Authorize User
-
+
Do you want to grant <b>%1</b> access to your Collection?
diff --git a/resources.qrc b/resources.qrc
index eed64bd59..602774165 100644
--- a/resources.qrc
+++ b/resources.qrc
@@ -87,6 +87,7 @@
data/images/station.png
data/images/new-additions.png
data/images/charts.png
+ data/images/new-releases.png
data/images/loved_playlist.png
data/images/dashboard.png
data/images/artist-icon.png
diff --git a/src/accounts/lastfm/LastFmAccount.cpp b/src/accounts/lastfm/LastFmAccount.cpp
index 7e4ac519f..61de6bec7 100644
--- a/src/accounts/lastfm/LastFmAccount.cpp
+++ b/src/accounts/lastfm/LastFmAccount.cpp
@@ -54,8 +54,6 @@ LastFmAccountFactory::icon() const
LastFmAccount::LastFmAccount( const QString& accountId )
: CustomAtticaAccount( accountId )
{
- m_infoPlugin = QWeakPointer< LastFmPlugin >( new LastFmPlugin( this ) );
-
setAccountFriendlyName( "Last.Fm" );
m_icon.load( RESPATH "images/lastfm-icon.png" );
@@ -70,12 +68,22 @@ LastFmAccount::LastFmAccount( const QString& accountId )
{
hookupResolver();
}
+
+
+ if ( infoPlugin() && Tomahawk::InfoSystem::InfoSystem::instance()->workerThread() )
+ {
+ infoPlugin().data()->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() );
+ Tomahawk::InfoSystem::InfoSystem::instance()->addInfoPlugin( infoPlugin() );
+ QMetaObject::invokeMethod( infoPlugin().data(), "init", Qt::QueuedConnection );
+ }
}
LastFmAccount::~LastFmAccount()
{
- delete m_infoPlugin.data();
+ if ( m_infoPlugin )
+ Tomahawk::InfoSystem::InfoSystem::instance()->removeInfoPlugin( infoPlugin() );
+
delete m_resolver.data();
}
@@ -155,10 +163,13 @@ LastFmAccount::icon() const
}
-InfoPlugin*
+InfoPluginPtr
LastFmAccount::infoPlugin()
{
- return m_infoPlugin.data();
+ if ( m_infoPlugin.isNull() )
+ m_infoPlugin = QWeakPointer< LastFmPlugin >( new LastFmPlugin( this ) );
+
+ return InfoPluginPtr( m_infoPlugin.data() );
}
bool
@@ -178,7 +189,8 @@ LastFmAccount::saveConfig()
setScrobble( m_configWidget.data()->scrobble() );
}
- m_infoPlugin.data()->settingsChanged();
+ if ( m_infoPlugin )
+ QTimer::singleShot( 0, m_infoPlugin.data(), SLOT( settingsChanged() ) );
}
diff --git a/src/accounts/lastfm/LastFmAccount.h b/src/accounts/lastfm/LastFmAccount.h
index 7988c37d6..e7fc5adf6 100644
--- a/src/accounts/lastfm/LastFmAccount.h
+++ b/src/accounts/lastfm/LastFmAccount.h
@@ -72,7 +72,7 @@ public:
virtual void authenticate();
virtual SipPlugin* sipPlugin() { return 0; }
- virtual Tomahawk::InfoSystem::InfoPlugin* infoPlugin();
+ virtual Tomahawk::InfoSystem::InfoPluginPtr infoPlugin();
virtual bool isAuthenticated() const;
diff --git a/src/accounts/lastfm/lastfmplugin.cpp b/src/accounts/lastfm/lastfmplugin.cpp
index 7e824fa53..3a9275323 100644
--- a/src/accounts/lastfm/lastfmplugin.cpp
+++ b/src/accounts/lastfm/lastfmplugin.cpp
@@ -46,17 +46,27 @@ LastFmPlugin::LastFmPlugin( LastFmAccount* account )
{
m_supportedGetTypes << InfoAlbumCoverArt << InfoArtistImages << InfoArtistSimilars << InfoArtistSongs << InfoChart << InfoChartCapabilities;
m_supportedPushTypes << InfoSubmitScrobble << InfoSubmitNowPlaying << InfoLove << InfoUnLove;
+}
+
+void
+LastFmPlugin::init()
+{
+ if ( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread() && thread() != Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() )
+ {
+ tDebug() << "Failure: move to the worker thread before running init";
+ return;
+ }
// Flush session key cache
// TODO WHY FLUSH
// m_account->setSessionKey( QByteArray() );
lastfm::ws::ApiKey = "7194b85b6d1f424fe1668173a78c0c4a";
lastfm::ws::SharedSecret = "ba80f1df6d27ae63e9cb1d33ccf2052f";
- lastfm::ws::Username = m_account->username();
+ lastfm::ws::Username = m_account.data()->username();
lastfm::setNetworkAccessManager( TomahawkUtils::nam() );
- m_pw = m_account->password();
+ m_pw = m_account.data()->password();
//HACK work around a bug in liblastfm---it doesn't create its config dir, so when it
// tries to write the track cache, it fails silently. until we have a fixed version, do this
@@ -707,23 +717,26 @@ LastFmPlugin::artistImagesReturned()
void
LastFmPlugin::settingsChanged()
{
- if ( !m_scrobbler && m_account->scrobble() )
+ if ( m_account.isNull() )
+ return;
+
+ if ( !m_scrobbler && m_account.data()->scrobble() )
{ // can simply create the scrobbler
- lastfm::ws::Username = m_account->username();
- m_pw = m_account->password();
+ lastfm::ws::Username = m_account.data()->username();
+ m_pw = m_account.data()->password();
createScrobbler();
}
- else if ( m_scrobbler && !m_account->scrobble() )
+ else if ( m_scrobbler && !m_account.data()->scrobble() )
{
delete m_scrobbler;
m_scrobbler = 0;
}
- else if ( m_account->username() != lastfm::ws::Username ||
- m_account->password() != m_pw )
+ else if ( m_account.data()->username() != lastfm::ws::Username ||
+ m_account.data()->password() != m_pw )
{
- lastfm::ws::Username = m_account->username();
- m_pw = m_account->password();
+ lastfm::ws::Username = m_account.data()->username();
+ m_pw = m_account.data()->password();
// credentials have changed, have to re-create scrobbler for them to take effect
if ( m_scrobbler )
{
@@ -740,12 +753,12 @@ void
LastFmPlugin::onAuthenticated()
{
QNetworkReply* authJob = dynamic_cast( sender() );
- if ( !authJob )
+ if ( !authJob || m_account.isNull() )
{
tLog() << Q_FUNC_INFO << "Help! No longer got a last.fm auth job!";
return;
}
-
+
if ( authJob->error() == QNetworkReply::NoError )
{
lastfm::XmlQuery lfm = lastfm::XmlQuery( authJob->readAll() );
@@ -753,16 +766,16 @@ LastFmPlugin::onAuthenticated()
if ( lfm.children( "error" ).size() > 0 )
{
tLog() << "Error from authenticating with Last.fm service:" << lfm.text();
- m_account->setSessionKey( QByteArray() );
+ m_account.data()->setSessionKey( QByteArray() );
}
else
{
lastfm::ws::SessionKey = lfm[ "session" ][ "key" ].text();
- m_account->setSessionKey( lastfm::ws::SessionKey.toLatin1() );
+ m_account.data()->setSessionKey( lastfm::ws::SessionKey.toLatin1() );
// qDebug() << "Got session key from last.fm";
- if ( m_account->scrobble() )
+ if ( m_account.data()->scrobble() )
m_scrobbler = new lastfm::Audioscrobbler( "thk" );
}
}
@@ -778,7 +791,10 @@ LastFmPlugin::onAuthenticated()
void
LastFmPlugin::createScrobbler()
{
- if ( m_account->sessionKey().isEmpty() ) // no session key, so get one
+ if ( m_account.isNull() )
+ return;
+
+ if ( m_account.data()->sessionKey().isEmpty() ) // no session key, so get one
{
qDebug() << "LastFmPlugin::createScrobbler Session key is empty";
QString authToken = TomahawkUtils::md5( ( lastfm::ws::Username.toLower() + TomahawkUtils::md5( m_pw.toUtf8() ) ).toUtf8() );
@@ -794,7 +810,7 @@ LastFmPlugin::createScrobbler()
else
{
qDebug() << "LastFmPlugin::createScrobbler Already have session key";
- lastfm::ws::SessionKey = m_account->sessionKey();
+ lastfm::ws::SessionKey = m_account.data()->sessionKey();
m_scrobbler = new lastfm::Audioscrobbler( "thk" );
}
diff --git a/src/accounts/lastfm/lastfmplugin.h b/src/accounts/lastfm/lastfmplugin.h
index c3c86bb96..4d9b7d530 100644
--- a/src/accounts/lastfm/lastfmplugin.h
+++ b/src/accounts/lastfm/lastfmplugin.h
@@ -49,6 +49,7 @@ public:
virtual ~LastFmPlugin();
public slots:
+ void init();
void settingsChanged();
void onAuthenticated();
@@ -79,7 +80,7 @@ private:
void dataError( Tomahawk::InfoSystem::InfoRequestData requestData );
- Accounts::LastFmAccount* m_account;
+ QWeakPointer< Accounts::LastFmAccount > m_account;
QList parseTrackList( QNetworkReply * reply );
lastfm::MutableTrack m_track;
diff --git a/src/accounts/spotify/SpotifyAccount.h b/src/accounts/spotify/SpotifyAccount.h
index 4379e6502..d60f26086 100644
--- a/src/accounts/spotify/SpotifyAccount.h
+++ b/src/accounts/spotify/SpotifyAccount.h
@@ -84,7 +84,7 @@ public:
virtual void saveConfig();
virtual QWidget* aclWidget() { return 0; }
- virtual InfoSystem::InfoPlugin* infoPlugin() { return 0; }
+ virtual Tomahawk::InfoSystem::InfoPluginPtr infoPlugin() { return Tomahawk::InfoSystem::InfoPluginPtr(); }
virtual SipPlugin* sipPlugin() { return 0; }
QString sendMessage( const QVariantMap& msg, QObject* receiver = 0, const QString& slot = QString() );
diff --git a/src/accounts/twitter/CMakeLists.txt b/src/accounts/twitter/CMakeLists.txt
index 253bd4e03..62bcf83b6 100644
--- a/src/accounts/twitter/CMakeLists.txt
+++ b/src/accounts/twitter/CMakeLists.txt
@@ -8,6 +8,7 @@ add_definitions( -DACCOUNTDLLEXPORT_PRO )
set( twitterAccountSources
twitteraccount.cpp
+ twitterinfoplugin.cpp
twitterconfigwidget.cpp
tomahawkoauthtwitter.cpp
sip/twittersip.cpp
@@ -15,6 +16,7 @@ set( twitterAccountSources
set( twitterAccountHeaders
twitteraccount.h
+ twitterinfoplugin.h
twitterconfigwidget.h
tomahawkoauthtwitter.h
sip/twittersip.h
diff --git a/src/accounts/twitter/twitteraccount.cpp b/src/accounts/twitter/twitteraccount.cpp
index 92eaab161..da1fb2467 100644
--- a/src/accounts/twitter/twitteraccount.cpp
+++ b/src/accounts/twitter/twitteraccount.cpp
@@ -21,6 +21,7 @@
#include "twitteraccount.h"
#include "twitterconfigwidget.h"
#include "accounts/twitter/tomahawkoauthtwitter.h"
+#include "libtomahawk/infosystem/infosystem.h"
#include "sip/SipPlugin.h"
@@ -47,9 +48,10 @@ TwitterAccountFactory::createAccount( const QString& accountId )
TwitterAccount::TwitterAccount( const QString &accountId )
: Account( accountId )
, m_isAuthenticated( false )
+ , m_isAuthenticating( false )
{
setAccountServiceName( "Twitter" );
- setTypes( AccountTypes( InfoType | SipType ) );
+ setTypes( AccountTypes( StatusPushType | SipType ) );
qDebug() << "Got cached peers:" << configuration() << configuration()[ "cachedpeers" ];
@@ -99,19 +101,57 @@ TwitterAccount::sipPlugin()
}
+Tomahawk::InfoSystem::InfoPluginPtr
+TwitterAccount::infoPlugin()
+{
+ if ( m_twitterInfoPlugin.isNull() )
+ m_twitterInfoPlugin = QWeakPointer< Tomahawk::InfoSystem::TwitterInfoPlugin >( new Tomahawk::InfoSystem::TwitterInfoPlugin( this ) );
+
+ return Tomahawk::InfoSystem::InfoPluginPtr( m_twitterInfoPlugin.data() );
+}
+
+
void
TwitterAccount::authenticate()
{
+ // Since we need to have a chance for deletion (via the infosystem) to work on the info plugin, we put this on the event loop
+ tDebug() << Q_FUNC_INFO;
+ QTimer::singleShot( 0, this, SLOT( authenticateSlot() ) );
+}
+
+
+void
+TwitterAccount::authenticateSlot()
+{
+ tDebug() << Q_FUNC_INFO;
+ if ( m_twitterInfoPlugin.isNull() )
+ {
+ if ( infoPlugin() && Tomahawk::InfoSystem::InfoSystem::instance()->workerThread() )
+ {
+ infoPlugin().data()->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() );
+ Tomahawk::InfoSystem::InfoSystem::instance()->addInfoPlugin( infoPlugin() );
+ QMetaObject::invokeMethod( infoPlugin().data(), "init", Qt::QueuedConnection );
+ }
+ }
+
+ if ( m_isAuthenticating )
+ {
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Already authenticating";
+ return;
+ }
+
tDebug() << Q_FUNC_INFO << "credentials: " << credentials().keys();
if ( credentials()[ "oauthtoken" ].toString().isEmpty() || credentials()[ "oauthtokensecret" ].toString().isEmpty() )
{
- qDebug() << "TwitterSipPlugin has empty Twitter credentials; not connecting";
+ tDebug() << Q_FUNC_INFO << "TwitterSipPlugin has empty Twitter credentials; not connecting";
return;
}
if ( refreshTwitterAuth() )
{
+ m_isAuthenticating = true;
+ tDebug() << Q_FUNC_INFO << "Verifying credentials";
QTweetAccountVerifyCredentials *credVerifier = new QTweetAccountVerifyCredentials( m_twitterAuth.data(), this );
connect( credVerifier, SIGNAL( parsedUser( const QTweetUser & ) ), SLOT( connectAuthVerifyReply( const QTweetUser & ) ) );
credVerifier->verify();
@@ -122,10 +162,17 @@ TwitterAccount::authenticate()
void
TwitterAccount::deauthenticate()
{
- if ( sipPlugin() )
+ tDebug() << Q_FUNC_INFO;
+
+ if ( m_twitterSipPlugin )
sipPlugin()->disconnectPlugin();
+ if ( m_twitterInfoPlugin )
+ Tomahawk::InfoSystem::InfoSystem::instance()->removeInfoPlugin( m_twitterInfoPlugin.data() );
+
m_isAuthenticated = false;
+ m_isAuthenticating = false;
+
emit nowDeauthenticated();
}
@@ -139,7 +186,7 @@ TwitterAccount::refreshTwitterAuth()
delete m_twitterAuth.data();
Q_ASSERT( TomahawkUtils::nam() != 0 );
- qDebug() << Q_FUNC_INFO << " with nam " << TomahawkUtils::nam();
+ tDebug() << Q_FUNC_INFO << " with nam " << TomahawkUtils::nam();
m_twitterAuth = QWeakPointer< TomahawkOAuthTwitter >( new TomahawkOAuthTwitter( TomahawkUtils::nam(), this ) );
if( m_twitterAuth.isNull() )
@@ -155,6 +202,7 @@ TwitterAccount::refreshTwitterAuth()
void
TwitterAccount::connectAuthVerifyReply( const QTweetUser &user )
{
+ m_isAuthenticating = false;
if ( user.id() == 0 )
{
qDebug() << "TwitterAccount could not authenticate to Twitter";
@@ -174,6 +222,8 @@ TwitterAccount::connectAuthVerifyReply( const QTweetUser &user )
emit nowAuthenticated( m_twitterAuth, user );
}
}
+
+
QPixmap
TwitterAccount::icon() const {
return QPixmap( ":/twitter-icon.png" );
diff --git a/src/accounts/twitter/twitteraccount.h b/src/accounts/twitter/twitteraccount.h
index 16dcf6242..2ec8e4079 100644
--- a/src/accounts/twitter/twitteraccount.h
+++ b/src/accounts/twitter/twitteraccount.h
@@ -25,6 +25,7 @@
#include "tomahawkoauthtwitter.h"
#include "sip/twittersip.h"
+#include "twitterinfoplugin.h"
#include "accounts/accountdllmacro.h"
#include "accounts/Account.h"
@@ -49,7 +50,7 @@ public:
QString factoryId() const { return "twitteraccount"; }
QString description() const { return tr( "Connect to your Twitter followers." ); }
QPixmap icon() const { return QPixmap( ":/twitter-icon.png" ); }
- AccountTypes types() const { return AccountTypes( SipType ); };
+ AccountTypes types() const { return AccountTypes( SipType | StatusPushType ); };
Account* createAccount( const QString& pluginId = QString() );
};
@@ -69,7 +70,7 @@ public:
ConnectionState connectionState() const;
- Tomahawk::InfoSystem::InfoPlugin* infoPlugin() { return 0; }
+ Tomahawk::InfoSystem::InfoPluginPtr infoPlugin();
SipPlugin* sipPlugin();
QWidget* configurationWidget() { return m_configWidget.data(); }
@@ -83,15 +84,18 @@ signals:
void nowDeauthenticated();
private slots:
+ void authenticateSlot();
void configDialogAuthedSignalSlot( bool authed );
void connectAuthVerifyReply( const QTweetUser &user );
private:
QIcon m_icon;
bool m_isAuthenticated;
+ bool m_isAuthenticating;
QWeakPointer< TomahawkOAuthTwitter > m_twitterAuth;
QWeakPointer< TwitterConfigWidget > m_configWidget;
QWeakPointer< TwitterSipPlugin > m_twitterSipPlugin;
+ QWeakPointer< Tomahawk::InfoSystem::TwitterInfoPlugin > m_twitterInfoPlugin;
// for settings access
friend class TwitterConfigWidget;
diff --git a/src/accounts/twitter/twitterinfoplugin.cpp b/src/accounts/twitter/twitterinfoplugin.cpp
new file mode 100644
index 000000000..1de65a9ef
--- /dev/null
+++ b/src/accounts/twitter/twitterinfoplugin.cpp
@@ -0,0 +1,174 @@
+/* === This file is part of Tomahawk Player - ===
+ *
+ * Copyright 2012, Dominik Schmidt
+ * Copyright 2012, Jeff Mitchell
+ *
+ * Tomahawk is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tomahawk is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tomahawk. If not, see .
+ */
+
+
+#include "twitterinfoplugin.h"
+
+#include "accounts/twitter/twitteraccount.h"
+
+#include
+#include
+
+#include "globalactionmanager.h"
+#include "utils/logger.h"
+
+namespace Tomahawk
+{
+
+namespace InfoSystem
+{
+
+TwitterInfoPlugin::TwitterInfoPlugin( Tomahawk::Accounts::TwitterAccount* account )
+ : m_account( account )
+{
+ m_supportedPushTypes << InfoLove;
+}
+
+
+void
+TwitterInfoPlugin::init()
+{
+ if ( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread() && thread() != Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() )
+ {
+ tDebug() << "Failure: move to the worker thread before running init";
+ return;
+ }
+
+ QVariantHash credentials = m_account->credentials();
+ if ( credentials[ "oauthtoken" ].toString().isEmpty() || credentials[ "oauthtokensecret" ].toString().isEmpty() )
+ {
+ tDebug() << "TwitterInfoPlugin has empty Twitter credentials; not connecting";
+ return;
+ }
+
+ if ( refreshTwitterAuth() )
+ {
+ QTweetAccountVerifyCredentials *credVerifier = new QTweetAccountVerifyCredentials( m_twitterAuth.data(), this );
+ connect( credVerifier, SIGNAL( parsedUser( const QTweetUser & ) ), SLOT( connectAuthVerifyReply( const QTweetUser & ) ) );
+ credVerifier->verify();
+ }
+}
+
+
+TwitterInfoPlugin::~TwitterInfoPlugin()
+{
+ tDebug() << Q_FUNC_INFO;
+}
+
+
+bool
+TwitterInfoPlugin::refreshTwitterAuth()
+{
+ tDebug() << Q_FUNC_INFO << " begin" << this;
+ if( !m_twitterAuth.isNull() )
+ delete m_twitterAuth.data();
+
+ Q_ASSERT( TomahawkUtils::nam() != 0 );
+ tDebug() << Q_FUNC_INFO << " with nam " << TomahawkUtils::nam() << this;
+ m_twitterAuth = QWeakPointer< TomahawkOAuthTwitter >( new TomahawkOAuthTwitter( TomahawkUtils::nam(), this ) );
+
+ if( m_twitterAuth.isNull() )
+ return false;
+
+ m_twitterAuth.data()->setOAuthToken( m_account->credentials()[ "oauthtoken" ].toString().toLatin1() );
+ m_twitterAuth.data()->setOAuthTokenSecret( m_account->credentials()[ "oauthtokensecret" ].toString().toLatin1() );
+
+ return true;
+}
+
+
+void
+TwitterInfoPlugin::connectAuthVerifyReply( const QTweetUser &user )
+{
+ if ( user.id() == 0 )
+ {
+ tDebug() << "TwitterInfoPlugin could not authenticate to Twitter" << this;
+ deleteLater();
+ return;
+ }
+ else
+ {
+ tDebug() << "TwitterInfoPlugin successfully authenticated to Twitter" << this;
+ return;
+ }
+}
+
+
+void
+TwitterInfoPlugin::pushInfo( Tomahawk::InfoSystem::InfoPushData pushData )
+{
+ tDebug() << Q_FUNC_INFO;
+ if ( !isValid() )
+ {
+ tDebug() << Q_FUNC_INFO << "Plugin not valid, deleting and returning";
+ deleteLater();
+ return;
+ }
+
+ Tomahawk::InfoSystem::PushInfoPair pushInfoPair = pushData.infoPair;
+
+ if ( !pushInfoPair.second.canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
+ {
+ tDebug() << Q_FUNC_INFO << "Cannot convert input into an info string hash";
+ return;
+ }
+
+ Tomahawk::InfoSystem::InfoStringHash info = pushInfoPair.second.value< Tomahawk::InfoSystem::InfoStringHash >();
+
+ QString msg = tr( "Listening to \"%1\" by %2 and loving it! %3" )
+ .arg( info[ "title" ] )
+ .arg( info[ "artist" ] )
+ .arg( pushInfoPair.first.contains( "shorturl" ) ?
+ pushInfoPair.first[ "shorturl" ].toUrl().toString() :
+ GlobalActionManager::instance()->openLink( info[ "title" ], info[ "artist" ], info[ "album" ] ).toString() );
+
+ QTweetStatusUpdate *statUpdate = new QTweetStatusUpdate( m_twitterAuth.data(), this );
+ connect( statUpdate, SIGNAL( postedStatus(const QTweetStatus &) ), SLOT( postLovedStatusUpdateReply(const QTweetStatus &) ) );
+ connect( statUpdate, SIGNAL( error(QTweetNetBase::ErrorCode, const QString&) ), SLOT( postLovedStatusUpdateError(QTweetNetBase::ErrorCode, const QString &) ) );
+ tDebug() << Q_FUNC_INFO << "Posting message: " << msg;
+ statUpdate->post( msg );
+}
+
+
+void
+TwitterInfoPlugin::postLovedStatusUpdateReply( const QTweetStatus& status )
+{
+ if ( status.id() == 0 )
+ tDebug() << Q_FUNC_INFO << "Failed to post loved status";
+ else
+ tDebug() << Q_FUNC_INFO << "Successfully posted loved status";
+}
+
+
+void
+TwitterInfoPlugin::postLovedStatusUpdateError( QTweetNetBase::ErrorCode code, const QString& errorMsg )
+{
+ tDebug() << Q_FUNC_INFO << "Error posting love message, error code is " << code << ", error message is " << errorMsg;
+}
+
+
+bool
+TwitterInfoPlugin::isValid() const
+{
+ return !m_twitterAuth.isNull();
+}
+
+}
+
+}
\ No newline at end of file
diff --git a/src/accounts/twitter/twitterinfoplugin.h b/src/accounts/twitter/twitterinfoplugin.h
new file mode 100644
index 000000000..77242754d
--- /dev/null
+++ b/src/accounts/twitter/twitterinfoplugin.h
@@ -0,0 +1,80 @@
+/* === This file is part of Tomahawk Player - ===
+ *
+ * Copyright 2012, Dominik Schmidt
+ * Copyright 2012, Jeff Mitchell
+ *
+ * Tomahawk is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tomahawk is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tomahawk. If not, see .
+ */
+
+#ifndef TWITTERINFOPLUGIN_H
+#define TWITTERINFOPLUGIN_H
+
+#include "infosystem/infosystem.h"
+#include "accounts/twitter/tomahawkoauthtwitter.h"
+
+#include
+#include
+#include
+
+namespace Tomahawk {
+
+ namespace Accounts {
+ class TwitterAccount;
+ }
+
+ namespace InfoSystem {
+
+ class TwitterInfoPlugin : public InfoPlugin
+ {
+ Q_OBJECT
+
+ public:
+ TwitterInfoPlugin( Tomahawk::Accounts::TwitterAccount* account );
+ virtual ~TwitterInfoPlugin();
+
+ public slots:
+ void init();
+ void notInCacheSlot( const Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
+ {
+ Q_UNUSED( criteria );
+ Q_UNUSED( requestData );
+ }
+
+ protected slots:
+ void pushInfo( Tomahawk::InfoSystem::InfoPushData pushData );
+ void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
+ {
+ Q_UNUSED( requestData );
+ }
+
+ private slots:
+ void connectAuthVerifyReply( const QTweetUser &user );
+ void postLovedStatusUpdateReply( const QTweetStatus& status );
+ void postLovedStatusUpdateError( QTweetNetBase::ErrorCode code, const QString& errorMsg );
+
+ private:
+ bool refreshTwitterAuth();
+ bool isValid() const;
+
+ Tomahawk::Accounts::TwitterAccount* m_account;
+ QWeakPointer< TomahawkOAuthTwitter > m_twitterAuth;
+ };
+
+ }
+
+}
+
+#endif // TWITTERINFOPLUGIN_H
+
+struct A;
diff --git a/src/accounts/xmpp/XmppInfoPlugin.cpp b/src/accounts/xmpp/XmppInfoPlugin.cpp
index 728ba4cf5..b1d822a68 100644
--- a/src/accounts/xmpp/XmppInfoPlugin.cpp
+++ b/src/accounts/xmpp/XmppInfoPlugin.cpp
@@ -1,6 +1,7 @@
/* === This file is part of Tomahawk Player - ===
*
* Copyright 2012, Dominik Schmidt
+ * Copyright 2012, Jeff Mitchell
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,31 +24,18 @@
#include "sip/xmppsip.h"
#include "utils/logger.h"
-#include
-#include
-#include
-
-#include
// remove now playing status after PAUSE_TIMEOUT seconds
-static const int PAUSE_TIMEOUT = 60;
+static const int PAUSE_TIMEOUT = 10;
-Tomahawk::InfoSystem::XmppInfoPlugin::XmppInfoPlugin(XmppSipPlugin* sipPlugin)
+Tomahawk::InfoSystem::XmppInfoPlugin::XmppInfoPlugin( XmppSipPlugin* sipPlugin )
: m_sipPlugin( sipPlugin )
- , m_pubSubManager( 0 )
, m_pauseTimer( this )
{
Q_ASSERT( sipPlugin->m_client );
m_supportedPushTypes << InfoNowPlaying << InfoNowPaused << InfoNowResumed << InfoNowStopped;
- m_pubSubManager = new Jreen::PubSub::Manager( sipPlugin->m_client );
- m_pubSubManager->addEntityType< Jreen::Tune >();
-
- // Clear status
- Jreen::Tune::Ptr tune( new Jreen::Tune() );
- m_pubSubManager->publishItems(QList() << tune, Jreen::JID());
-
m_pauseTimer.setSingleShot( true );
connect( &m_pauseTimer, SIGNAL( timeout() ),
this, SLOT( audioStopped() ) );
@@ -56,24 +44,28 @@ Tomahawk::InfoSystem::XmppInfoPlugin::XmppInfoPlugin(XmppSipPlugin* sipPlugin)
Tomahawk::InfoSystem::XmppInfoPlugin::~XmppInfoPlugin()
{
- //Note: the next two lines don't currently work, because the deletion wipes out internally posted events, need to talk to euro about a fix
- Jreen::Tune::Ptr tune( new Jreen::Tune() );
- m_pubSubManager->publishItems(QList() << tune, Jreen::JID());
- m_pubSubManager->deleteLater();
+}
+
+
+void
+Tomahawk::InfoSystem::XmppInfoPlugin::init()
+{
+ if ( QThread::currentThread() != Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() )
+ {
+ QMetaObject::invokeMethod( this, "init", Qt::QueuedConnection );
+ return;
+ }
+
+ if ( m_sipPlugin.isNull() )
+ return;
+
+ connect( this, SIGNAL( publishTune( QUrl, Tomahawk::InfoSystem::InfoStringHash ) ), m_sipPlugin.data(), SLOT( publishTune( QUrl, Tomahawk::InfoSystem::InfoStringHash ) ), Qt::QueuedConnection );
}
void
Tomahawk::InfoSystem::XmppInfoPlugin::pushInfo( Tomahawk::InfoSystem::InfoPushData pushData )
{
- tDebug() << Q_FUNC_INFO << m_sipPlugin->m_client->jid().full();
-
- if( m_sipPlugin->m_account->configuration().value("publishtracks").toBool() == false )
- {
- tDebug() << Q_FUNC_INFO << m_sipPlugin->m_client->jid().full() << "Not publishing now playing info (disabled in account config)";
- return;
- }
-
switch ( pushData.type )
{
case InfoNowPlaying:
@@ -108,8 +100,7 @@ Tomahawk::InfoSystem::XmppInfoPlugin::audioStarted( const Tomahawk::InfoSystem::
QVariantMap map = pushInfoPair.second.toMap();
if ( map.contains( "private" ) && map[ "private" ] == TomahawkSettings::FullyPrivate )
{
- Jreen::Tune::Ptr tune( new Jreen::Tune() );
- m_pubSubManager->publishItems( QList() << tune, Jreen::JID() );
+ emit publishTune( QUrl(), Tomahawk::InfoSystem::InfoStringHash() );
return;
}
@@ -120,42 +111,25 @@ Tomahawk::InfoSystem::XmppInfoPlugin::audioStarted( const Tomahawk::InfoSystem::
}
Tomahawk::InfoSystem::InfoStringHash info = map[ "trackinfo" ].value< Tomahawk::InfoSystem::InfoStringHash >();
- tDebug() << Q_FUNC_INFO << m_sipPlugin->m_client->jid().full() << info;
-
- Jreen::Tune::Ptr tune( new Jreen::Tune() );
- tune->setTitle( info.value( "title" ) );
- tune->setArtist( info.value( "artist" ) );
- tune->setLength( info.value("duration").toInt() );
- tune->setTrack( info.value("albumpos") );
+ QUrl url;
if ( pushInfoPair.first.contains( "shorturl" ) )
- tune->setUri( pushInfoPair.first[ "shorturl" ].toUrl() );
+ url = pushInfoPair.first[ "shorturl" ].toUrl();
else
- tune->setUri( GlobalActionManager::instance()->openLink( info.value( "title" ), info.value( "artist" ), info.value( "album" ) ) );
+ url = GlobalActionManager::instance()->openLink( info.value( "title" ), info.value( "artist" ), info.value( "album" ) );
- tDebug() << Q_FUNC_INFO << "Setting URI of " << tune->uri().toString();
- //TODO: provide a rating once available in Tomahawk
- tune->setRating( 10 );
-
- //TODO: it would be nice to set Spotify, Dilandau etc here, but not the jabber ids of friends
- tune->setSource( "Tomahawk" );
-
- m_pubSubManager->publishItems( QList() << tune, Jreen::JID() );
+ emit publishTune( url, info );
}
void
Tomahawk::InfoSystem::XmppInfoPlugin::audioPaused()
{
- tDebug() << Q_FUNC_INFO << m_sipPlugin->m_client->jid().full();
}
void
Tomahawk::InfoSystem::XmppInfoPlugin::audioStopped()
{
- tDebug() << Q_FUNC_INFO << m_sipPlugin->m_client->jid().full();
-
- Jreen::Tune::Ptr tune( new Jreen::Tune() );
- m_pubSubManager->publishItems(QList() << tune, Jreen::JID());
+ emit publishTune( QUrl(), Tomahawk::InfoSystem::InfoStringHash() );
}
diff --git a/src/accounts/xmpp/XmppInfoPlugin.h b/src/accounts/xmpp/XmppInfoPlugin.h
index 223167524..c15f1571f 100644
--- a/src/accounts/xmpp/XmppInfoPlugin.h
+++ b/src/accounts/xmpp/XmppInfoPlugin.h
@@ -1,6 +1,7 @@
/* === This file is part of Tomahawk Player - ===
*
* Copyright 2012, Dominik Schmidt
+ * Copyright 2012, Jeff Mitchell
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,12 +24,6 @@
#include
-namespace Jreen {
- namespace PubSub {
- class Manager;
- }
-}
-
class XmppSipPlugin;
namespace Tomahawk {
@@ -43,7 +38,11 @@ namespace Tomahawk {
XmppInfoPlugin(XmppSipPlugin* parent);
virtual ~XmppInfoPlugin();
+ signals:
+ void publishTune( QUrl url, Tomahawk::InfoSystem::InfoStringHash trackInfo );
+
public slots:
+ void init();
void notInCacheSlot( const Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
protected slots:
@@ -56,8 +55,7 @@ namespace Tomahawk {
void audioPaused();
private:
- XmppSipPlugin* m_sipPlugin;
- Jreen::PubSub::Manager* m_pubSubManager;
+ QWeakPointer< XmppSipPlugin > m_sipPlugin;
QTimer m_pauseTimer;
};
diff --git a/src/accounts/xmpp/sip/xmppsip.cpp b/src/accounts/xmpp/sip/xmppsip.cpp
index 10fb265b4..a36d3fb1e 100644
--- a/src/accounts/xmpp/sip/xmppsip.cpp
+++ b/src/accounts/xmpp/sip/xmppsip.cpp
@@ -35,6 +35,7 @@
#include
#include
#include
+#include
#include
#include
@@ -86,11 +87,11 @@ JreenMessageHandler(QtMsgType type, const char *msg)
XmppSipPlugin::XmppSipPlugin( Account *account )
: SipPlugin( account )
- , m_infoPlugin( 0 )
, m_state( Account::Disconnected )
#ifndef ENABLE_HEADLESS
, m_menu( 0 )
, m_xmlConsole( 0 )
+ , m_pubSubManager( 0 )
#endif
{
Jreen::Logger::addHandler( JreenMessageHandler );
@@ -161,11 +162,22 @@ XmppSipPlugin::XmppSipPlugin( Account *account )
#ifndef ENABLE_HEADLESS
connect(m_avatarManager, SIGNAL(newAvatar(QString)), SLOT(onNewAvatar(QString)));
#endif
+
+ m_pubSubManager = new Jreen::PubSub::Manager( m_client );
+ m_pubSubManager->addEntityType< Jreen::Tune >();
+
+ // Clear status
+ Jreen::Tune::Ptr tune( new Jreen::Tune() );
+ m_pubSubManager->publishItems(QList() << tune, Jreen::JID());
+
}
XmppSipPlugin::~XmppSipPlugin()
{
- delete m_infoPlugin;
+ //Note: the next two lines don't currently work, because the deletion wipes out internally posted events, need to talk to euro about a fix
+ Jreen::Tune::Ptr tune( new Jreen::Tune() );
+ m_pubSubManager->publishItems(QList() << tune, Jreen::JID());
+ delete m_pubSubManager;
delete m_avatarManager;
delete m_roster;
#ifndef ENABLE_HEADLESS
@@ -175,10 +187,13 @@ XmppSipPlugin::~XmppSipPlugin()
}
-InfoSystem::InfoPlugin*
+InfoSystem::InfoPluginPtr
XmppSipPlugin::infoPlugin()
{
- return m_infoPlugin;
+ if ( m_infoPlugin.isNull() )
+ m_infoPlugin = QWeakPointer< Tomahawk::InfoSystem::XmppInfoPlugin >( new Tomahawk::InfoSystem::XmppInfoPlugin( this ) );
+
+ return InfoSystem::InfoPluginPtr( m_infoPlugin.data() );
}
@@ -241,6 +256,8 @@ XmppSipPlugin::disconnectPlugin()
m_peers.clear();
+ publishTune( QUrl(), Tomahawk::InfoSystem::InfoStringHash() );
+
m_client->disconnectFromServer( true );
m_state = Account::Disconnecting;
emit stateChanged( m_state );
@@ -272,10 +289,11 @@ XmppSipPlugin::onConnect()
m_roster->load();
// load XmppInfoPlugin
- if( !m_infoPlugin )
+ if ( infoPlugin() && Tomahawk::InfoSystem::InfoSystem::instance()->workerThread() )
{
- m_infoPlugin = new Tomahawk::InfoSystem::XmppInfoPlugin( this );
- InfoSystem::InfoSystem::instance()->addInfoPlugin( m_infoPlugin );
+ infoPlugin().data()->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() );
+ Tomahawk::InfoSystem::InfoSystem::instance()->addInfoPlugin( infoPlugin() );
+ QMetaObject::invokeMethod( infoPlugin().data(), "init", Qt::QueuedConnection );
}
//FIXME: this implementation is totally broken atm, so it's disabled to avoid harm :P
@@ -340,6 +358,9 @@ XmppSipPlugin::onDisconnect( Jreen::Client::DisconnectReason reason )
{
handlePeerStatus(peer, Jreen::Presence::Unavailable);
}
+
+ if ( !m_infoPlugin.isNull() )
+ Tomahawk::InfoSystem::InfoSystem::instance()->removeInfoPlugin( infoPlugin() );
}
@@ -509,6 +530,41 @@ XmppSipPlugin::showAddFriendDialog()
}
+void
+XmppSipPlugin::publishTune( const QUrl& url, const InfoSystem::InfoStringHash& trackInfo )
+{
+ if( m_account->configuration().value("publishtracks").toBool() == false )
+ {
+ tDebug() << Q_FUNC_INFO << m_client->jid().full() << "Not publishing now playing info (disabled in account config)";
+ return;
+ }
+
+ if ( trackInfo.isEmpty() )
+ {
+ Jreen::Tune::Ptr tune( new Jreen::Tune() );
+ m_pubSubManager->publishItems(QList() << tune, Jreen::JID());
+ }
+
+ Jreen::Tune::Ptr tune( new Jreen::Tune() );
+
+ tune->setTitle( trackInfo.value( "title" ) );
+ tune->setArtist( trackInfo.value( "artist" ) );
+ tune->setLength( trackInfo.value("duration").toInt() );
+ tune->setTrack( trackInfo.value("albumpos") );
+
+ //TODO: provide a rating once available in Tomahawk
+ tune->setRating( 10 );
+
+ //TODO: it would be nice to set Spotify, Dilandau etc here, but not the jabber ids of friends
+ tune->setSource( "Tomahawk" );
+
+ tune->setUri( url );
+ tDebug() << Q_FUNC_INFO << "Setting URI of " << tune->uri().toString();
+
+ m_pubSubManager->publishItems( QList() << tune, Jreen::JID() );
+}
+
+
QString
XmppSipPlugin::defaultSuffix() const
{
diff --git a/src/accounts/xmpp/sip/xmppsip.h b/src/accounts/xmpp/sip/xmppsip.h
index 33b7b61dd..1e570928d 100644
--- a/src/accounts/xmpp/sip/xmppsip.h
+++ b/src/accounts/xmpp/sip/xmppsip.h
@@ -42,6 +42,7 @@
#include
#include
#include
+#include
#ifndef ENABLE_HEADLESS
#include
@@ -67,7 +68,7 @@ public:
//FIXME: Make this more correct
virtual bool isValid() const { return true; }
- Tomahawk::InfoSystem::InfoPlugin* infoPlugin();
+ Tomahawk::InfoSystem::InfoPluginPtr infoPlugin();
#ifndef ENABLE_HEADLESS
virtual QMenu* menu();
@@ -92,6 +93,7 @@ public slots:
void broadcastMsg( const QString &msg );
virtual void addContact( const QString &jid, const QString& msg = QString() );
void showAddFriendDialog();
+ void publishTune( const QUrl &url, const Tomahawk::InfoSystem::InfoStringHash &trackInfo );
protected:
virtual QString defaultSuffix() const;
@@ -131,7 +133,7 @@ private:
int m_currentPort;
QString m_currentResource;
- Tomahawk::InfoSystem::InfoPlugin* m_infoPlugin;
+ QWeakPointer< Tomahawk::InfoSystem::XmppInfoPlugin> m_infoPlugin;
Tomahawk::Accounts::Account::ConnectionState m_state;
// sort out
@@ -147,6 +149,7 @@ private:
#endif
enum IqContext { NoContext, RequestDisco, RequestedDisco, SipMessageSent, RequestedVCard, RequestVersion, RequestedVersion };
AvatarManager *m_avatarManager;
+ Jreen::PubSub::Manager* m_pubSubManager;
};
#endif
diff --git a/src/accounts/xmpp/xmppaccount.cpp b/src/accounts/xmpp/xmppaccount.cpp
index aafabd7f7..1d40ae397 100644
--- a/src/accounts/xmpp/xmppaccount.cpp
+++ b/src/accounts/xmpp/xmppaccount.cpp
@@ -91,13 +91,13 @@ XmppAccount::saveConfig()
}
-InfoSystem::InfoPlugin*
+InfoSystem::InfoPluginPtr
XmppAccount::infoPlugin()
{
if( !m_xmppSipPlugin.isNull() )
return m_xmppSipPlugin.data()->infoPlugin();
- return 0;
+ return InfoSystem::InfoPluginPtr();
}
diff --git a/src/accounts/xmpp/xmppaccount.h b/src/accounts/xmpp/xmppaccount.h
index 7dde11c49..03037aacc 100644
--- a/src/accounts/xmpp/xmppaccount.h
+++ b/src/accounts/xmpp/xmppaccount.h
@@ -51,7 +51,7 @@ public:
QString description() const { return tr( "Log on to your Jabber/XMPP account to connect to your friends" ); }
QString factoryId() const { return "xmppaccount"; }
QPixmap icon() const { return QPixmap( ":/xmpp-icon.png" ); }
- AccountTypes types() const { return AccountTypes( SipType ); };
+ AccountTypes types() const { return AccountTypes( SipType | StatusPushType ); };
Account* createAccount( const QString& pluginId = QString() );
};
@@ -69,7 +69,7 @@ public:
void deauthenticate();
bool isAuthenticated() const;
- Tomahawk::InfoSystem::InfoPlugin* infoPlugin();
+ Tomahawk::InfoSystem::InfoPluginPtr infoPlugin();
SipPlugin* sipPlugin();
diff --git a/src/accounts/zeroconf/zeroconfaccount.h b/src/accounts/zeroconf/zeroconfaccount.h
index 29a6673fd..4733cf22b 100644
--- a/src/accounts/zeroconf/zeroconfaccount.h
+++ b/src/accounts/zeroconf/zeroconfaccount.h
@@ -64,7 +64,7 @@ public:
bool isAuthenticated() const;
ConnectionState connectionState() const;
- Tomahawk::InfoSystem::InfoPlugin* infoPlugin() { return 0; }
+ virtual Tomahawk::InfoSystem::InfoPluginPtr infoPlugin() { return Tomahawk::InfoSystem::InfoPluginPtr(); }
SipPlugin* sipPlugin();
QWidget* configurationWidget() { return 0; }
diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt
index b634f8026..230d4a792 100644
--- a/src/libtomahawk/CMakeLists.txt
+++ b/src/libtomahawk/CMakeLists.txt
@@ -135,6 +135,7 @@ set( libGuiSources
widgets/playlisttypeselectordlg.cpp
widgets/welcomewidget.cpp
widgets/whatshotwidget.cpp
+ widgets/newreleaseswidget.cpp
widgets/ChartDataLoader.cpp
widgets/RecentlyPlayedPlaylistsModel.cpp
widgets/RecentPlaylistsModel.cpp
@@ -252,6 +253,7 @@ set( libSources
infosystem/infoplugins/generic/echonestplugin.cpp
infosystem/infoplugins/generic/chartsplugin.cpp
+ infosystem/infoplugins/generic/newreleasesplugin.cpp
infosystem/infoplugins/generic/spotifyPlugin.cpp
infosystem/infoplugins/generic/hypemPlugin.cpp
infosystem/infoplugins/generic/musixmatchplugin.cpp
@@ -290,6 +292,7 @@ set( libSources
utils/logger.cpp
utils/qnr_iodevicestream.cpp
utils/xspfloader.cpp
+ utils/tomahawkcache.cpp
thirdparty/kdsingleapplicationguard/kdsingleapplicationguard.cpp
thirdparty/kdsingleapplicationguard/kdsharedmemorylocker.cpp
@@ -303,6 +306,7 @@ set( libUI ${libUI}
widgets/searchwidget.ui
widgets/welcomewidget.ui
widgets/whatshotwidget.ui
+ widgets/newreleaseswidget.ui
widgets/SocialPlaylistWidget.ui
widgets/infowidgets/sourceinfowidget.ui
widgets/infowidgets/ArtistInfoWidget.ui
diff --git a/src/libtomahawk/accounts/Account.cpp b/src/libtomahawk/accounts/Account.cpp
index eda98702f..b51d7eab1 100644
--- a/src/libtomahawk/accounts/Account.cpp
+++ b/src/libtomahawk/accounts/Account.cpp
@@ -37,7 +37,7 @@ accountTypeToString( AccountType type )
case InfoType:
case StatusPushType:
return QObject::tr( "Status Updaters" );
- default:
+ case NoType:
return QString();
}
diff --git a/src/libtomahawk/accounts/Account.h b/src/libtomahawk/accounts/Account.h
index 43e98ff67..66349a724 100644
--- a/src/libtomahawk/accounts/Account.h
+++ b/src/libtomahawk/accounts/Account.h
@@ -31,16 +31,13 @@
#include "dllmacro.h"
#include "tomahawksettings.h"
+#include "libtomahawk/infosystem/infosystem.h"
+
class SipPlugin;
namespace Tomahawk
{
-namespace InfoSystem
-{
- class InfoPlugin;
-}
-
namespace Accounts
{
@@ -100,7 +97,7 @@ public:
virtual QString errorMessage() const { QMutexLocker locker( &m_mutex ); return m_cachedError; }
- virtual Tomahawk::InfoSystem::InfoPlugin* infoPlugin() = 0;
+ virtual Tomahawk::InfoSystem::InfoPluginPtr infoPlugin() = 0;
virtual SipPlugin* sipPlugin() = 0;
AccountTypes types() const;
diff --git a/src/libtomahawk/accounts/AccountManager.cpp b/src/libtomahawk/accounts/AccountManager.cpp
index eb1f7b43d..7c3f68035 100644
--- a/src/libtomahawk/accounts/AccountManager.cpp
+++ b/src/libtomahawk/accounts/AccountManager.cpp
@@ -51,14 +51,7 @@ AccountManager::AccountManager( QObject *parent )
{
s_instance = this;
- connect( TomahawkSettings::instance(), SIGNAL( changed() ), SLOT( onSettingsChanged() ) );
-
- loadPluginFactories( findPluginFactories() );
-
- // We include the resolver factory manually, not in a plugin
- ResolverAccountFactory* f = new ResolverAccountFactory();
- m_accountFactories[ f->factoryId() ] = f;
- registerAccountFactoryForFilesystem( f );
+ QTimer::singleShot( 0, this, SLOT( init() ) );
}
@@ -72,6 +65,29 @@ AccountManager::~AccountManager()
}
+void
+AccountManager::init()
+{
+ if ( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().isNull() )
+ {
+ //We need the info system worker to be alive so that we can move info plugins into its thread
+ QTimer::singleShot( 0, this, SLOT( init() ) );
+ return;
+ }
+
+ connect( TomahawkSettings::instance(), SIGNAL( changed() ), SLOT( onSettingsChanged() ) );
+
+ loadPluginFactories( findPluginFactories() );
+
+ // We include the resolver factory manually, not in a plugin
+ ResolverAccountFactory* f = new ResolverAccountFactory();
+ m_accountFactories[ f->factoryId() ] = f;
+ registerAccountFactoryForFilesystem( f );
+
+ emit ready();
+}
+
+
QStringList
AccountManager::findPluginFactories()
{
@@ -180,6 +196,7 @@ AccountManager::loadPluginFactory( const QString& path )
void
AccountManager::enableAccount( Account* account )
{
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO;
if ( account->enabled() )
return;
@@ -195,6 +212,7 @@ AccountManager::enableAccount( Account* account )
void
AccountManager::disableAccount( Account* account )
{
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO;
if ( !account->enabled() )
return;
@@ -209,6 +227,7 @@ AccountManager::disableAccount( Account* account )
void
AccountManager::connectAll()
{
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO;
foreach( Account* acc, m_accounts )
{
acc->authenticate();
@@ -222,6 +241,7 @@ AccountManager::connectAll()
void
AccountManager::disconnectAll()
{
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO;
foreach( Account* acc, m_enabledAccounts )
acc->deauthenticate();
@@ -234,6 +254,7 @@ AccountManager::disconnectAll()
void
AccountManager::toggleAccountsConnected()
{
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO;
if ( m_connected )
disconnectAll();
else
@@ -297,9 +318,6 @@ AccountManager::addAccount( Account* account )
if ( account->types() & Accounts::StatusPushType )
m_accountsByAccountType[ Accounts::StatusPushType ].append( account );
- if ( account->infoPlugin() )
- InfoSystem::InfoSystem::instance()->addInfoPlugin( account->infoPlugin() );
-
emit added( account );
}
@@ -370,6 +388,7 @@ AccountManager::hookupAccount( Account* account ) const
void
AccountManager::hookupAndEnable( Account* account, bool startup )
{
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO;
SipPlugin* p = account->sipPlugin();
if ( p )
SipHandler::instance()->hookUpPlugin( p );
diff --git a/src/libtomahawk/accounts/AccountManager.h b/src/libtomahawk/accounts/AccountManager.h
index 16dcf72fc..1e1820476 100644
--- a/src/libtomahawk/accounts/AccountManager.h
+++ b/src/libtomahawk/accounts/AccountManager.h
@@ -43,7 +43,7 @@ public:
explicit AccountManager( QObject *parent );
virtual ~AccountManager();
-
+
void loadFromConfig();
void initSIP();
@@ -84,6 +84,8 @@ public slots:
void toggleAccountsConnected();
signals:
+ void ready();
+
void added( Tomahawk::Accounts::Account* );
void removed( Tomahawk::Accounts::Account* );
@@ -94,6 +96,7 @@ signals:
void stateChanged( Account* p, Accounts::Account::ConnectionState state );
private slots:
+ void init();
void onStateChanged( Tomahawk::Accounts::Account::ConnectionState state );
void onError( int code, const QString& msg );
diff --git a/src/libtomahawk/accounts/ResolverAccount.h b/src/libtomahawk/accounts/ResolverAccount.h
index b115d8fc4..4846d0e59 100644
--- a/src/libtomahawk/accounts/ResolverAccount.h
+++ b/src/libtomahawk/accounts/ResolverAccount.h
@@ -80,7 +80,7 @@ public:
// Not relevant
virtual QPixmap icon() const { return QPixmap(); }
virtual SipPlugin* sipPlugin() { return 0; }
- virtual Tomahawk::InfoSystem::InfoPlugin* infoPlugin() { return 0; }
+ virtual Tomahawk::InfoSystem::InfoPluginPtr infoPlugin() { return Tomahawk::InfoSystem::InfoPluginPtr(); }
virtual QWidget* aclWidget() { return 0; }
private slots:
diff --git a/src/libtomahawk/audio/audioengine.cpp b/src/libtomahawk/audio/audioengine.cpp
index 36681e8ab..cd2bc6041 100644
--- a/src/libtomahawk/audio/audioengine.cpp
+++ b/src/libtomahawk/audio/audioengine.cpp
@@ -327,8 +327,8 @@ AudioEngine::sendNowPlayingNotification( const Tomahawk::InfoSystem::InfoType ty
onNowPlayingInfoReady( type );
else
{
- _detail::Closure* closure = NewClosure( m_currentTrack->album().data(), SIGNAL( updated() ), const_cast< AudioEngine* >( this ), SLOT( onNowPlayingInfoReady( const Tomahawk::InfoSystem::InfoType ) ), type );
- m_currentTrack->album()->cover( QSize( 0, 0 ) );
+ NewClosure( m_currentTrack->album().data(), SIGNAL( updated() ), const_cast< AudioEngine* >( this ), SLOT( onNowPlayingInfoReady( const Tomahawk::InfoSystem::InfoType ) ), type );
+ m_currentTrack->album()->cover( QSize( 0, 0 ), true );
}
#endif
}
@@ -337,14 +337,11 @@ AudioEngine::sendNowPlayingNotification( const Tomahawk::InfoSystem::InfoType ty
void
AudioEngine::onNowPlayingInfoReady( const Tomahawk::InfoSystem::InfoType type )
{
- tDebug( LOGVERBOSE ) << Q_FUNC_INFO;
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO << type;
if ( m_currentTrack.isNull() ||
m_currentTrack->track().isNull() ||
m_currentTrack->artist().isNull() )
return;
-
- if ( !m_currentTrack->album().isNull() && sender() && m_currentTrack->album().data() != sender() )
- return;
QVariantMap playInfo;
@@ -353,26 +350,29 @@ AudioEngine::onNowPlayingInfoReady( const Tomahawk::InfoSystem::InfoType type )
#ifndef ENABLE_HEADLESS
QImage cover;
cover = m_currentTrack->album()->cover( QSize( 0, 0 ) ).toImage();
- playInfo["cover"] = cover;
-
- QTemporaryFile coverTempFile( QDir::toNativeSeparators( QDir::tempPath() + "/" + m_currentTrack->artist()->name() + "_" + m_currentTrack->album()->name() + "_tomahawk_cover.png" ) );
- if ( !coverTempFile.open() )
+ if ( !cover.isNull() )
{
- tDebug() << "WARNING: could not write temporary file for cover art!";
- }
+ playInfo["cover"] = cover;
- // Finally, save the image to the new temp file
- if ( cover.save( &coverTempFile, "PNG" ) )
- {
- tDebug( LOGVERBOSE ) << "Saving cover image to:" << QFileInfo( coverTempFile ).absoluteFilePath();
- coverTempFile.close();
- playInfo["coveruri"] = QFileInfo( coverTempFile ).absoluteFilePath();
+ QTemporaryFile* coverTempFile = new QTemporaryFile( QDir::toNativeSeparators( QDir::tempPath() + "/" + m_currentTrack->artist()->name() + "_" + m_currentTrack->album()->name() + "_tomahawk_cover.png" ) );
+ if ( !coverTempFile->open() )
+ tDebug() << Q_FUNC_INFO << "WARNING: could not write temporary file for cover art!";
+ else
+ {
+ // Finally, save the image to the new temp file
+ coverTempFile->setAutoRemove( false );
+ if ( cover.save( coverTempFile, "PNG" ) )
+ {
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Saving cover image to:" << QFileInfo( *coverTempFile ).absoluteFilePath();
+ playInfo["coveruri"] = QFileInfo( *coverTempFile ).absoluteFilePath();
+ }
+ else
+ tDebug() << Q_FUNC_INFO << "failed to save cover image!";
+ }
+ delete coverTempFile;
}
else
- {
- tDebug() << Q_FUNC_INFO << "failed to save cover image!";
- coverTempFile.close();
- }
+ tDebug() << Q_FUNC_INFO << "Cover from album is null!";
#endif
}
@@ -388,6 +388,7 @@ AudioEngine::onNowPlayingInfoReady( const Tomahawk::InfoSystem::InfoType type )
Tomahawk::InfoSystem::InfoPushData pushData ( s_aeInfoIdentifier, type, playInfo, Tomahawk::InfoSystem::PushShortUrlFlag );
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "pushing data with type " << type;
Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo( pushData );
}
diff --git a/src/libtomahawk/globalactionmanager.cpp b/src/libtomahawk/globalactionmanager.cpp
index 0c5ecc0f0..ffeb4dbc9 100644
--- a/src/libtomahawk/globalactionmanager.cpp
+++ b/src/libtomahawk/globalactionmanager.cpp
@@ -125,6 +125,7 @@ GlobalActionManager::openLink( const QString& title, const QString& artist, cons
void
GlobalActionManager::shortenLink( const QUrl& url, const QVariant& callbackObj )
{
+ tDebug() << Q_FUNC_INFO << "callbackObj is valid: " << ( callbackObj.isValid() ? "true" : "false" );
if ( QThread::currentThread() != thread() )
{
qDebug() << "Reinvoking in correct thread:" << Q_FUNC_INFO;
@@ -136,7 +137,7 @@ GlobalActionManager::shortenLink( const QUrl& url, const QVariant& callbackObj )
request.setUrl( url );
QNetworkReply *reply = TomahawkUtils::nam()->get( request );
- if ( !callbackObj.isValid() )
+ if ( callbackObj.isValid() )
reply->setProperty( "callbackobj", callbackObj );
connect( reply, SIGNAL( finished() ), SLOT( shortenLinkRequestFinished() ) );
connect( reply, SIGNAL( error( QNetworkReply::NetworkError ) ), SLOT( shortenLinkRequestError( QNetworkReply::NetworkError ) ) );
@@ -1013,7 +1014,7 @@ GlobalActionManager::shortenLinkRequestFinished()
}
QVariant callbackObj;
- if ( reply->property( "callbackobj" ).canConvert< QVariant >() && reply->property( "callbackobj" ).isValid() )
+ if ( reply->property( "callbackobj" ).isValid() )
callbackObj = reply->property( "callbackobj" );
// Check for the redirect attribute, as this should be the shortened link
diff --git a/src/libtomahawk/infosystem/infoplugins/generic/chartsplugin.cpp b/src/libtomahawk/infosystem/infoplugins/generic/chartsplugin.cpp
index cf330b695..56e005997 100644
--- a/src/libtomahawk/infosystem/infoplugins/generic/chartsplugin.cpp
+++ b/src/libtomahawk/infosystem/infoplugins/generic/chartsplugin.cpp
@@ -1,5 +1,6 @@
/* === This file is part of Tomahawk Player - ===
*
+ * Copyright 2012, Casey Link
* Copyright 2010-2011, Hugo Lindström
* Copyright 2011, Leo Franchi
* Copyright 2010-2011, Jeff Mitchell
@@ -32,6 +33,7 @@
#include "tomahawksettings.h"
#include "utils/tomahawkutils.h"
#include "utils/logger.h"
+#include "utils/tomahawkcache.h"
#define CHART_URL "http://charts.tomahawk-player.org/"
//#define CHART_URL "http://localhost:8080/"
@@ -45,10 +47,17 @@ ChartsPlugin::ChartsPlugin()
: InfoPlugin()
, m_chartsFetchJobs( 0 )
{
- /// Add resources here
- m_chartResources << "billboard" << "itunes" << "rdio" << "wearehunted" << "ex.fm" << "soundcloudwall";
/// If you add resource, update version aswell
- m_chartVersion = "2.1";
+ m_chartVersion = "2.3";
+ QVariantList source_qvarlist = TomahawkUtils::Cache::instance()->getData( "ChartsPlugin", "chart_sources" ).toList();
+ foreach( const QVariant & source, source_qvarlist ) {
+ m_chartResources.append( source.toString() );
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "fetched source from cache" << source.toString();
+
+ }
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "total sources" << m_chartResources.size() << source_qvarlist.size();
+ if( m_chartResources.size() == 0 )
+ fetchChartSourcesList( true );
m_supportedGetTypes << InfoChart << InfoChartCapabilities;
}
@@ -93,22 +102,24 @@ ChartsPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
{
if( resource == hash["chart_source"] )
{
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "get source" << resource;
foundSource = true;
}
}
if( !foundSource )
{
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "no such source" << hash["chart_source"] << "(" << m_chartResources.size() << " total sources)";
dataError( requestData );
break;
}
}
- fetchChart( requestData );
+ fetchChartFromCache( requestData );
break;
case InfoChartCapabilities:
- fetchChartCapabilities( requestData );
+ fetchChartCapabilitiesFromCache( requestData );
break;
default:
dataError( requestData );
@@ -117,11 +128,12 @@ ChartsPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
void
-ChartsPlugin::fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData )
+ChartsPlugin::fetchChartFromCache( Tomahawk::InfoSystem::InfoRequestData requestData )
{
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
{
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Could not convert requestData to InfoStringHash!";
dataError( requestData );
return;
}
@@ -140,12 +152,14 @@ ChartsPlugin::fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData )
/// Set the criterias for current chart
criteria["chart_id"] = hash["chart_id"];
criteria["chart_source"] = hash["chart_source"];
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Checking cache for " << hash["chart_id"] << " from " << hash["chart_source"];
+
emit getCachedInfo( criteria, 86400000, requestData );
}
void
-ChartsPlugin::fetchChartCapabilities( Tomahawk::InfoSystem::InfoRequestData requestData )
+ChartsPlugin::fetchChartCapabilitiesFromCache( Tomahawk::InfoSystem::InfoRequestData requestData )
{
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
{
@@ -157,6 +171,7 @@ ChartsPlugin::fetchChartCapabilities( Tomahawk::InfoSystem::InfoRequestData requ
Tomahawk::InfoSystem::InfoStringHash criteria;
criteria[ "InfoChartCapabilities" ] = "chartsplugin";
criteria[ "InfoChartVersion" ] = m_chartVersion;
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Checking cache for " << "InfoChartCapabilities" << m_chartVersion;
emit getCachedInfo( criteria, 864000000, requestData );
}
@@ -168,53 +183,17 @@ ChartsPlugin::notInCacheSlot( QHash criteria, Tomahawk::InfoSy
case InfoChart:
{
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "InfoChart not in cache! Fetching...";
-
- /// 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"] ) );
- tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Getting chart url" << url;
-
- QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
- reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
-
- connect( reply, SIGNAL( finished() ), SLOT( chartReturned() ) );
+ fetchChart( requestData, criteria["chart_source"], criteria["chart_id"] );
return;
}
case InfoChartCapabilities:
{
-
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "InfoChartCapabilities not in cache! Fetching...";
- // we never need to re-fetch
- //if ( !m_allChartsMap.isEmpty() )
- // return;
+ fetchChartSourcesList( false );
+ m_cachedRequests.append( requestData );
- /// 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 )
- {
- tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "InfoChartCapabilities still fetching!";
- m_cachedRequests.append( requestData );
- return;
- }
-
- emit info( requestData, m_allChartsMap );
return;
}
@@ -227,21 +206,94 @@ ChartsPlugin::notInCacheSlot( QHash criteria, Tomahawk::InfoSy
}
}
+void
+ChartsPlugin::fetchChartSourcesList( bool fetchOnlySourceList )
+{
+ QUrl url = QUrl( QString( CHART_URL "charts" ) );
+ QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
+ reply->setProperty( "only_source_list", fetchOnlySourceList );
+
+
+ tDebug() << "fetching:" << url;
+ connect( reply, SIGNAL( finished() ), SLOT( chartSourcesList() ) );
+
+}
void
-ChartsPlugin::chartTypes()
+ChartsPlugin::chartSourcesList()
{
- /// Get possible chart type for specificChartsPlugin: InfoChart types returned chart source
- tDebug( LOGVERBOSE ) << "Got chart type result";
+ tDebug( LOGVERBOSE ) << "Got chart sources list";
+ QNetworkReply* reply = qobject_cast( sender() );
+
+ if ( reply->error() == QNetworkReply::NoError )
+ {
+ QJson::Parser p;
+ bool ok;
+ const QVariantMap res = p.parse( reply, &ok ).toMap();
+ const QVariantList sources = res.value( "sources" ).toList();
+
+ if ( !ok )
+ {
+ tLog() << "Failed to parse sources" << p.errorString() << "On line" << p.errorLine();
+ return;
+ }
+
+ m_chartResources.clear();
+ foreach(const QVariant &source, sources) {
+ m_chartResources << source.toString();
+
+ }
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "storing sources in cache" << m_chartResources;
+ TomahawkUtils::Cache::instance()->putData( "ChartsPlugin", 172800000 /* 2 days */, "chart_sources", m_chartResources );
+ if( !reply->property("only_source_list" ).toBool() )
+ fetchAllChartSources();
+ }
+}
+
+void ChartsPlugin::fetchAllChartSources()
+{
+ if ( !m_chartResources.isEmpty() && m_allChartsMap.isEmpty() )
+ {
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "InfoChart fetching source data";
+ foreach ( QString source, m_chartResources )
+ {
+ QUrl url = QUrl( QString( CHART_URL "charts/%1" ).arg( source ) );
+ QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
+ reply->setProperty( "chart_source", source);
+
+ tDebug() << "fetching:" << url;
+ connect( reply, SIGNAL( finished() ), SLOT( chartsList() ) );
+
+ m_chartsFetchJobs++;
+ }
+ }
+}
+
+void ChartsPlugin::fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData, const QString& source, const QString& chart_id)
+{
+ /// Fetch the chart, we need source and id
+ QUrl url = QUrl( QString( CHART_URL "charts/%1/%2" ).arg( source ).arg( chart_id ) );
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "fetching: " << url;
+
+ QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
+ reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
+
+ connect( reply, SIGNAL( finished() ), SLOT( chartReturned() ) );
+}
+
+
+
+void
+ChartsPlugin::chartsList()
+{
+ tDebug( LOGVERBOSE ) << "Got chart list result";
QNetworkReply* reply = qobject_cast( sender() );
-
if ( reply->error() == QNetworkReply::NoError )
{
QJson::Parser p;
bool ok;
const QVariantMap res = p.parse( reply, &ok ).toMap();
- const QVariantMap chartObjs = res.value( "charts" ).toMap();
if ( !ok )
{
@@ -251,7 +303,7 @@ ChartsPlugin::chartTypes()
}
/// Got types, append!
- const QString source = res.value( "source" ).toString();
+ const QString source = reply->property("chart_source").toString();
// We'll populate charts with the data from the server
QVariantMap charts;
@@ -267,7 +319,7 @@ ChartsPlugin::chartTypes()
// WeAreHunted - Type - Artists - Chart Type
// - Tracks - Chart Type
QHash< QString, QVariantMap > extraType;
- foreach( const QVariant& chartObj, chartObjs.values() )
+ foreach( const QVariant& chartObj, res.values() )
{
if( !chartObj.toMap().isEmpty() )
{
@@ -352,7 +404,7 @@ ChartsPlugin::chartTypes()
QList< InfoStringHash > trackCharts;
QList< InfoStringHash > artistCharts;
- foreach( const QVariant& chartObj, chartObjs.values() )
+ foreach( const QVariant& chartObj, res.values() )
{
if( !chartObj.toMap().isEmpty() ){
const QVariantMap chart = chartObj.toMap();
@@ -407,7 +459,7 @@ ChartsPlugin::chartTypes()
}
/// Add the possible charts and its types to breadcrumb
-// tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "ADDING CHART TYPE TO CHARTS:" << chartName;
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "ADDING CHART TO CHARTS:" << chartName;
QVariantMap defaultMap = m_allChartsMap.value( "defaults" ).value< QVariantMap >();
defaultMap[ source ] = defaultChain;
m_allChartsMap[ "defaults" ] = defaultMap;
@@ -427,6 +479,7 @@ ChartsPlugin::chartTypes()
{
emit info( request, m_allChartsMap );
// update cache
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Updating cache with " << m_allChartsMap.size() << "charts";
Tomahawk::InfoSystem::InfoStringHash criteria;
criteria[ "InfoChartCapabilities" ] = "chartsplugin";
criteria[ "InfoChartVersion" ] = m_chartVersion;
diff --git a/src/libtomahawk/infosystem/infoplugins/generic/chartsplugin.h b/src/libtomahawk/infosystem/infoplugins/generic/chartsplugin.h
index 0bebb4629..352ac2a3a 100644
--- a/src/libtomahawk/infosystem/infoplugins/generic/chartsplugin.h
+++ b/src/libtomahawk/infosystem/infoplugins/generic/chartsplugin.h
@@ -52,10 +52,6 @@ public:
void setChartType( ChartType type ) { m_chartType = type; }
ChartType chartType() const { return m_chartType; }
-public slots:
- void chartReturned();
- void chartTypes();
-
protected slots:
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
@@ -65,9 +61,39 @@ protected slots:
Q_UNUSED( pushData );
}
+ /**
+ * Parses a QNetworkReply of a list of chart sources.
+ */
+ void chartSourcesList();
+
+ /**
+ * Parses a QNetworkReply of a list of charts for a particular source
+ */
+ void chartsList();
+
+ /**
+ * Parses a QNetworkReply for the chart data for a particular chart
+ */
+ void chartReturned();
+
private:
- void fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData );
- void fetchChartCapabilities( Tomahawk::InfoSystem::InfoRequestData requestData );
+ /**
+ * Fetch list of chart sources (e.g., itunes, billboard)
+ * Populates the m_chartResources member.
+ */
+ void fetchChartSourcesList( bool fetchOnlySourceList );
+ /**
+ * Requests charts list for each chart source in m_chartResources
+ */
+ void fetchAllChartSources();
+ /**
+ * Fetches a specific chart from a particular source.
+ * Updates the cache.
+ */
+ void fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData, const QString& source, const QString& chart_id );
+
+ void fetchChartFromCache( Tomahawk::InfoSystem::InfoRequestData requestData );
+ void fetchChartCapabilitiesFromCache( Tomahawk::InfoSystem::InfoRequestData requestData );
void dataError( Tomahawk::InfoSystem::InfoRequestData requestData );
QStringList m_chartResources;
diff --git a/src/libtomahawk/infosystem/infoplugins/generic/newreleasesplugin.cpp b/src/libtomahawk/infosystem/infoplugins/generic/newreleasesplugin.cpp
new file mode 100644
index 000000000..0a4cb9338
--- /dev/null
+++ b/src/libtomahawk/infosystem/infoplugins/generic/newreleasesplugin.cpp
@@ -0,0 +1,356 @@
+#include "newreleasesplugin.h"
+
+#include
+#include
+#include
+#include
+
+#include "album.h"
+#include "chartsplugin_data_p.h"
+#include "typedefs.h"
+#include "audio/audioengine.h"
+#include "tomahawksettings.h"
+#include "utils/tomahawkutils.h"
+#include "utils/logger.h"
+#include "utils/tomahawkcache.h"
+
+#include
+#include
+
+#define CHART_URL "http://charts.tomahawk-player.org/"
+//#define CHART_URL "http://localhost:8080/"
+
+using namespace Tomahawk::InfoSystem;
+
+NewReleasesPlugin::NewReleasesPlugin()
+ : InfoPlugin()
+ , m_nrFetchJobs ( 0 )
+{
+ m_nrVersion = "0";
+ m_supportedGetTypes << InfoNewReleaseCapabilities << InfoNewRelease;
+ QVariantList source_qvarlist = TomahawkUtils::Cache::instance()->getData( "NewReleasesPlugin", "nr_sources" ).toList();
+ foreach( const QVariant & source, source_qvarlist ) {
+ m_nrSources.append( source.toString() );
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "fetched source from cache" << source.toString();
+
+ }
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "total sources" << m_nrSources.size() << source_qvarlist.size();
+ if( m_nrSources.size() == 0 )
+ fetchNRSourcesList( true );
+}
+
+NewReleasesPlugin::~NewReleasesPlugin()
+{
+ tDebug ( LOGVERBOSE ) << Q_FUNC_INFO;
+}
+
+void NewReleasesPlugin::dataError ( InfoRequestData requestData )
+{
+ emit info ( requestData, QVariant() );
+ return;
+}
+
+void NewReleasesPlugin::getInfo ( InfoRequestData requestData )
+{
+//qDebug() << Q_FUNC_INFO << requestData.caller;
+ //qDebug() << Q_FUNC_INFO << requestData.customData;
+
+ InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
+ bool foundSource = false;
+
+ switch ( requestData.type ) {
+ case InfoNewRelease:
+ /// We need something to check if the request is actually ment to go to this plugin
+ if ( !hash.contains ( "nr_source" ) ) {
+ tDebug ( LOGVERBOSE ) << Q_FUNC_INFO << "Hash did not contain required param!";
+ dataError ( requestData );
+ break;
+ } else {
+ foreach ( QString resource, m_nrSources ) {
+ if ( resource == hash["nr_source"] ) {
+ foundSource = true;
+ }
+ }
+
+ if ( !foundSource ) {
+ dataError ( requestData );
+ break;
+ }
+
+ }
+ fetchNRFromCache ( requestData );
+ break;
+
+ case InfoNewReleaseCapabilities:
+ fetchNRCapabilitiesFromCache ( requestData );
+ break;
+ default:
+ dataError ( requestData );
+ }
+}
+
+void NewReleasesPlugin::fetchNRFromCache ( InfoRequestData requestData )
+{
+ if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() ) {
+ dataError ( requestData );
+ return;
+ }
+
+ InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
+ Tomahawk::InfoSystem::InfoStringHash criteria;
+
+ /// Each request needs to contain both a id and source
+ if ( !hash.contains ( "nr_id" ) && !hash.contains ( "nr_source" ) ) {
+ tDebug ( LOGVERBOSE ) << Q_FUNC_INFO << "Hash did not contain required params!";
+ dataError ( requestData );
+ return;
+
+ }
+ /// Set the criterias for current chart
+ criteria["nr_id"] = hash["nr_id"];
+ criteria["nr_source"] = hash["nr_source"];
+
+ emit getCachedInfo ( criteria, 86400000, requestData );
+}
+
+void NewReleasesPlugin::fetchNRCapabilitiesFromCache ( InfoRequestData requestData )
+{
+ if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() ) {
+ tDebug ( LOGVERBOSE ) << Q_FUNC_INFO << "Could not convert requestData to InfoStringHash!";
+ dataError ( requestData );
+ return;
+ }
+
+ Tomahawk::InfoSystem::InfoStringHash criteria;
+ criteria[ "InfoNewReleaseCapabilities" ] = "newreleasesplugin";
+ criteria[ "InfoNewReleaseVersion" ] = m_nrVersion;
+ emit getCachedInfo ( criteria, 864000000, requestData );
+}
+
+void NewReleasesPlugin::notInCacheSlot ( InfoStringHash criteria, InfoRequestData requestData )
+{
+ switch ( requestData.type ) {
+ case InfoNewRelease: {
+ tDebug ( LOGVERBOSE ) << Q_FUNC_INFO << "InfoNewRelease not in cache! Fetching...";
+ fetchNR ( requestData, criteria["nr_source"], criteria["nr_id"] );
+ return;
+
+ }
+
+ case InfoNewReleaseCapabilities: {
+ tDebug ( LOGVERBOSE ) << Q_FUNC_INFO << "InfoChartCapabilities not in cache! Fetching...";
+ fetchNRSourcesList( false );
+ m_cachedRequests.append ( requestData );
+
+ return;
+ }
+
+ default: {
+ tLog() << Q_FUNC_INFO << "Couldn't figure out what to do with this type of request after cache miss";
+ emit info ( requestData, QVariant() );
+ return;
+ }
+ }
+}
+
+void NewReleasesPlugin::fetchNRSourcesList( bool fetchOnlySourcesList )
+{
+ QUrl url = QUrl ( QString ( CHART_URL "newreleases" ) );
+ QNetworkReply* reply = TomahawkUtils::nam()->get ( QNetworkRequest ( url ) );
+ reply->setProperty( "only_source_list", fetchOnlySourcesList );
+
+
+ tDebug() << "fetching:" << url;
+ connect ( reply, SIGNAL ( finished() ), SLOT ( nrSourcesList() ) );
+
+}
+
+void NewReleasesPlugin::nrSourcesList()
+{
+ tDebug ( LOGVERBOSE ) << "Got newreleases sources list";
+ QNetworkReply* reply = qobject_cast ( sender() );
+
+ if ( reply->error() == QNetworkReply::NoError ) {
+ QJson::Parser p;
+ bool ok;
+ const QVariantMap res = p.parse ( reply, &ok ).toMap();
+ const QVariantList sources = res.value ( "sources" ).toList();
+
+ if ( !ok ) {
+ tLog() << "Failed to parse sources" << p.errorString() << "On line" << p.errorLine();
+ return;
+ }
+
+ m_nrSources.clear();
+ foreach ( const QVariant &source, sources ) {
+ m_nrSources << source.toString();
+ }
+ TomahawkUtils::Cache::instance()->putData( "NewReleasesPlugin", 172800000 /* 2 days */, "nr_sources", m_nrSources );
+ if( !reply->property( "only_source_list" ).toBool() )
+ fetchAllNRSources();
+ }
+}
+
+void NewReleasesPlugin::fetchAllNRSources()
+{
+ if ( !m_nrSources.isEmpty() && m_allNRsMap.isEmpty() ) {
+ tDebug ( LOGVERBOSE ) << Q_FUNC_INFO << "InfoNewRelease fetching source data";
+ foreach ( QString source, m_nrSources ) {
+ QUrl url = QUrl ( QString ( CHART_URL "newreleases/%1" ).arg ( source ) );
+ QNetworkReply* reply = TomahawkUtils::nam()->get ( QNetworkRequest ( url ) );
+ reply->setProperty ( "nr_source", source );
+
+ tDebug() << "fetching:" << url;
+ connect ( reply, SIGNAL ( finished() ), SLOT ( nrList() ) );
+
+ m_nrFetchJobs++;
+ }
+ }
+}
+
+void NewReleasesPlugin::fetchNR ( InfoRequestData requestData, const QString& source, const QString& nr_id )
+{
+ /// Fetch the chart, we need source and id
+ QUrl url = QUrl ( QString ( CHART_URL "newreleases/%1/%2" ).arg ( source ).arg ( nr_id ) );
+ tDebug ( LOGVERBOSE ) << Q_FUNC_INFO << "fetching: " << url;
+
+ QNetworkReply* reply = TomahawkUtils::nam()->get ( QNetworkRequest ( url ) );
+ reply->setProperty ( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData > ( requestData ) );
+
+ connect ( reply, SIGNAL ( finished() ), SLOT ( nrReturned() ) );
+}
+
+void NewReleasesPlugin::nrList()
+{
+ tDebug ( LOGVERBOSE ) << "Got newreleases list result";
+ QNetworkReply* reply = qobject_cast ( sender() );
+
+ if ( reply->error() == QNetworkReply::NoError ) {
+ QJson::Parser p;
+ bool ok;
+ const QVariantMap res = p.parse ( reply, &ok ).toMap();
+
+ if ( !ok ) {
+ tLog() << "Failed to parse resources" << p.errorString() << "On line" << p.errorLine();
+
+ return;
+ }
+
+ /// Got types, append!
+ const QString source = reply->property ( "nr_source" ).toString();
+
+ // We'll populate newreleases with the data from the server
+ QVariantMap newreleases;
+ QString nrName;
+
+ // Building:
+ // [Source] - New Release
+ QList< InfoStringHash > albumNRs;
+
+ foreach ( const QVariant &nrObj, res.values() ) {
+ if ( !nrObj.toMap().isEmpty() ) {
+ const QVariantMap nrMap = nrObj.toMap();
+ const QString type = nrMap.value ( "type" ).toString();
+
+ InfoStringHash nr;
+ nr["id"] = nrMap.value ( "id" ).toString();
+ nr["label"] = nrMap.value ( "name" ).toString();
+ nr["date"] = nrMap.value ( "date" ).toString();
+
+ if ( type == "Album" ) {
+ nr[ "type" ] = "album";
+ albumNRs.append ( nr );
+ } else {
+ tLog() << "Unknown newrelease type " << type;
+ continue;
+ }
+
+ }
+ }
+ if ( !albumNRs.isEmpty() )
+ newreleases.insert ( tr ( "Albums" ), QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > > ( albumNRs ) );
+
+ /// @note For displaying purposes, upper the first letter
+ /// @note Remeber to lower it when fetching this!
+ nrName = source;
+ nrName[0] = nrName[0].toUpper();
+
+ tDebug ( LOGVERBOSE ) << Q_FUNC_INFO << "ADDING newrelease TO NRS:" << nrName;
+ QVariantMap defaultMap = m_allNRsMap.value ( "defaults" ).value< QVariantMap >();
+ m_allNRsMap.insert ( nrName, QVariant::fromValue< QVariantMap > ( newreleases ) );
+
+ } else {
+ tLog() << "Error fetching charts:" << reply->errorString();
+ }
+
+ m_nrFetchJobs--;
+ if ( !m_cachedRequests.isEmpty() && m_nrFetchJobs == 0 ) {
+ foreach ( InfoRequestData request, m_cachedRequests ) {
+ emit info ( request, m_allNRsMap );
+ // update cache
+ Tomahawk::InfoSystem::InfoStringHash criteria;
+ criteria[ "InfoNewReleaseCapabilities" ] = "newreleasesplugin";
+ criteria[ "InfoNewReleaseVersion" ] = m_nrVersion;
+ emit updateCache ( criteria, 864000000, request.type, m_allNRsMap );
+ }
+ m_cachedRequests.clear();
+ }
+}
+
+void NewReleasesPlugin::nrReturned()
+{
+ /// Chart request returned something! Woho
+ QNetworkReply* reply = qobject_cast ( sender() );
+ QVariantMap returnedData;
+
+ if ( reply->error() == QNetworkReply::NoError ) {
+ QJson::Parser p;
+ bool ok;
+ QVariantMap res = p.parse ( reply, &ok ).toMap();
+
+ if ( !ok ) {
+ tLog() << "Failed to parse json from chart lookup:" << p.errorString() << "On line" << p.errorLine();
+ return;
+ }
+
+ /// SO we have a result, parse it!
+ QVariantList albumList = res.value ( "list" ).toList();
+ QList< Tomahawk::InfoSystem::InfoStringHash > newreleases;
+
+ foreach( const QVariant & albumObj, albumList ) {
+ QVariantMap albumMap = albumObj.toMap();
+ if(!albumMap.isEmpty()) {
+ const QString album = albumMap.value("album").toString();
+ const QString artist = albumMap.value("artist").toString();
+ const QString date = albumMap.value("date").toString();
+
+ Tomahawk::InfoSystem::InfoStringHash pair;
+ pair["artist"] = artist;
+ pair["album"] = album;
+ newreleases.append( pair );
+ }
+ }
+
+ tDebug() << "NewReleasesPlugin:" << "\tgot " << newreleases.size() << " albums";
+ returnedData[ "albums" ] = QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > >( newreleases );
+ returnedData[ "type" ] = "albums";
+ Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
+
+ emit info( requestData, returnedData );
+ // update cache
+ Tomahawk::InfoSystem::InfoStringHash criteria;
+ Tomahawk::InfoSystem::InfoStringHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
+ criteria[ "nr_id" ] = origData[ "nr_id" ];
+ criteria[ "nr_source" ] = origData[ "nr_source" ];
+ emit updateCache( criteria, 86400000, requestData.type, returnedData );
+ } else
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Network error in fetching newrelease:" << reply->url().toString();
+}
+
+
+
+
+
+
+
+
diff --git a/src/libtomahawk/infosystem/infoplugins/generic/newreleasesplugin.h b/src/libtomahawk/infosystem/infoplugins/generic/newreleasesplugin.h
new file mode 100644
index 000000000..7fcedbddc
--- /dev/null
+++ b/src/libtomahawk/infosystem/infoplugins/generic/newreleasesplugin.h
@@ -0,0 +1,100 @@
+/* === This file is part of Tomahawk Player - ===
+ *
+ * Copyright 2012, Casey Link
+ *
+ * Tomahawk is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tomahawk is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tomahawk. If not, see .
+ */
+
+#ifndef NEWRELEASESPLUGIN_H
+#define NEWRELEASESPLUGIN_H
+
+#include "infosystem/infosystem.h"
+#include "infosystem/infosystemworker.h"
+#include
+#include
+
+class QNetworkReply;
+
+namespace Tomahawk
+{
+
+namespace InfoSystem
+{
+
+class NewReleasesPlugin : public InfoPlugin
+{
+ Q_OBJECT
+
+public:
+ NewReleasesPlugin();
+ virtual ~NewReleasesPlugin();
+
+protected slots:
+ virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
+ virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
+
+ virtual void pushInfo( Tomahawk::InfoSystem::InfoPushData pushData )
+ {
+ Q_UNUSED( pushData );
+ }
+
+ /**
+ * Parses a QNetworkReply of a list of newreleases sources.
+ */
+ void nrSourcesList();
+
+ /**
+ * Parses a QNetworkReply of a list of newreleases from a particular source
+ */
+ void nrList();
+
+ /**
+ * Parses a QNetworkReply for the newreleases data for a particular newrelease
+ */
+ void nrReturned();
+
+private:
+ /**
+ * Fetch list of newlreeases sources (e.g., rovi)
+ * Populates the m_nrSources member.
+ */
+ void fetchNRSourcesList( bool fetchOnlySourcesList );
+ /**
+ * Requests newrelease list for each source in m_chartSources
+ */
+ void fetchAllNRSources();
+ /**
+ * Fetches a specific newrelease from a particular source.
+ * Updates the cache.
+ */
+ void fetchNR( Tomahawk::InfoSystem::InfoRequestData requestData, const QString& source, const QString& nr_id );
+ void fetchNRFromCache( Tomahawk::InfoSystem::InfoRequestData requestData );
+ void fetchNRCapabilitiesFromCache( Tomahawk::InfoSystem::InfoRequestData requestData );
+ void dataError( Tomahawk::InfoSystem::InfoRequestData requestData );
+
+ QStringList m_nrSources;
+ QString m_nrVersion;
+ QList< InfoStringHash > m_newreleases;
+ //ChartType m_chartType;
+ QVariantMap m_allNRsMap;
+ uint m_nrFetchJobs;
+ QList< InfoRequestData > m_cachedRequests;
+ QHash< QString, QString > m_cachedCountries;
+ QWeakPointer< QNetworkAccessManager > m_nam;
+};
+
+}
+}
+
+#endif // NEWRELEASESPLUGIN_H
diff --git a/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.cpp b/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.cpp
index 4cc973270..5c252f820 100644
--- a/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.cpp
+++ b/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.cpp
@@ -49,9 +49,9 @@
using namespace Tomahawk::InfoSystem;
-
FdoNotifyPlugin::FdoNotifyPlugin()
: InfoPlugin()
+ , m_nowPlayingId( 0 )
{
qDebug() << Q_FUNC_INFO;
m_supportedPushTypes << InfoNotifyUser << InfoNowPlaying << InfoTrackUnresolved << InfoNowStopped;
@@ -119,6 +119,7 @@ FdoNotifyPlugin::notifyUser( const QString &messageText )
void
FdoNotifyPlugin::nowPlaying( const QVariant &input )
{
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO;
if ( !input.canConvert< QVariantMap >() )
return;
@@ -135,23 +136,29 @@ FdoNotifyPlugin::nowPlaying( const QVariant &input )
.arg( hash[ "title" ] )
.arg( hash[ "artist" ] )
.arg( hash[ "album" ].isEmpty() ? QString() : QString( " %1" ).arg( tr( "on \"%1\"" ).arg( hash[ "album" ] ) ) );
-
+
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "sending message" << messageText;
+
QDBusMessage message = QDBusMessage::createMethodCall( "org.freedesktop.Notifications", "/org/freedesktop/Notifications", "org.freedesktop.Notifications", "Notify" );
QList arguments;
arguments << QString( "Tomahawk" ); //app_name
- arguments << quint32( 0 ); //notification_id
+ arguments << m_nowPlayingId; //notification_id
arguments << QString(); //app_icon
arguments << QString( "Tomahawk" ); //summary
arguments << messageText; //body
arguments << QStringList(); //actions
QVariantMap dict;
dict["desktop-entry"] = QString( "tomahawk" );
- if ( map.contains( "cover" ) && map[ "cover" ].canConvert< QImage >() )
- dict[ "image_data" ] = ImageConverter::variantForImage( map[ "cover" ].value< QImage >() );
+ if ( map.contains( "coveruri" ) && map[ "coveruri" ].canConvert< QString >() )
+ dict[ "image_data" ] = ImageConverter::variantForImage( QImage( map[ "coveruri" ].toString(), "PNG" ) );
else
dict[ "image_data" ] = ImageConverter::variantForImage( QImage( RESPATH "icons/tomahawk-icon-128x128.png" ) );
arguments << dict; //hints
arguments << qint32( -1 ); //expire_timeout
message.setArguments( arguments );
- QDBusConnection::sessionBus().send( message );
+
+ const QDBusMessage &reply = QDBusConnection::sessionBus().call( message );
+ const QVariantList &list = reply.arguments();
+ if ( list.count() > 0 )
+ m_nowPlayingId = list.at( 0 ).toInt();
}
diff --git a/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.h b/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.h
index c12621ff3..bba7bc304 100644
--- a/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.h
+++ b/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.h
@@ -54,6 +54,8 @@ private:
void notifyUser( const QString &messageText );
void nowPlaying( const QVariant &input );
+
+ quint32 m_nowPlayingId;
};
}
diff --git a/src/libtomahawk/infosystem/infosystem.cpp b/src/libtomahawk/infosystem/infosystem.cpp
index c1f6c020b..2dca67a95 100644
--- a/src/libtomahawk/infosystem/infosystem.cpp
+++ b/src/libtomahawk/infosystem/infosystem.cpp
@@ -137,7 +137,7 @@ InfoSystem::init()
bool
InfoSystem::getInfo( const InfoRequestData &requestData )
{
- qDebug() << Q_FUNC_INFO;
+ //qDebug() << Q_FUNC_INFO;
if ( !m_inited || !m_infoSystemWorkerThreadController->worker() )
{
init();
@@ -210,15 +210,67 @@ InfoSystem::pushInfo( const QString &caller, const InfoTypeMap &input, const Pus
void
-InfoSystem::addInfoPlugin( InfoPlugin* plugin )
+InfoSystem::addInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin )
+{
+ // Init is not complete (waiting for worker thread to start and create worker object) so keep trying till then
+ if ( !m_inited || !m_infoSystemWorkerThreadController->worker() )
+ {
+ QMetaObject::invokeMethod( this, "addInfoPlugin", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoPluginPtr, plugin ) );
+ return;
+ }
+
+ if ( plugin.isNull() )
+ {
+ tDebug() << Q_FUNC_INFO << "Given plugin is null!";
+ return;
+ }
+
+ if ( plugin.data()->thread() != m_infoSystemWorkerThreadController->worker()->thread() )
+ {
+ Q_ASSERT( false );
+ tDebug() << Q_FUNC_INFO << "The object must be moved to the worker thread first, see InfoSystem::workerThread()";
+ return;
+ }
+
+ tDebug() << Q_FUNC_INFO << plugin.data();
+ QMetaObject::invokeMethod( m_infoSystemWorkerThreadController->worker(), "addInfoPlugin", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoPluginPtr, plugin ) );
+}
+
+
+void
+InfoSystem::removeInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin )
{
// Init is not complete (waiting for worker th read to start and create worker object) so keep trying till then
if ( !m_inited || !m_infoSystemWorkerThreadController->worker() )
{
- QMetaObject::invokeMethod( this, "addInfoPlugin", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoPlugin*, plugin ) );
+ QMetaObject::invokeMethod( this, "removeInfoPlugin", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoPluginPtr, plugin ) );
return;
}
- QMetaObject::invokeMethod( m_infoSystemWorkerThreadController->worker(), "addInfoPlugin", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoPlugin*, plugin ) );
+
+ if ( plugin.isNull() )
+ {
+ tDebug() << Q_FUNC_INFO << "Given plugin is null!";
+ return;
+ }
+
+ if ( plugin.data()->thread() != m_infoSystemWorkerThreadController->worker()->thread() )
+ {
+ tDebug() << Q_FUNC_INFO << "The object must be moved to the worker thread first, see InfoSystem::workerThread()";
+ return;
+ }
+
+ tDebug() << Q_FUNC_INFO << plugin.data();
+ QMetaObject::invokeMethod( m_infoSystemWorkerThreadController->worker(), "removeInfoPlugin", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoPluginPtr, plugin ) );
+}
+
+
+QWeakPointer< QThread >
+InfoSystem::workerThread() const
+{
+ if ( m_infoSystemWorkerThreadController->isRunning() && m_infoSystemWorkerThreadController->worker() )
+ return QWeakPointer< QThread >( m_infoSystemWorkerThreadController->worker()->thread() );
+
+ return QWeakPointer< QThread >();
}
diff --git a/src/libtomahawk/infosystem/infosystem.h b/src/libtomahawk/infosystem/infosystem.h
index 9f0d8a811..bb0716525 100644
--- a/src/libtomahawk/infosystem/infosystem.h
+++ b/src/libtomahawk/infosystem/infosystem.h
@@ -112,6 +112,9 @@ enum InfoType { // as items are saved in cache, mark them here to not change the
*/
InfoChart = 51,
+ InfoNewReleaseCapabilities = 52,
+ InfoNewRelease = 53,
+
InfoMiscTopHotttness = 60,
InfoMiscTopTerms = 61,
@@ -195,7 +198,7 @@ struct InfoPushData {
, pushFlags( pflags )
, infoPair( Tomahawk::InfoSystem::PushInfoPair( QVariantMap(), QVariant() ) )
{}
-
+
};
@@ -282,9 +285,12 @@ public:
bool pushInfo( InfoPushData pushData );
bool pushInfo( const QString &caller, const InfoTypeMap &input, const PushInfoFlags pushFlags );
+ QWeakPointer< QThread > workerThread() const;
+
public slots:
// InfoSystem takes ownership of InfoPlugins
- void addInfoPlugin( Tomahawk::InfoSystem::InfoPlugin* plugin );
+ void addInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin );
+ void removeInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin );
signals:
void info( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
@@ -307,7 +313,6 @@ private:
}
-
inline uint qHash( Tomahawk::InfoSystem::InfoStringHash hash )
{
QCryptographicHash md5( QCryptographicHash::Md5 );
@@ -329,6 +334,7 @@ inline uint qHash( Tomahawk::InfoSystem::InfoStringHash hash )
return returnval;
}
+
Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoRequestData );
Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoPushData );
Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoStringHash );
@@ -337,6 +343,7 @@ Q_DECLARE_METATYPE( Tomahawk::InfoSystem::PushInfoFlags );
Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoType );
Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoSystemCache* );
Q_DECLARE_METATYPE( QList< Tomahawk::InfoSystem::InfoStringHash > );
+Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoPluginPtr );
Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoPlugin* );
#endif // TOMAHAWK_INFOSYSTEM_H
diff --git a/src/libtomahawk/infosystem/infosystemcache.cpp b/src/libtomahawk/infosystem/infosystemcache.cpp
index ac626ecd0..5a2503046 100644
--- a/src/libtomahawk/infosystem/infosystemcache.cpp
+++ b/src/libtomahawk/infosystem/infosystemcache.cpp
@@ -159,7 +159,7 @@ InfoSystemCache::getCachedInfoSlot( Tomahawk::InfoSystem::InfoStringHash criteri
if ( !fileLocationHash.isEmpty() )
{
//We already know of some values, so no need to re-read the directory again as it's already happened
- qDebug() << Q_FUNC_INFO << "notInCache -- filelocationhash empty";
+ //qDebug() << Q_FUNC_INFO << "notInCache -- filelocationhash empty";
notInCache( sendingObj, criteria, requestData );
return;
}
@@ -169,7 +169,7 @@ InfoSystemCache::getCachedInfoSlot( Tomahawk::InfoSystem::InfoStringHash criteri
if ( !dir.exists() )
{
//Dir doesn't exist so clearly not in cache
- qDebug() << Q_FUNC_INFO << "notInCache -- dir doesn't exist";
+ //qDebug() << Q_FUNC_INFO << "notInCache -- dir doesn't exist";
notInCache( sendingObj, criteria, requestData );
return;
}
@@ -186,7 +186,7 @@ InfoSystemCache::getCachedInfoSlot( Tomahawk::InfoSystem::InfoStringHash criteri
if ( !fileLocationHash.contains( criteriaHashVal ) )
{
//Still didn't find it? It's really not in the cache then
- qDebug() << Q_FUNC_INFO << "notInCache -- filelocationhash doesn't contain criteria val";
+ //qDebug() << Q_FUNC_INFO << "notInCache -- filelocationhash doesn't contain criteria val";
notInCache( sendingObj, criteria, requestData );
return;
}
@@ -250,7 +250,7 @@ InfoSystemCache::notInCache( QObject *receiver, Tomahawk::InfoSystem::InfoString
void
InfoSystemCache::updateCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, qint64 maxAge, Tomahawk::InfoSystem::InfoType type, QVariant output )
{
- qDebug() << Q_FUNC_INFO;
+ //qDebug() << Q_FUNC_INFO;
const QString criteriaHashVal = criteriaMd5( criteria );
const QString criteriaHashValWithType = criteriaMd5( criteria, type );
const QString cacheDir = m_cacheBaseDir + QString::number( (int)type );
diff --git a/src/libtomahawk/infosystem/infosystemcache.h b/src/libtomahawk/infosystem/infosystemcache.h
index aa2544816..591f21efb 100644
--- a/src/libtomahawk/infosystem/infosystemcache.h
+++ b/src/libtomahawk/infosystem/infosystemcache.h
@@ -58,7 +58,7 @@ private:
void doUpgrade( uint oldVersion, uint newVersion );
void performWipe( QString directory );
const QString criteriaMd5( const Tomahawk::InfoSystem::InfoStringHash &criteria, Tomahawk::InfoSystem::InfoType type = Tomahawk::InfoSystem::InfoNoInfo ) const;
-
+
QString m_cacheBaseDir;
QHash< InfoType, QHash< QString, QString > > m_fileLocationCache;
QTimer m_pruneTimer;
diff --git a/src/libtomahawk/infosystem/infosystemworker.cpp b/src/libtomahawk/infosystem/infosystemworker.cpp
index be7fb4f2b..cdefc1095 100644
--- a/src/libtomahawk/infosystem/infosystemworker.cpp
+++ b/src/libtomahawk/infosystem/infosystemworker.cpp
@@ -28,6 +28,7 @@
#include "infoplugins/generic/echonestplugin.h"
#include "infoplugins/generic/musixmatchplugin.h"
#include "infoplugins/generic/chartsplugin.h"
+#include "infoplugins/generic/newreleasesplugin.h"
#include "infoplugins/generic/spotifyPlugin.h"
#include "infoplugins/generic/musicbrainzPlugin.h"
#include "infoplugins/generic/hypemPlugin.h"
@@ -82,36 +83,52 @@ InfoSystemWorker::init( Tomahawk::InfoSystem::InfoSystemCache* cache )
m_shortLinksWaiting = 0;
m_cache = cache;
#ifndef ENABLE_HEADLESS
- addInfoPlugin( new EchoNestPlugin() );
- addInfoPlugin( new MusixMatchPlugin() );
- addInfoPlugin( new MusicBrainzPlugin() );
- addInfoPlugin( new ChartsPlugin() );
- addInfoPlugin( new RoviPlugin() );
- addInfoPlugin( new SpotifyPlugin() );
- addInfoPlugin( new hypemPlugin() );
+ addInfoPlugin( InfoPluginPtr( new EchoNestPlugin() ) );
+ addInfoPlugin( InfoPluginPtr( new MusixMatchPlugin() ) );
+ addInfoPlugin( InfoPluginPtr( new MusicBrainzPlugin() ) );
+ addInfoPlugin( InfoPluginPtr( new ChartsPlugin() ) );
+ addInfoPlugin( InfoPluginPtr( new NewReleasesPlugin() ) );
+ addInfoPlugin( InfoPluginPtr( new RoviPlugin() ) );
+ addInfoPlugin( InfoPluginPtr( new SpotifyPlugin() ) );
+ addInfoPlugin( InfoPluginPtr( new hypemPlugin() ) );
#endif
#ifdef Q_WS_MAC
- addInfoPlugin( new AdiumPlugin() );
+ addInfoPlugin( InfoPluginPtr( new AdiumPlugin() ) );
#endif
#ifndef ENABLE_HEADLESS
#ifdef Q_WS_X11
- addInfoPlugin( new FdoNotifyPlugin() );
- addInfoPlugin( new MprisPlugin() );
+ addInfoPlugin( InfoPluginPtr( new FdoNotifyPlugin() ) );
+ addInfoPlugin( InfoPluginPtr( new MprisPlugin() ) );
#endif
#endif
}
void
-InfoSystemWorker::addInfoPlugin( InfoPlugin* plugin )
+InfoSystemWorker::addInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin )
{
- InfoPluginPtr weakptr( plugin );
- m_plugins.append( weakptr );
- registerInfoTypes( weakptr, weakptr.data()->supportedGetTypes(), weakptr.data()->supportedPushTypes() );
+ tDebug() << Q_FUNC_INFO << plugin;
+ foreach ( InfoPluginPtr ptr, m_plugins )
+ {
+ if ( ptr == plugin )
+ {
+ tDebug() << Q_FUNC_INFO << "This plugin is already added to the infosystem.";
+ return;
+ }
+ }
+
+ if ( plugin.isNull() )
+ {
+ tDebug() << Q_FUNC_INFO << "passed-in plugin is null";
+ return;
+ }
+
+ m_plugins.append( plugin );
+ registerInfoTypes( plugin, plugin.data()->supportedGetTypes(), plugin.data()->supportedPushTypes() );
connect(
- plugin,
+ plugin.data(),
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
this,
SLOT( infoSlot( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
@@ -119,14 +136,14 @@ InfoSystemWorker::addInfoPlugin( InfoPlugin* plugin )
);
connect(
- plugin,
+ plugin.data(),
SIGNAL( getCachedInfo( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoRequestData ) ),
m_cache,
SLOT( getCachedInfoSlot( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoRequestData ) ),
Qt::QueuedConnection
);
connect(
- plugin,
+ plugin.data(),
SIGNAL( updateCache( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoType, QVariant ) ),
m_cache,
SLOT( updateCacheSlot( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoType, QVariant ) ),
@@ -135,6 +152,32 @@ InfoSystemWorker::addInfoPlugin( InfoPlugin* plugin )
}
+void
+InfoSystemWorker::removeInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin )
+{
+ tDebug() << Q_FUNC_INFO << plugin;
+
+ if ( plugin.isNull() )
+ {
+ tDebug() << Q_FUNC_INFO << "passed-in plugin is null";
+ return;
+ }
+
+ foreach ( InfoPluginPtr ptr, m_plugins )
+ {
+ if ( ptr == plugin )
+ break;
+
+ tDebug() << Q_FUNC_INFO << "This plugin does not exist in the infosystem.";
+ return;
+ }
+
+ m_plugins.removeOne( plugin );
+ deregisterInfoTypes( plugin, plugin.data()->supportedGetTypes(), plugin.data()->supportedPushTypes() );
+ delete plugin.data();
+}
+
+
void
InfoSystemWorker::registerInfoTypes( const InfoPluginPtr &plugin, const QSet< InfoType >& getTypes, const QSet< InfoType >& pushTypes )
{
@@ -145,6 +188,16 @@ InfoSystemWorker::registerInfoTypes( const InfoPluginPtr &plugin, const QSet< In
}
+void
+InfoSystemWorker::deregisterInfoTypes( const InfoPluginPtr &plugin, const QSet< InfoType >& getTypes, const QSet< InfoType >& pushTypes )
+{
+ Q_FOREACH( InfoType type, getTypes )
+ m_infoGetMap[type].removeOne( plugin );
+ Q_FOREACH( InfoType type, pushTypes )
+ m_infoPushMap[type].removeOne( plugin );
+}
+
+
QList< InfoPluginPtr >
InfoSystemWorker::determineOrderedMatches( const InfoType type ) const
{
@@ -223,7 +276,7 @@ void
InfoSystemWorker::pushInfo( Tomahawk::InfoSystem::InfoPushData pushData )
{
tDebug() << Q_FUNC_INFO << "type is " << pushData.type;
-
+
if ( pushData.pushFlags != PushNoFlag )
{
if ( pushData.pushFlags & PushShortUrlFlag )
@@ -234,6 +287,8 @@ InfoSystemWorker::pushInfo( Tomahawk::InfoSystem::InfoPushData pushData )
}
}
+ tDebug() << Q_FUNC_INFO << "number of matching plugins: " << m_infoPushMap[ pushData.type ].size();
+
Q_FOREACH( InfoPluginPtr ptr, m_infoPushMap[ pushData.type ] )
{
if( ptr )
@@ -281,7 +336,7 @@ InfoSystemWorker::shortLinkReady( QUrl longUrl, QUrl shortUrl, QVariant callback
m_shortLinksWaiting--;
if ( !m_shortLinksWaiting )
disconnect( GlobalActionManager::instance(), SIGNAL( shortLinkReady( QUrl, QUrl, QVariant ) ) );
-
+
if ( !callbackObj.isValid() )
{
tDebug() << Q_FUNC_INFO << "callback object was not valid, cannot continue";
diff --git a/src/libtomahawk/infosystem/infosystemworker.h b/src/libtomahawk/infosystem/infosystemworker.h
index 6a51299b5..e949329ec 100644
--- a/src/libtomahawk/infosystem/infosystemworker.h
+++ b/src/libtomahawk/infosystem/infosystemworker.h
@@ -49,8 +49,6 @@ public:
InfoSystemWorker();
~InfoSystemWorker();
- void registerInfoTypes( const InfoPluginPtr &plugin, const QSet< InfoType > &getTypes, const QSet< InfoType > &pushTypes );
-
signals:
void info( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
void finished( QString target );
@@ -64,7 +62,8 @@ public slots:
void infoSlot( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
- void addInfoPlugin( Tomahawk::InfoSystem::InfoPlugin* plugin );
+ void addInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin );
+ void removeInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin );
void getShortUrl( Tomahawk::InfoSystem::InfoPushData data );
void shortLinkReady( QUrl longUrl, QUrl shortUrl, QVariant callbackObj );
@@ -73,6 +72,8 @@ private slots:
void checkTimeoutsTimerFired();
private:
+ void registerInfoTypes( const InfoPluginPtr &plugin, const QSet< InfoType > &getTypes, const QSet< InfoType > &pushTypes );
+ void deregisterInfoTypes( const InfoPluginPtr &plugin, const QSet< InfoType > &getTypes, const QSet< InfoType > &pushTypes );
void checkFinished( const Tomahawk::InfoSystem::InfoRequestData &target );
QList< InfoPluginPtr > determineOrderedMatches( const InfoType type ) const;
diff --git a/src/libtomahawk/playlist/artistview.cpp b/src/libtomahawk/playlist/artistview.cpp
index 351c76d48..45f55ca19 100644
--- a/src/libtomahawk/playlist/artistview.cpp
+++ b/src/libtomahawk/playlist/artistview.cpp
@@ -384,7 +384,7 @@ ArtistView::onCustomContextMenu( const QPoint& pos )
m_contextMenu->setArtists( artists );
m_contextMenu->setAlbums( albums );
- m_contextMenu->exec( mapToGlobal( pos ) );
+ m_contextMenu->exec( viewport()->mapToGlobal( pos ) );
}
diff --git a/src/libtomahawk/playlist/trackview.cpp b/src/libtomahawk/playlist/trackview.cpp
index 35ed48376..7939596b1 100644
--- a/src/libtomahawk/playlist/trackview.cpp
+++ b/src/libtomahawk/playlist/trackview.cpp
@@ -567,7 +567,7 @@ TrackView::onCustomContextMenu( const QPoint& pos )
}
m_contextMenu->setQueries( queries );
- m_contextMenu->exec( mapToGlobal( pos ) );
+ m_contextMenu->exec( viewport()->mapToGlobal( pos ) );
}
diff --git a/src/libtomahawk/query.cpp b/src/libtomahawk/query.cpp
index 0702cad40..2b9cabc86 100644
--- a/src/libtomahawk/query.cpp
+++ b/src/libtomahawk/query.cpp
@@ -588,9 +588,9 @@ Query::setLoved( bool loved )
trackInfo["album"] = album();
Tomahawk::InfoSystem::InfoPushData pushData ( id(),
- Tomahawk::InfoSystem::InfoLove,
+ ( loved ? Tomahawk::InfoSystem::InfoLove : Tomahawk::InfoSystem::InfoUnLove ),
QVariant::fromValue< Tomahawk::InfoSystem::InfoStringHash >( trackInfo ),
- Tomahawk::InfoSystem::PushNoFlag );
+ Tomahawk::InfoSystem::PushShortUrlFlag );
Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo( pushData );
diff --git a/src/libtomahawk/utils/tomahawkcache.cpp b/src/libtomahawk/utils/tomahawkcache.cpp
new file mode 100644
index 000000000..ac509a194
--- /dev/null
+++ b/src/libtomahawk/utils/tomahawkcache.cpp
@@ -0,0 +1,152 @@
+/* === This file is part of Tomahawk Player - ===
+ *
+ * Copyright 2012, Casey Link
+ *
+ * Tomahawk is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tomahawk is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tomahawk. If not, see .
+ */
+
+#include "tomahawkcache.h"
+
+#include "tomahawksettings.h"
+#include "utils/logger.h"
+
+#include
+#include
+#include
+
+using namespace TomahawkUtils;
+
+Cache*Cache::s_instance = 0;
+
+Cache* Cache::instance()
+{
+ if ( !s_instance )
+ s_instance = new Cache();
+
+ return s_instance;
+}
+
+Cache::Cache()
+ : QObject ( 0 )
+ , m_cacheBaseDir ( TomahawkSettings::instance()->storageCacheLocation() + "/GenericCache/" )
+ , m_cacheManifest ( m_cacheBaseDir + "cachemanifest.ini", QSettings::IniFormat )
+{
+ m_pruneTimer.setInterval ( 300000 );
+ m_pruneTimer.setSingleShot ( false );
+ connect ( &m_pruneTimer, SIGNAL ( timeout() ), SLOT ( pruneTimerFired() ) );
+ m_pruneTimer.start();
+}
+
+Cache::~Cache()
+{
+
+}
+
+void Cache::pruneTimerFired()
+{
+ QMutexLocker mutex_locker( &m_mutex );
+
+ qDebug() << Q_FUNC_INFO << "Pruning tomahawkcache";
+ qlonglong currentMSecsSinceEpoch = QDateTime::currentMSecsSinceEpoch();
+
+ QVariantList clients = m_cacheManifest.value ( "clients" ).toList();
+ foreach ( const QVariant &client, clients ) {
+ const QString client_identifier = client.toString();
+ const QString cache_dir = m_cacheBaseDir + client_identifier;
+
+ QSettings cached_settings ( cache_dir, QSettings::IniFormat );
+ const QStringList keys = cached_settings.allKeys();
+ foreach ( const QString &key, keys ) {
+ CacheData data = cached_settings.value ( key ).value();
+ if ( data.maxAge < currentMSecsSinceEpoch ) {
+ cached_settings.remove ( key );
+ tLog() << Q_FUNC_INFO << "Removed stale entry: " << client_identifier << key;
+ }
+ }
+ cached_settings.sync();
+ if ( cached_settings.allKeys().size() == 0 )
+ removeClient ( client_identifier );
+ }
+}
+
+
+QVariant Cache::getData ( const QString& identifier, const QString& key )
+{
+ QMutexLocker mutex_locker( &m_mutex );
+
+ const QString cacheDir = m_cacheBaseDir + identifier;
+ QSettings cached_settings ( cacheDir, QSettings::IniFormat );
+
+ if ( cached_settings.contains ( key ) ) {
+ CacheData data = cached_settings.value ( key ).value();
+
+ if ( data.maxAge < QDateTime::currentMSecsSinceEpoch() ) {
+ cached_settings.remove ( key );
+ tLog() << Q_FUNC_INFO << "Removed stale entry: " << identifier << key;
+ return QVariant();
+ }
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Fetched data for" << identifier << key;
+ return data.data;
+
+ }
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "No such client" << identifier;
+ return QVariant();
+}
+
+void Cache::putData ( const QString& identifier, qint64 maxAge, const QString& key, const QVariant& value )
+{
+ QMutexLocker mutex_locker( &m_mutex );
+
+ const QString cacheDir = m_cacheBaseDir + identifier;
+ addClient ( identifier );
+ QSettings cached_settings ( cacheDir, QSettings::IniFormat );
+ cached_settings.setValue ( key, QVariant::fromValue ( CacheData ( QDateTime::currentMSecsSinceEpoch() + maxAge, value ) ) );
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Storing from client " << identifier << maxAge << key << value;
+}
+
+void Cache::addClient ( const QString& identifier )
+{
+ QVariantList clients = m_cacheManifest.value ( "clients" ).toList();
+ foreach ( const QVariant &client, clients ) {
+ const QString client_identifier = client.toString();
+ if ( identifier == client_identifier ) return;
+ }
+
+ tLog() << Q_FUNC_INFO << "adding client" << identifier;
+ clients.append ( identifier );
+ m_cacheManifest.setValue ( "clients", clients );
+ m_cacheManifest.sync();
+}
+
+void Cache::removeClient ( const QString& identifier )
+{
+ QVariantList clients = m_cacheManifest.value ( "clients" ).toList();
+ QVariantList::iterator it = clients.begin();
+ while ( it != clients.end() ) {
+ const QString client_identifier = it->toString();
+ if ( identifier == client_identifier ) {
+ tLog() << Q_FUNC_INFO << "removing client" << identifier;
+ clients.erase ( it );
+ break;
+ }
+ ++it;
+ }
+ m_cacheManifest.setValue ( "clients", clients );
+ m_cacheManifest.sync();
+}
+
+
+
+
+
diff --git a/src/libtomahawk/utils/tomahawkcache.h b/src/libtomahawk/utils/tomahawkcache.h
new file mode 100644
index 000000000..3bd17885f
--- /dev/null
+++ b/src/libtomahawk/utils/tomahawkcache.h
@@ -0,0 +1,122 @@
+/* === This file is part of Tomahawk Player - ===
+ *
+ * Copyright 2012, Casey Link
+ *
+ * Tomahawk is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tomahawk is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tomahawk. If not, see .
+ */
+
+#ifndef TOMAHAWKCACHE_H
+#define TOMAHAWKCACHE_H
+
+#include "dllmacro.h"
+#include "utils/tomahawkutils.h"
+
+#include
+#include
+#include
+#include
+
+namespace TomahawkUtils {
+
+/**
+ * Internal data structure. Don't use.
+ */
+struct CacheData {
+ CacheData(){}
+ CacheData( qint64 maxAg, QVariant dat )
+ : maxAge( maxAg )
+ , data( dat )
+ {}
+
+ qint64 maxAge; //!< milliseconds
+ QVariant data;
+};
+
+/**
+ * A simple generic cache for anyone to use.
+ *
+ * Data is segmented according to clients, which specify
+ * a client identifier.
+ *
+ * Structure is a basic key-value store with associated max lifetime in
+ * milliseconds.
+ */
+class DLLEXPORT Cache : public QObject
+{
+Q_OBJECT
+
+public:
+ static Cache* instance();
+ virtual ~Cache();
+
+ /**
+ * Store data in the cache.
+ * @param identifier your unique identifier, used to segment your data.
+ * @param maxAge lifetime of data in milliseconds (e.g, 3600000 = 1 hour)
+ * @param key the key to store the data
+ * @param value the data to store
+ */
+ void putData( const QString &identifier, qint64 maxAge, const QString &key, const QVariant& value );
+
+ /**
+ * Retrieve data from the cache.
+ * @param identifier your unique identifier, used to segment your data.
+ * @param key the key to store the data
+ * @return the data, if found, if not found an invalid QVariant is returned.
+ */
+ QVariant getData( const QString &identifier, const QString &key );
+
+private slots:
+ void pruneTimerFired();
+
+private:
+ Cache();
+ static Cache* s_instance;
+
+ /**
+ * Adds a client to the manifest.
+ * Does not lock the mutex.
+ */
+ void addClient( const QString &identifier );
+
+ /**
+ * Removes a client to the manifest.
+ * Does not lock the mutex.
+ */
+ void removeClient( const QString &identifier );
+
+ QString m_cacheBaseDir;
+ QSettings m_cacheManifest;
+ QTimer m_pruneTimer;
+ QMutex m_mutex;
+};
+
+}
+
+inline QDataStream& operator<< ( QDataStream& in, const TomahawkUtils::CacheData& data )
+{
+ in << data.data << data.maxAge;
+ return in;
+}
+
+inline QDataStream& operator>> ( QDataStream& out, TomahawkUtils::CacheData& data )
+{
+ out >> data.data;
+ out >> data.maxAge;
+ return out;
+}
+
+Q_DECLARE_METATYPE( TomahawkUtils::CacheData );
+
+#endif // TOMAHAWKCACHE_H
diff --git a/src/libtomahawk/viewmanager.cpp b/src/libtomahawk/viewmanager.cpp
index f9c939e45..3835cbed6 100644
--- a/src/libtomahawk/viewmanager.cpp
+++ b/src/libtomahawk/viewmanager.cpp
@@ -75,6 +75,7 @@ ViewManager::ViewManager( QObject* parent )
, m_widget( new QWidget() )
, m_welcomeWidget( new WelcomeWidget() )
, m_whatsHotWidget( new WhatsHotWidget() )
+ , m_newReleasesWidget( new NewReleasesWidget() )
, m_topLovedWidget( 0 )
, m_recentPlaysWidget( 0 )
, m_currentMode( PlaylistInterface::Tree )
@@ -118,6 +119,7 @@ ViewManager::ViewManager( QObject* parent )
connect( m_infobar, SIGNAL( filterTextChanged( QString ) ), SLOT( setFilter( QString ) ) );
connect( this, SIGNAL( tomahawkLoaded() ), m_whatsHotWidget, SLOT( fetchData() ) );
+ connect( this, SIGNAL( tomahawkLoaded() ), m_newReleasesWidget, SLOT( fetchData() ) );
connect( this, SIGNAL( tomahawkLoaded() ), m_welcomeWidget, SLOT( loadData() ) );
/* connect( m_infobar, SIGNAL( flatMode() ), SLOT( setTableMode() ) );
@@ -130,6 +132,7 @@ ViewManager::~ViewManager()
{
saveCurrentPlaylistSettings();
delete m_whatsHotWidget;
+ delete m_newReleasesWidget;
delete m_welcomeWidget;
delete m_topLovedWidget;
delete m_recentPlaysWidget;
@@ -437,6 +440,13 @@ ViewManager::showWhatsHotPage()
}
+Tomahawk::ViewPage*
+ViewManager::showNewReleasesPage()
+{
+ return show( m_newReleasesWidget );
+}
+
+
Tomahawk::ViewPage*
ViewManager::showTopLovedPage()
{
diff --git a/src/libtomahawk/viewmanager.h b/src/libtomahawk/viewmanager.h
index a62f18f74..fc37724cd 100644
--- a/src/libtomahawk/viewmanager.h
+++ b/src/libtomahawk/viewmanager.h
@@ -31,6 +31,7 @@
#include "viewpage.h"
#include "widgets/welcomewidget.h"
#include "widgets/whatshotwidget.h"
+#include "widgets/newreleaseswidget.h"
#include "dllmacro.h"
@@ -91,6 +92,7 @@ public:
Tomahawk::ViewPage* welcomeWidget() const { return m_welcomeWidget; }
Tomahawk::ViewPage* whatsHotWidget() const { return m_whatsHotWidget; }
+ Tomahawk::ViewPage* newReleasesWidget() const { return m_newReleasesWidget; }
Tomahawk::ViewPage* topLovedWidget() const { return m_topLovedWidget; }
Tomahawk::ViewPage* recentPlaysWidget() const { return m_recentPlaysWidget; }
ArtistView* superCollectionView() const { return m_superCollectionView; }
@@ -139,6 +141,7 @@ public slots:
Tomahawk::ViewPage* showSuperCollection();
Tomahawk::ViewPage* showWelcomePage();
Tomahawk::ViewPage* showWhatsHotPage();
+ Tomahawk::ViewPage* showNewReleasesPage();
Tomahawk::ViewPage* showTopLovedPage();
Tomahawk::ViewPage* showRecentPlaysPage();
void showCurrentTrack();
@@ -202,6 +205,7 @@ private:
QueueView* m_queue;
WelcomeWidget* m_welcomeWidget;
WhatsHotWidget* m_whatsHotWidget;
+ NewReleasesWidget* m_newReleasesWidget;
Tomahawk::ViewPage* m_topLovedWidget;
Tomahawk::ViewPage* m_recentPlaysWidget;
diff --git a/src/libtomahawk/widgets/Breadcrumb.cpp b/src/libtomahawk/widgets/Breadcrumb.cpp
index 975a5c2b0..fdccebd46 100644
--- a/src/libtomahawk/widgets/Breadcrumb.cpp
+++ b/src/libtomahawk/widgets/Breadcrumb.cpp
@@ -21,6 +21,7 @@
#include "BreadcrumbButton.h"
#include "utils/stylehelper.h"
#include "utils/logger.h"
+#include "utils/tomahawkutilsgui.h"
#include
#include
@@ -35,8 +36,7 @@ Breadcrumb::Breadcrumb( QWidget* parent, Qt::WindowFlags f )
, m_model( 0 )
, m_buttonlayout( new QHBoxLayout( this ) )
{
- m_buttonlayout->setSpacing( 0 );
- m_buttonlayout->setMargin( 0 );
+ TomahawkUtils::unmarginLayout( m_buttonlayout );
m_buttonlayout->setAlignment( Qt::AlignLeft );
setAutoFillBackground( true );
diff --git a/src/libtomahawk/widgets/BreadcrumbButton.cpp b/src/libtomahawk/widgets/BreadcrumbButton.cpp
index 4b479c21e..12127538b 100644
--- a/src/libtomahawk/widgets/BreadcrumbButton.cpp
+++ b/src/libtomahawk/widgets/BreadcrumbButton.cpp
@@ -31,21 +31,67 @@
using namespace Tomahawk;
+class BreadcrumbArrow : public QWidget
+{
+public:
+ BreadcrumbArrow(QWidget* parent) : QWidget(parent) {}
+
+protected:
+ virtual void paintEvent( QPaintEvent* ) {
+ QPainter p( this );
+ QStyleOption opt;
+ opt.initFrom( this );
+ QRect r = rect();
+
+ const bool reverse = opt.direction == Qt::RightToLeft;
+ const int menuButtonWidth = 12;
+ const int rightSpacing = 10;
+ const int right = !reverse ? r.right() - rightSpacing : r.left() + menuButtonWidth;
+ const int height = r.height();
+
+ QLine l1( 1, 0, right, height / 2 );
+ QLine l2( 1, height, right, height / 2 );
+
+ p.setRenderHint( QPainter::Antialiasing, true );
+
+ // Draw the shadow
+ QColor shadow( 0, 0, 0, 100 );
+ p.translate( 0, 1 );
+ p.setPen( shadow );
+ p.drawLine( l1 );
+ p.drawLine( l2 );
+
+ // Draw the main arrow
+ QColor foreGround( "#747474" );
+ p.translate( 0, -1 );
+ p.setPen( foreGround );
+ p.drawLine( l1 );
+ p.drawLine( l2 );
+ }
+ virtual QSize sizeHint() const {
+ return QSize( 20, TomahawkUtils::headerHeight() );
+
+ }
+
+};
+
BreadcrumbButton::BreadcrumbButton( Breadcrumb* parent, QAbstractItemModel* model )
: QWidget( parent )
, m_breadcrumb( parent )
, m_model( model )
, m_combo( new ComboBox( this ) )
+ , m_arrow( new BreadcrumbArrow( this ) )
{
setLayout( new QHBoxLayout );
- layout()->setContentsMargins( 0, 0, 0, 0 );
- layout()->setSpacing( 0 );
+
+ TomahawkUtils::unmarginLayout( layout() );
layout()->addWidget( m_combo );
+ layout()->addWidget( m_arrow );
setFixedHeight( TomahawkUtils::headerHeight() );
m_combo->setSizeAdjustPolicy( QComboBox::AdjustToContents );
- setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Expanding );
+ setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Expanding );
connect( m_combo, SIGNAL( activated( int ) ), SLOT( comboboxActivated( int ) ) );
}
@@ -55,44 +101,9 @@ void
BreadcrumbButton::paintEvent( QPaintEvent* )
{
QPainter p( this );
- QStyleOption opt;
- opt.initFrom( this );
- QRect r = rect();
- StyleHelper::horizontalHeader( &p, r ); // draw the background
-
- if ( !hasChildren() )
- return;
-
- bool reverse = opt.direction == Qt::RightToLeft;
- int menuButtonWidth = 12;
- int rightSpacing = 10;
- int left = !reverse ? r.right() - rightSpacing - menuButtonWidth : r.left();
- int right = !reverse ? r.right() - rightSpacing : r.left() + menuButtonWidth;
- int height = r.height();
- QRect arrowRect( ( left + right ) / 2 + ( reverse ? 6 : -6 ), 0, height, height );
-
- QStyleOption arrowOpt = opt;
- arrowOpt.rect = arrowRect;
-
- QLine l1( left, 0, right, height / 2 );
- QLine l2( left, height, right, height / 2 );
-
- p.setRenderHint( QPainter::Antialiasing, true );
-
- // Draw the shadow
- QColor shadow( 0, 0, 0, 100 );
- p.translate( 0, -1 );
- p.setPen( shadow );
- p.drawLine( l1 );
- p.drawLine( l2 );
-
- // Draw the main arrow
- QColor foreGround( "#747474" );
- p.translate( 0, 1 );
- p.setPen( foreGround );
- p.drawLine( l1 );
- p.drawLine( l2 );
+ StyleHelper::horizontalHeader( &p, rect() ); // draw the background
+ m_arrow->setVisible( hasChildren() );
}
diff --git a/src/libtomahawk/widgets/BreadcrumbButton.h b/src/libtomahawk/widgets/BreadcrumbButton.h
index 9735bfff7..cf424e7e1 100644
--- a/src/libtomahawk/widgets/BreadcrumbButton.h
+++ b/src/libtomahawk/widgets/BreadcrumbButton.h
@@ -23,6 +23,7 @@
#include
class ComboBox;
+class BreadcrumbArrow;
class QPaintEvent;
namespace Tomahawk {
@@ -63,6 +64,7 @@ private:
QPersistentModelIndex m_parentIndex;
QPersistentModelIndex m_curIndex;
ComboBox* m_combo;
+ BreadcrumbArrow* m_arrow;
};
}
diff --git a/src/libtomahawk/widgets/headerbreadcrumb.cpp b/src/libtomahawk/widgets/headerbreadcrumb.cpp
deleted file mode 100644
index a638164d0..000000000
--- a/src/libtomahawk/widgets/headerbreadcrumb.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-/* === This file is part of Tomahawk Player - ===
- *
- * Copyright 2011, Casey Link
- *
- * Tomahawk is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tomahawk is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tomahawk. If not, see .
- */
-
-#include "headerbreadcrumb.h"
-
-#include "utils/stylehelper.h"
-
-#include
-#include
-#include
-
-HeaderBreadCrumb::HeaderBreadCrumb( BreadcrumbButtonFactory* buttonFactory, QWidget* parent )
- : BreadcrumbBar( buttonFactory, parent )
-{
-}
-
-
-HeaderBreadCrumb::HeaderBreadCrumb( QWidget* parent )
- : BreadcrumbBar( parent )
-{
-}
-
-
-HeaderBreadCrumb::~HeaderBreadCrumb()
-{
-}
-
-
-void HeaderBreadCrumb::paintEvent( QPaintEvent* /* event */ )
-{
- QStylePainter p( this );
- StyleHelper::horizontalHeader( &p, rect() );
-}
diff --git a/src/libtomahawk/widgets/headerbreadcrumb.h b/src/libtomahawk/widgets/headerbreadcrumb.h
deleted file mode 100644
index 8b15ca5a8..000000000
--- a/src/libtomahawk/widgets/headerbreadcrumb.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* === This file is part of Tomahawk Player - ===
- *
- * Copyright 2011, Casey Link
- *
- * Tomahawk is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tomahawk is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tomahawk. If not, see .
- */
-
-#ifndef HEADERBREADCRUMB_H
-#define HEADERBREADCRUMB_H
-
-#include "breadcrumbbar.h"
-
-class QPaintEvent;
-
-/**
- * \brief a bread crumb widget with Tomahawk's distinctive header style
- */
-class HeaderBreadCrumb : public BreadcrumbBar
-{
- Q_OBJECT
- public:
- HeaderBreadCrumb( BreadcrumbButtonFactory* buttonFactory, QWidget* parent = 0 );
- HeaderBreadCrumb( QWidget* parent = 0 );
- ~HeaderBreadCrumb();
-
- protected:
- virtual void paintEvent( QPaintEvent* event );
-};
-
-#endif
diff --git a/src/libtomahawk/widgets/newreleaseswidget.cpp b/src/libtomahawk/widgets/newreleaseswidget.cpp
new file mode 100644
index 000000000..5d77d7404
--- /dev/null
+++ b/src/libtomahawk/widgets/newreleaseswidget.cpp
@@ -0,0 +1,368 @@
+/* === This file is part of Tomahawk Player - ===
+ *
+ * Copyright 2012, Casey Link
+ * Copyright 2010-2011, Christian Muehlhaeuser
+ * Copyright 2011, Leo Franchi
+ * Copyright 2011, Jeff Mitchell
+ *
+ * Tomahawk is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tomahawk is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tomahawk. If not, see .
+ */
+
+#include "newreleaseswidget.h"
+#include "whatshotwidget_p.h"
+#include "ui_newreleaseswidget.h"
+
+#include
+#include
+#include
+
+#include "viewmanager.h"
+#include "sourcelist.h"
+#include "tomahawksettings.h"
+#include "RecentPlaylistsModel.h"
+#include "ChartDataLoader.h"
+
+#include "audio/audioengine.h"
+#include "dynamic/GeneratorInterface.h"
+#include "playlist/playlistmodel.h"
+#include "playlist/treeproxymodel.h"
+#include "playlist/PlaylistChartItemDelegate.h"
+#include "widgets/overlaywidget.h"
+#include "utils/tomahawkutils.h"
+#include "utils/logger.h"
+#include "pipeline.h"
+
+#define HISTORY_TRACK_ITEMS 25
+#define HISTORY_PLAYLIST_ITEMS 10
+#define HISTORY_RESOLVING_TIMEOUT 2500
+
+using namespace Tomahawk;
+
+static QString s_newReleasesIdentifier = QString( "NewReleasesWidget" );
+
+
+NewReleasesWidget::NewReleasesWidget( QWidget* parent )
+ : QWidget( parent )
+ , ui( new Ui::NewReleasesWidget )
+ , m_sortedProxy( 0 )
+ , m_workerThread( 0 )
+{
+ ui->setupUi( this );
+
+ ui->albumsView->setFrameShape( QFrame::NoFrame );
+ ui->albumsView->setAttribute( Qt::WA_MacShowFocusRect, 0 );
+
+ TomahawkUtils::unmarginLayout( layout() );
+ TomahawkUtils::unmarginLayout( ui->verticalLayout_2 );
+ TomahawkUtils::unmarginLayout( ui->breadCrumbLeft->layout() );
+
+ m_crumbModelLeft = new QStandardItemModel( this );
+ m_sortedProxy = new QSortFilterProxyModel( this );
+ m_sortedProxy->setDynamicSortFilter( true );
+ m_sortedProxy->setFilterCaseSensitivity( Qt::CaseInsensitive );
+
+ ui->breadCrumbLeft->setRootIcon( QPixmap( RESPATH "images/new-releases.png" ) );
+
+ connect( ui->breadCrumbLeft, SIGNAL( activateIndex( QModelIndex ) ), SLOT( leftCrumbIndexChanged(QModelIndex) ) );
+
+
+ //m_playlistInterface = Tomahawk::playlistinterface_ptr( new ChartsPlaylistInterface( this ) );
+
+ m_workerThread = new QThread( this );
+ m_workerThread->start();
+
+ connect( Tomahawk::InfoSystem::InfoSystem::instance(),
+ SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
+ SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) );
+
+ connect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( finished( QString ) ), SLOT( infoSystemFinished( QString ) ) );
+}
+
+
+NewReleasesWidget::~NewReleasesWidget()
+{
+ qDeleteAll( m_workers );
+ m_workers.clear();
+ m_workerThread->exit(0);
+ m_playlistInterface.clear();
+ delete ui;
+}
+
+
+Tomahawk::playlistinterface_ptr
+NewReleasesWidget::playlistInterface() const
+{
+ return m_playlistInterface;
+}
+
+
+bool
+NewReleasesWidget::isBeingPlayed() const
+{
+ return false;
+}
+
+
+bool
+NewReleasesWidget::jumpToCurrentTrack()
+{
+ return false;
+}
+
+
+void
+NewReleasesWidget::fetchData()
+{
+ Tomahawk::InfoSystem::InfoStringHash artistInfo;
+
+ Tomahawk::InfoSystem::InfoRequestData requestData;
+ requestData.caller = s_newReleasesIdentifier;
+ requestData.customData = QVariantMap();
+ requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoStringHash >( artistInfo );
+ requestData.type = Tomahawk::InfoSystem::InfoNewReleaseCapabilities;
+ requestData.timeoutMillis = 20000;
+ requestData.allSources = true;
+ Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData );
+
+ tDebug( LOGVERBOSE ) << "NewReleases: requested InfoNewReleaseCapabilities";
+}
+
+
+void
+NewReleasesWidget::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output )
+{
+ if ( requestData.caller != s_newReleasesIdentifier )
+ return;
+
+ if ( !output.canConvert< QVariantMap >() )
+ {
+ tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "NewReleases: Could not parse output";
+ return;
+ }
+
+ QVariantMap returnedData = output.toMap();
+ switch ( requestData.type )
+ {
+ case InfoSystem::InfoNewReleaseCapabilities:
+ {
+ tLog() << "NewReleases: got InfoNewReleaseCapabilities";
+ QStandardItem *rootItem= m_crumbModelLeft->invisibleRootItem();
+
+ foreach ( const QString label, returnedData.keys() )
+ {
+ QStandardItem *childItem = parseNode( rootItem, label, returnedData[label] );
+ rootItem->appendRow(childItem);
+ tLog() << "NewReleases: " << label;
+ }
+
+ m_sortedProxy->setSourceModel( m_crumbModelLeft );
+ m_sortedProxy->sort( 0, Qt::AscendingOrder );
+ ui->breadCrumbLeft->setModel( m_sortedProxy );
+ break;
+ }
+
+ case InfoSystem::InfoNewRelease:
+ {
+ if( !returnedData.contains("type") )
+ break;
+ const QString type = returnedData["type"].toString();
+ if( !returnedData.contains(type) )
+ break;
+ const QString side = requestData.customData["whatshot_side"].toString();
+ const QString releaseId = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >().value( "nr_id" );
+
+ m_queuedFetches.remove( releaseId );
+
+ ChartDataLoader* loader = new ChartDataLoader();
+ loader->setProperty( "nrid", releaseId );
+ loader->moveToThread( m_workerThread );
+
+ if ( type == "albums" )
+ {
+
+ loader->setType( ChartDataLoader::Album );
+ loader->setData( returnedData[ "albums" ].value< QList< Tomahawk::InfoSystem::InfoStringHash > >() );
+
+ connect( loader, SIGNAL( albums( Tomahawk::ChartDataLoader*, QList< Tomahawk::album_ptr > ) ), this, SLOT( newReleasesLoaded( Tomahawk::ChartDataLoader*, QList ) ) );
+
+ AlbumModel* albumModel = new AlbumModel( ui->albumsView );
+
+ m_albumModels[ releaseId ] = albumModel;
+
+ if ( m_queueItemToShow == releaseId )
+ setLeftViewAlbums( albumModel );
+ }
+ else
+ {
+ // intentionally unhandled
+ }
+
+ QMetaObject::invokeMethod( loader, "go", Qt::QueuedConnection );
+
+ break;
+ }
+
+ default:
+ return;
+ }
+}
+
+
+void
+NewReleasesWidget::infoSystemFinished( QString target )
+{
+ Q_UNUSED( target );
+}
+
+
+void
+NewReleasesWidget::leftCrumbIndexChanged( QModelIndex index )
+{
+ tDebug( LOGVERBOSE ) << "NewReleases:: left crumb changed" << index.data();
+ QStandardItem* item = m_crumbModelLeft->itemFromIndex( m_sortedProxy->mapToSource( index ) );
+ if( !item )
+ return;
+ if( !item->data( Breadcrumb::ChartIdRole ).isValid() )
+ return;
+
+
+ QList indexes;
+ while ( index.parent().isValid() )
+ {
+ indexes.prepend(index);
+ index = index.parent();
+ }
+
+
+ const QString nrId = item->data( Breadcrumb::ChartIdRole ).toString();
+
+ if ( m_albumModels.contains( nrId ) )
+ {
+ setLeftViewAlbums( m_albumModels[ nrId ] );
+ return;
+ }
+
+ if ( m_queuedFetches.contains( nrId ) )
+ {
+ return;
+ }
+
+ Tomahawk::InfoSystem::InfoStringHash criteria;
+ criteria.insert( "nr_id", nrId );
+ /// Remember to lower the source!
+ criteria.insert( "nr_source", index.data().toString().toLower() );
+
+ Tomahawk::InfoSystem::InfoRequestData requestData;
+ QVariantMap customData;
+ customData.insert( "newrelease_side", "left" );
+ requestData.caller = s_newReleasesIdentifier;
+ requestData.customData = customData;
+ requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoStringHash >( criteria );
+ requestData.type = Tomahawk::InfoSystem::InfoNewRelease;
+ requestData.timeoutMillis = 20000;
+ requestData.allSources = true;
+
+ qDebug() << "Making infosystem request for chart of type:" <getInfo( requestData );
+
+ m_queuedFetches.insert( nrId );
+ m_queueItemToShow = nrId;
+}
+
+
+void
+NewReleasesWidget::changeEvent( QEvent* e )
+{
+ QWidget::changeEvent( e );
+ switch ( e->type() )
+ {
+ case QEvent::LanguageChange:
+ ui->retranslateUi( this );
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+QStandardItem*
+NewReleasesWidget::parseNode( QStandardItem* parentItem, const QString &label, const QVariant &data )
+{
+ Q_UNUSED( parentItem );
+// tDebug( LOGVERBOSE ) << "NewReleases:: parsing " << label;
+
+ QStandardItem *sourceItem = new QStandardItem(label);
+
+ if ( data.canConvert< QList< Tomahawk::InfoSystem::InfoStringHash > >() )
+ {
+ QList< Tomahawk::InfoSystem::InfoStringHash > charts = data.value< QList< Tomahawk::InfoSystem::InfoStringHash > >();
+ foreach ( Tomahawk::InfoSystem::InfoStringHash chart, charts )
+ {
+ QStandardItem *childItem= new QStandardItem( chart[ "label" ] );
+ childItem->setData( chart[ "id" ], Breadcrumb::ChartIdRole );
+ if ( chart.value( "default", "" ) == "true")
+ {
+ childItem->setData( true, Breadcrumb::DefaultRole );
+ }
+ sourceItem->appendRow( childItem );
+ }
+ }
+ else if ( data.canConvert() )
+ {
+ QVariantMap dataMap = data.toMap();
+ foreach ( const QString childLabel,dataMap.keys() )
+ {
+ QStandardItem *childItem = parseNode( sourceItem, childLabel, dataMap[childLabel] );
+ sourceItem->appendRow( childItem );
+ }
+ }
+ else if ( data.canConvert() )
+ {
+ QVariantList dataList = data.toList();
+
+ foreach ( const QVariant value, dataList )
+ {
+ QStandardItem *childItem= new QStandardItem(value.toString());
+ sourceItem->appendRow(childItem);
+ }
+ }
+ else
+ {
+ QStandardItem *childItem= new QStandardItem( data.toString() );
+ sourceItem->appendRow( childItem );
+ }
+ return sourceItem;
+}
+
+
+void
+NewReleasesWidget::setLeftViewAlbums( AlbumModel* model )
+{
+ ui->albumsView->setAlbumModel( model );
+ ui->albumsView->proxyModel()->sort( -1 ); // disable sorting, must be called after artistsViewLeft->setTreeModel
+}
+
+void
+NewReleasesWidget::newReleasesLoaded( ChartDataLoader* loader, const QList< album_ptr >& albums )
+{
+ QString chartId = loader->property( "nrid" ).toString();
+ Q_ASSERT( m_albumModels.contains( chartId ) );
+
+ if ( m_albumModels.contains( chartId ) )
+ m_albumModels[ chartId ]->addAlbums( albums );
+
+ m_workers.remove( loader );
+ loader->deleteLater();
+}
diff --git a/src/libtomahawk/widgets/newreleaseswidget.h b/src/libtomahawk/widgets/newreleaseswidget.h
new file mode 100644
index 000000000..8223f7482
--- /dev/null
+++ b/src/libtomahawk/widgets/newreleaseswidget.h
@@ -0,0 +1,126 @@
+/* === This file is part of Tomahawk Player - ===
+ *
+ * Copyright 2012, Casey Link
+ * Copyright 2010-2011, Christian Muehlhaeuser
+ * Copyright 2011, Leo Franchi
+ * Copyright 2011, Jeff Mitchell
+ *
+ * Tomahawk is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tomahawk is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tomahawk. If not, see .
+ */
+
+#ifndef NEWRELEASESWIDGET_H
+#define NEWRELEASESWIDGET_H
+
+#include
+#include
+#include
+
+#include "playlistinterface.h"
+#include "infosystem/infosystem.h"
+#include "viewpage.h"
+
+#include "utils/tomahawkutils.h"
+
+#include "dllmacro.h"
+
+class QSortFilterProxyModel;
+class QStandardItemModel;
+class QStandardItem;
+class TreeModel;
+class PlaylistModel;
+class OverlayWidget;
+class TreeProxyModel;
+class AlbumModel;
+
+namespace Ui
+{
+ class NewReleasesWidget;
+}
+
+namespace Tomahawk
+{
+ class ChartDataLoader;
+ class ChartsPlaylistInterface;
+ class ChartDataLoader;
+}
+
+/**
+ * \class
+ * \brief The tomahawk page that shows music charts.
+ */
+class DLLEXPORT NewReleasesWidget : public QWidget, public Tomahawk::ViewPage
+{
+Q_OBJECT
+
+public:
+ NewReleasesWidget( QWidget* parent = 0 );
+ ~NewReleasesWidget();
+
+ virtual QWidget* widget() { return this; }
+ virtual Tomahawk::playlistinterface_ptr playlistInterface() const;
+
+ virtual QString title() const { return tr( "New Releases" ); }
+ virtual QString description() const { return QString(); }
+
+ virtual bool showStatsBar() const { return false; }
+ virtual bool showInfoBar() const { return false; }
+
+ virtual bool jumpToCurrentTrack();
+ virtual bool isBeingPlayed() const;
+
+protected:
+ void changeEvent( QEvent* e );
+
+signals:
+ void destroyed( QWidget* widget );
+
+public slots:
+ void fetchData();
+
+private slots:
+ void infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
+ void infoSystemFinished( QString target );
+ void leftCrumbIndexChanged( QModelIndex );
+
+ void newReleasesLoaded( Tomahawk::ChartDataLoader*, const QList< Tomahawk::album_ptr >& );
+
+private:
+ void setLeftViewArtists( TreeModel* artistModel );
+ void setLeftViewAlbums( AlbumModel* albumModel );
+ void setLeftViewTracks( PlaylistModel* trackModel );
+
+
+ QStandardItem* parseNode( QStandardItem* parentItem, const QString &label, const QVariant &data );
+ Ui::NewReleasesWidget *ui;
+ Tomahawk::playlistinterface_ptr m_playlistInterface;
+
+ QStandardItemModel* m_crumbModelLeft;
+ QSortFilterProxyModel* m_sortedProxy;
+
+ // Load artist, album, and track objects in a thread
+ // {Artist,Album,Track}::get() calls are all synchronous db calls
+ // and we don't want to lock up out UI in case the db is busy (e.g. on startup)
+ QThread* m_workerThread;
+ QSet< Tomahawk::ChartDataLoader* > m_workers;
+
+ // Cache our model data
+ QHash< QString, AlbumModel* > m_albumModels;
+ QString m_queueItemToShow;
+ QSet< QString > m_queuedFetches;
+ QTimer* m_timer;
+
+ friend class Tomahawk::ChartsPlaylistInterface;
+};
+
+#endif // NEWRELEASESWIDGET_H
diff --git a/src/libtomahawk/widgets/newreleaseswidget.ui b/src/libtomahawk/widgets/newreleaseswidget.ui
new file mode 100644
index 000000000..d6122d622
--- /dev/null
+++ b/src/libtomahawk/widgets/newreleaseswidget.ui
@@ -0,0 +1,45 @@
+
+
+ NewReleasesWidget
+
+
+
+ 0
+ 0
+ 875
+ 513
+
+
+
+ -
+
+
+
+ -
+
+
+ true
+
+
+ QAbstractItemView::ExtendedSelection
+
+
+
+
+
+
+
+ AlbumView
+ QListView
+
+
+
+ Tomahawk::Breadcrumb
+ QWidget
+
+ 1
+
+
+
+
+
diff --git a/src/musicscanner.cpp b/src/musicscanner.cpp
index 0edd230a4..06a0cf2c6 100644
--- a/src/musicscanner.cpp
+++ b/src/musicscanner.cpp
@@ -174,7 +174,6 @@ MusicScanner::scan()
SLOT( commitBatch( QVariantList, QVariantList ) ), Qt::DirectConnection );
m_dirListerThreadController = new QThread( this );
- m_dirListerThreadController->setPriority( QThread::IdlePriority );
m_dirLister = QWeakPointer< DirLister >( new DirLister( m_dirs ) );
m_dirLister.data()->moveToThread( m_dirListerThreadController );
@@ -186,7 +185,7 @@ MusicScanner::scan()
connect( m_dirLister.data(), SIGNAL( finished() ),
SLOT( listerFinished() ), Qt::QueuedConnection );
- m_dirListerThreadController->start();
+ m_dirListerThreadController->start( QThread::IdlePriority );
QMetaObject::invokeMethod( m_dirLister.data(), "go" );
}
diff --git a/src/scanmanager.cpp b/src/scanmanager.cpp
index c82438481..cf3c8a7bd 100644
--- a/src/scanmanager.cpp
+++ b/src/scanmanager.cpp
@@ -196,7 +196,6 @@ ScanManager::runDirScan()
{
m_scanTimer->stop();
m_musicScannerThreadController = new QThread( this );
- m_musicScannerThreadController->setPriority( QThread::IdlePriority );
m_scanner = QWeakPointer< MusicScanner >( new MusicScanner( paths ) );
m_scanner.data()->moveToThread( m_musicScannerThreadController );
connect( m_scanner.data(), SIGNAL( finished() ), SLOT( scannerFinished() ) );
diff --git a/src/sourcetree/sourcesmodel.cpp b/src/sourcetree/sourcesmodel.cpp
index 7ee3b8b0c..5b0d96ce9 100644
--- a/src/sourcetree/sourcesmodel.cpp
+++ b/src/sourcetree/sourcesmodel.cpp
@@ -297,6 +297,11 @@ SourcesModel::appendGroups()
boost::bind( &ViewManager::whatsHotWidget, ViewManager::instance() ) );
hot->setSortValue( 4 );
+ GenericPageItem* newReleases = new GenericPageItem( this, browse, tr( "New Releases" ), QIcon( RESPATH "images/new-releases.png" ),
+ boost::bind( &ViewManager::showNewReleasesPage, ViewManager::instance() ),
+ boost::bind( &ViewManager::newReleasesWidget, ViewManager::instance() ) );
+ newReleases->setSortValue( 5 );
+
m_collectionsGroup = new GroupItem( this, m_rootItem, tr( "Friends" ), 4 );
endInsertRows();
@@ -320,7 +325,7 @@ SourcesModel::appendItem( const Tomahawk::source_ptr& source )
beginInsertRows( idx, rowCount( idx ), rowCount( idx ) );
new SourceItem( this, parent, source );
endInsertRows();
-
+
parent->checkExpandedState();
}
diff --git a/src/stackedsettingsdialog.ui b/src/stackedsettingsdialog.ui
index 63e3674a1..0500d69c6 100644
--- a/src/stackedsettingsdialog.ui
+++ b/src/stackedsettingsdialog.ui
@@ -393,7 +393,7 @@
Qt::RightToLeft
- Allow web browsers to interact with Tomahawk
+ Allow web browsers to interact with Tomahawk (recommended)
true
diff --git a/src/tomahawkapp.cpp b/src/tomahawkapp.cpp
index e4ad0d9a5..ec729071a 100644
--- a/src/tomahawkapp.cpp
+++ b/src/tomahawkapp.cpp
@@ -35,6 +35,8 @@
#include "collection.h"
#include "infosystem/infosystem.h"
#include "accounts/AccountManager.h"
+#include "accounts/spotify/SpotifyAccount.h"
+#include "accounts/lastfm/LastFmAccount.h"
#include "database/database.h"
#include "database/databasecollection.h"
#include "database/databasecommand_collectionstats.h"
@@ -64,6 +66,7 @@
#include "accounts/lastfm/LastFmAccount.h"
#include "accounts/spotify/SpotifyAccount.h"
#include "accounts/spotify/SpotifyPlaylistUpdater.h"
+#include "utils/tomahawkcache.h"
#include "config.h"
@@ -229,15 +232,7 @@ TomahawkApp::init()
tDebug() << "Init AccountManager.";
m_accountManager = QWeakPointer< Tomahawk::Accounts::AccountManager >( new Tomahawk::Accounts::AccountManager( this ) );
-
- Tomahawk::Accounts::LastFmAccountFactory* lastfmFactory = new Tomahawk::Accounts::LastFmAccountFactory();
- m_accountManager.data()->addAccountFactory( lastfmFactory );
-
- Tomahawk::Accounts::SpotifyAccountFactory* spotifyFactory = new Tomahawk::Accounts::SpotifyAccountFactory;
- m_accountManager.data()->addAccountFactory( spotifyFactory );
- m_accountManager.data()->registerAccountFactoryForFilesystem( spotifyFactory );
-
- Tomahawk::Accounts::AccountManager::instance()->loadFromConfig();
+ connect( m_accountManager.data(), SIGNAL( ready() ), SLOT( accountManagerReady() ) );
Echonest::Config::instance()->setNetworkAccessManager( TomahawkUtils::nam() );
#ifndef ENABLE_HEADLESS
@@ -331,6 +326,7 @@ TomahawkApp::~TomahawkApp()
delete m_audioEngine.data();
delete Tomahawk::Accounts::AccountManager::instance();
+ delete TomahawkUtils::Cache::instance();
#ifndef ENABLE_HEADLESS
delete m_mainwindow;
@@ -452,6 +448,7 @@ TomahawkApp::registerMetaTypes()
qRegisterMetaType< Tomahawk::InfoSystem::InfoRequestData >( "Tomahawk::InfoSystem::InfoRequestData" );
qRegisterMetaType< Tomahawk::InfoSystem::InfoPushData >( "Tomahawk::InfoSystem::InfoPushData" );
qRegisterMetaType< Tomahawk::InfoSystem::InfoSystemCache* >( "Tomahawk::InfoSystem::InfoSystemCache*" );
+ qRegisterMetaType< Tomahawk::InfoSystem::InfoPluginPtr >( "Tomahawk::InfoSystem::InfoPluginPtr" );
qRegisterMetaType< Tomahawk::InfoSystem::InfoPlugin* >( "Tomahawk::InfoSystem::InfoPlugin*" );
qRegisterMetaType< QList< Tomahawk::InfoSystem::InfoStringHash > >("QList< Tomahawk::InfoSystem::InfoStringHash > ");
@@ -461,6 +458,9 @@ TomahawkApp::registerMetaTypes()
qRegisterMetaType< QPersistentModelIndex >( "QPersistentModelIndex" );
qRegisterMetaType< Tomahawk::PlaylistInterface::LatchMode >( "Tomahawk::PlaylistInterface::LatchMode" );
+
+ qRegisterMetaType< TomahawkUtils::CacheData >( "TomahawkUtils::CacheData" );
+ qRegisterMetaTypeStreamOperators< TomahawkUtils::CacheData >( "TomahawkUtils::CacheData" );
}
@@ -603,6 +603,20 @@ TomahawkApp::spotifyApiCheckFinished()
}
+void
+TomahawkApp::accountManagerReady()
+{
+ Tomahawk::Accounts::LastFmAccountFactory* lastfmFactory = new Tomahawk::Accounts::LastFmAccountFactory();
+ m_accountManager.data()->addAccountFactory( lastfmFactory );
+
+ Tomahawk::Accounts::SpotifyAccountFactory* spotifyFactory = new Tomahawk::Accounts::SpotifyAccountFactory;
+ m_accountManager.data()->addAccountFactory( spotifyFactory );
+ m_accountManager.data()->registerAccountFactoryForFilesystem( spotifyFactory );
+
+ Tomahawk::Accounts::AccountManager::instance()->loadFromConfig();
+}
+
+
void
TomahawkApp::activate()
{
diff --git a/src/tomahawkapp.h b/src/tomahawkapp.h
index 68b060360..2c76e641c 100644
--- a/src/tomahawkapp.h
+++ b/src/tomahawkapp.h
@@ -111,6 +111,7 @@ private slots:
void initHTTP();
void spotifyApiCheckFinished();
+ void accountManagerReady();
private:
void registerMetaTypes();