diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt
index 3c275a63b..121cfdfc9 100644
--- a/src/libtomahawk/CMakeLists.txt
+++ b/src/libtomahawk/CMakeLists.txt
@@ -101,6 +101,7 @@ set( libGuiSources
     utils/m3uloader.cpp
     utils/itunesparser.cpp
     utils/rdioparser.cpp
+    utils/groovesharkparser.cpp
     utils/shortenedlinkparser.cpp
     utils/stylehelper.cpp
     utils/dropjobnotifier.cpp
@@ -218,6 +219,7 @@ set( libGuiHeaders
     utils/m3uloader.h
     utils/itunesparser.h
     utils/rdioparser.h
+    utils/groovesharkparser.h
     utils/shortenedlinkparser.h
     utils/dropjobnotifier.h
     utils/tomahawkutilsgui.h
diff --git a/src/libtomahawk/dropjob.cpp b/src/libtomahawk/dropjob.cpp
index 88e2b52fb..9a83f9c1a 100644
--- a/src/libtomahawk/dropjob.cpp
+++ b/src/libtomahawk/dropjob.cpp
@@ -26,6 +26,7 @@
 #include "utils/spotifyparser.h"
 #include "utils/itunesparser.h"
 #include "utils/rdioparser.h"
+#include "utils/groovesharkparser.h"
 #include "utils/m3uloader.h"
 #include "utils/shortenedlinkparser.h"
 #include "utils/logger.h"
@@ -120,6 +121,9 @@ DropJob::acceptsMimeData( const QMimeData* data, DropJob::DropTypes acceptedType
         // Not the most elegant
         if ( url.contains( "spotify" ) && url.contains( "playlist" ) && s_canParseSpotifyPlaylists )
             return true;
+        
+        if ( url.contains( "grooveshark.com" ) && url.contains( "playlist" ) )
+            return true;
     }
 
     if ( acceptedType.testFlag( Track ) )
@@ -188,6 +192,9 @@ DropJob::isDropType( DropJob::DropType desired, const QMimeData* data )
 
         if ( url.contains( "rdio.com" ) && url.contains( "people" ) && url.contains( "playlist" ) )
             return true;
+        
+        if ( url.contains( "grooveshark.com" ) && url.contains( "playlist" ) )
+            return true;
 
         if ( ShortenedLinkParser::handlesUrl( url ) )
             return true;
@@ -555,6 +562,27 @@ DropJob::handleRdioUrls( const QString& urlsRaw )
     rdio->parse( urls );
 }
 
+void
+DropJob::handleGroovesharkUrls ( const QString& urlsRaw )
+{
+    QStringList urls = urlsRaw.split( QRegExp( "\\s+" ), QString::SkipEmptyParts );
+    tDebug() << "Got Grooveshark urls!" << urls;
+    
+    if ( dropAction() == Default )
+        setDropAction( Create );
+
+    GroovesharkParser* groove = new GroovesharkParser( urls, dropAction() == Create, this );
+    connect( groove, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SLOT( onTracksAdded( QList< Tomahawk::query_ptr > ) ) );
+
+    if ( dropAction() == Append )
+    {
+        tDebug() << Q_FUNC_INFO << "Asking for grooveshark contents from" << urls;
+        connect( groove, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SLOT( onTracksAdded( QList< Tomahawk::query_ptr > ) ) );
+        m_queryCount++;
+    }
+}
+
+
 
 void
 DropJob::handleAllUrls( const QString& urls )
@@ -569,6 +597,8 @@ DropJob::handleAllUrls( const QString& urls )
         handleSpotifyUrls( urls );
     else if ( urls.contains( "rdio.com" ) )
         handleRdioUrls( urls );
+    else if ( urls.contains( "grooveshark.com" ) )
+        handleGroovesharkUrls( urls );
     else
         handleTrackUrls ( urls );
 }
diff --git a/src/libtomahawk/dropjob.h b/src/libtomahawk/dropjob.h
index eda72504e..71ca32787 100644
--- a/src/libtomahawk/dropjob.h
+++ b/src/libtomahawk/dropjob.h
@@ -106,6 +106,7 @@ public:
     void handleM3u( const QString& urls );
     void handleSpotifyUrls( const QString& urls );
     void handleRdioUrls( const QString& urls );
+    void handleGroovesharkUrls( const QString& urls );
 
     static bool canParseSpotifyPlaylists() { return s_canParseSpotifyPlaylists; }
     static void setCanParseSpotifyPlaylists( bool parseable ) { s_canParseSpotifyPlaylists = parseable; }
diff --git a/src/libtomahawk/utils/groovesharkparser.cpp b/src/libtomahawk/utils/groovesharkparser.cpp
new file mode 100644
index 000000000..6ee245c56
--- /dev/null
+++ b/src/libtomahawk/utils/groovesharkparser.cpp
@@ -0,0 +1,256 @@
+/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
+ *
+ *   Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
+ *   Copyright 2010-2011, Hugo Lindström <hugolm84@gmail.com>
+ *   Copyright 2010-2011, Stefan Derkits <stefan@derkits.at>
+ *
+ *   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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "groovesharkparser.h"
+
+#include "utils/logger.h"
+#include "utils/tomahawkutils.h"
+#include "query.h"
+#include "sourcelist.h"
+#include "dropjob.h"
+#include "jobview/JobStatusView.h"
+#include "jobview/JobStatusModel.h"
+#include "dropjobnotifier.h"
+#include "viewmanager.h"
+
+#include <qjson/parser.h>
+
+#include <QtCrypto>
+
+#include <QCoreApplication>
+#include <QtNetwork/QNetworkAccessManager>
+#include <QtNetwork/QNetworkReply>
+
+using namespace Tomahawk;
+
+QPixmap* GroovesharkParser::s_pixmap = 0;
+
+const char* enApiSecret = "erCj5s0Vebyqtc9Aduyotc1CLListJ9HfO2os5hBeew=";
+
+GroovesharkParser::GroovesharkParser( const QStringList& trackUrls, bool createNewPlaylist, QObject* parent )
+    : QObject ( parent )
+    , m_limit ( 40 )
+    , m_trackMode( true )
+    , m_createNewPlaylist( createNewPlaylist )
+    , m_browseJob( 0 )
+{
+    QByteArray magic = QByteArray::fromBase64( enApiSecret );
+
+    QByteArray wand = QByteArray::fromBase64( QCoreApplication::applicationName().toLatin1() );
+    int length = magic.length(), n2 = wand.length();
+    for ( int i=0; i<length; i++ ) magic[i] = magic[i] ^ wand[i%n2];
+
+    m_apiKey = QCA::SymmetricKey( magic );
+
+    foreach ( const QString& url, trackUrls )
+        lookupUrl( url );
+}
+
+GroovesharkParser::~GroovesharkParser()
+{
+
+}
+
+void
+GroovesharkParser::lookupUrl( const QString& link )
+{
+    if( link.contains( "playlist" ) )
+    {
+        if( !m_createNewPlaylist )
+            m_trackMode = true;
+        else
+            m_trackMode = false;
+
+        lookupGroovesharkPlaylist( link );
+    }
+    else
+        return;
+
+}
+
+
+void
+GroovesharkParser::lookupGroovesharkPlaylist( const QString& linkRaw )
+{
+    tLog() << "Parsing Grooveshark Playlist URI:" << linkRaw;
+
+    QStringList urlParts = linkRaw.split( "/" );
+    bool ok;
+    int playlistID = urlParts.last().toInt( &ok, 10 );
+    if (!ok)
+    {
+        tDebug() << "incorrect grooveshark url";
+        return;
+    }
+    
+    m_title = urlParts.at( urlParts.size()-2 );
+    
+    tDebug() << "should get playlist " << playlistID;
+    
+    DropJob::DropType type;
+
+    if ( linkRaw.contains( "playlist" ) )
+        type = DropJob::Playlist;
+
+    QString base_url( "http://api.grooveshark.com/ws3.php?sig=" );
+
+    QByteArray data = QString( "{\"method\":\"getPlaylistSongs\",\"parameters\":{\"playlistID\":\"%1\"},\"header\":{\"wsKey\":\"tomahawkplayer\"}}" ).arg( playlistID ).toLocal8Bit();
+    
+    
+    
+    
+    QCA::MessageAuthenticationCode hmac( "hmac(md5)", m_apiKey );
+
+    QCA::SecureArray secdata( data );
+    hmac.update(secdata);
+    QCA::SecureArray resultArray = hmac.final();
+    
+    QString hash = QCA::arrayToHex( resultArray.toByteArray() );
+    QUrl url = QUrl( base_url + hash );
+    
+    tDebug() << "Looking up URL..." << url.toString();
+
+    QNetworkReply* reply = TomahawkUtils::nam()->post( QNetworkRequest( url ), data );
+    connect( reply, SIGNAL( finished() ), this, SLOT( groovesharkLookupFinished() ) );
+
+    m_browseJob = new DropJobNotifier( pixmap(), "Grooveshark", type, reply );
+    JobStatusView::instance()->model()->addJob( m_browseJob );
+
+    m_queries.insert( reply );
+}
+
+void
+GroovesharkParser::groovesharkLookupFinished()
+{
+    QNetworkReply* r = qobject_cast< QNetworkReply* >( sender() );
+    Q_ASSERT( r );
+
+    m_queries.remove( r );
+    r->deleteLater();
+
+    if ( r->error() == QNetworkReply::NoError )
+    {
+        QJson::Parser p;
+        bool ok;
+        QVariantMap res = p.parse( r, &ok ).toMap();
+
+        if ( !ok )
+        {
+            tLog() << "Failed to parse json from Grooveshark browse item :" << p.errorString() << "On line" << p.errorLine();
+            checkTrackFinished();
+            return;
+        }
+
+        QVariantList list = res.value( "result" ).toMap().value( "songs" ).toList();
+        foreach (const QVariant& var, list)
+        {
+            QVariantMap trackResult = var.toMap();
+            
+            QString title, artist, album;
+
+            title = trackResult.value( "SongName", QString() ).toString();
+            artist = trackResult.value( "ArtistName", QString() ).toString();
+            album = trackResult.value( "AlbumName", QString() ).toString();
+
+            if ( title.isEmpty() && artist.isEmpty() ) // don't have enough...
+            {
+                tLog() << "Didn't get an artist and track name from grooveshark, not enough to build a query on. Aborting" << title << artist << album;
+                return;
+            }
+
+            Tomahawk::query_ptr q = Tomahawk::Query::get( artist, title, album, uuid(), m_trackMode );
+            m_tracks << q;
+        }
+        
+
+    } else
+    {
+        tLog() << "Error in network request to grooveshark for track decoding:" << r->errorString();
+    }
+
+    if ( m_trackMode )
+        checkTrackFinished();
+    else
+        checkPlaylistFinished();
+}
+
+void
+GroovesharkParser::checkPlaylistFinished()
+{
+    tDebug() << "Checking for grooveshark batch playlist job finished" << m_queries.isEmpty() << m_createNewPlaylist;
+    if ( m_queries.isEmpty() ) // we're done
+    {
+        if ( m_browseJob )
+            m_browseJob->setFinished();
+
+        if( m_createNewPlaylist && !m_tracks.isEmpty() )
+        {
+            m_playlist = Playlist::create( SourceList::instance()->getLocal(),
+                                       uuid(),
+                                       m_title,
+                                       m_info,
+                                       m_creator,
+                                       false,
+                                       m_tracks );
+            connect( m_playlist.data(), SIGNAL( revisionLoaded( Tomahawk::PlaylistRevision ) ), this, SLOT( playlistCreated() ) );
+            return;
+        }
+
+        
+        emit tracks( m_tracks );
+
+        deleteLater();
+    }
+}
+
+void
+GroovesharkParser::checkTrackFinished()
+{
+    tDebug() << "Checking for grooveshark batch track job finished" << m_queries.isEmpty();
+    if ( m_queries.isEmpty() ) // we're done
+    {
+        if ( m_browseJob )
+            m_browseJob->setFinished();
+
+        emit tracks( m_tracks );
+
+        deleteLater();
+    }
+
+}
+
+void
+GroovesharkParser::playlistCreated()
+{
+
+    ViewManager::instance()->show( m_playlist );
+
+    deleteLater();
+}
+
+
+QPixmap
+GroovesharkParser::pixmap() const
+{
+    if ( !s_pixmap )
+        s_pixmap = new QPixmap( RESPATH "images/grooveshark.png" );
+
+    return *s_pixmap;
+}
diff --git a/src/libtomahawk/utils/groovesharkparser.h b/src/libtomahawk/utils/groovesharkparser.h
new file mode 100644
index 000000000..a387ed928
--- /dev/null
+++ b/src/libtomahawk/utils/groovesharkparser.h
@@ -0,0 +1,87 @@
+/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
+ *
+ *   Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
+ *   Copyright 2010-2011, Hugo Lindström <hugolm84@gmail.com>
+ *   Copyright 2011, Stefan Derkits <stefan@derkits.at>
+ *
+ *   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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GROOVESHARKPARSER_H
+#define GROOVESHARKPARSER_H
+
+#include "dllmacro.h"
+#include "typedefs.h"
+#include "query.h"
+#include "jobview/JobStatusItem.h"
+
+#include <qca_basic.h>
+
+#include <QObject>
+#include <QSet>
+#include <QtCore/QStringList>
+
+/**
+ * Small class to parse grooveshark links into query_ptrs
+ *
+ * Connect to the signals to get the results
+ */
+
+class QNetworkReply;
+
+namespace Tomahawk
+{
+    
+class DropJobNotifier;
+
+class DLLEXPORT GroovesharkParser : public QObject
+{
+    Q_OBJECT
+public:
+    explicit GroovesharkParser( const QStringList& trackUrls, bool createNewPlaylist = false, QObject* parent = 0 );
+    virtual ~GroovesharkParser();
+signals:
+    void track( const Tomahawk::query_ptr& track );
+    void tracks( const QList< Tomahawk::query_ptr > tracks );
+    void playlist( const Tomahawk::query_ptr& playlist );
+
+private slots:
+    void groovesharkLookupFinished();
+
+    void playlistCreated();
+private:
+    QPixmap pixmap() const;
+
+    void lookupUrl( const QString& url );
+    void lookupGroovesharkPlaylist( const QString& playlist );
+    void checkTrackFinished();
+    void checkPlaylistFinished();
+    int  m_limit;
+    bool m_trackMode;
+    bool m_createNewPlaylist;
+    QList< query_ptr > m_tracks;
+    QSet< QNetworkReply* > m_queries;
+    QString m_title, m_info, m_creator;
+    Tomahawk::playlist_ptr m_playlist;
+    DropJobNotifier* m_browseJob;
+
+    QCA::SymmetricKey m_apiKey;
+
+    static QPixmap* s_pixmap;
+    
+};
+
+}
+
+#endif // GROOVESHARKPARSER_H