1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-07-31 19:30:21 +02:00

Add some mac-specific code. Tomahawk now opens spiffs from the browser

or the finder. There is also commented out code for handling multimedia keys.

Thanks to the Clementine project for the cocoa code :)
This commit is contained in:
Leo Franchi
2011-02-13 12:37:03 -05:00
parent d9bc06a4f6
commit 0ca1212691
10 changed files with 453 additions and 13 deletions

View File

@@ -23,6 +23,36 @@
<key>CFBundleName</key>
<string>Tomahawk</string>
<key>LSMinimumSystemVersion</key>
<string>10.5.0</string>
<string>10.5.0</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>Tomahawk URL</string>
<key>CFBundleURLSchemes</key>
<array>
<string>tomahawk</string>
</array>
</dict>
</array>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>xspf</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>Generic.icns</string>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>application/xspf+xml</string>
</array>
<key>CFBundleTypeName</key>
<string>XSPF Playlist</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
</array>
</dict>
</plist>

View File

@@ -4,6 +4,7 @@
#define APP TomahawkApp::instance()
#include "headlesscheck.h"
#include "tomahawkapp_mac.h" // for PlatforInterface
#include <QRegExp>
#include <QFile>
@@ -47,7 +48,7 @@ class TomahawkWindow;
// this also acts as a a container for important top-level objects
// that other parts of the app need to find
// (eg, library, pipeline, friends list)
class TomahawkApp : public TOMAHAWK_APPLICATION
class TomahawkApp : public TOMAHAWK_APPLICATION, public Tomahawk::PlatformInterface
{
Q_OBJECT
@@ -69,6 +70,10 @@ public:
void addScriptResolver( const QString& scriptPath );
void removeScriptResolver( const QString& scriptPath );
// PlatformInterface
virtual void activate();
virtual bool loadUrl( const QString& url );
signals:
void settingsChanged();

View File

@@ -2,6 +2,31 @@ SET( OS_SPECIFIC_LINK_LIBRARIES
${OS_SPECIFIC_LINK_LIBRARIES}
${COREAUDIO_LIBRARY}
${COREFOUNDATION_LIBRARY}
/System/Library/Frameworks/AppKit.framework
/System/Library/Frameworks/Carbon.framework
/System/Library/Frameworks/DiskArbitration.framework
/System/Library/Frameworks/Foundation.framework
/System/Library/Frameworks/IOKit.framework
rtaudio
tomahawklib
)
if (APPLE)
# find_library(GROWL Growl)
# option(ENABLE_SPARKLE "Sparkle updating" ON)
# find_library(SPARKLE Sparkle)
# if (ENABLE_SPARKLE AND SPARKLE)
# set(HAVE_SPARKLE ON)
# endif (ENABLE_SPARKLE AND SPARKLE)
# Uses Darwin kernel version.
# 9.8.0 -> 10.5/Leopard
# 10.4.0 -> 10.6/Snow Leopard
string(REGEX MATCH "[0-9]+" DARWIN_VERSION ${CMAKE_HOST_SYSTEM_VERSION})
if (DARWIN_VERSION GREATER 9)
SET(SNOW_LEOPARD 1)
elseif (DARWIN_VERSION GREATER 8)
SET(LEOPARD 1)
endif (DARWIN_VERSION GREATER 9)
endif (APPLE)

View File

@@ -57,6 +57,12 @@ SET( tomahawkSourcesGui ${tomahawkSourcesGui}
tomahawkwindow.cpp
)
IF( APPLE )
SET( tomahawkHeaders ${tomahawkHeaders} tomahawkapp_mac.h )
SET( tomahawkSources ${tomahawkSources} tomahawkapp_mac.mm )
ENDIF( APPLE )
SET( tomahawkHeaders ${tomahawkHeaders}
"${TOMAHAWK_INC_DIR}/tomahawk/tomahawkapp.h"
"${TOMAHAWK_INC_DIR}/tomahawk/infosystem.h"
@@ -138,6 +144,9 @@ kde4_add_app_icon( tomahawkSources "${CMAKE_CURRENT_SOURCE_DIR}/../data/icons/to
qt4_add_resources( RC_SRCS "../resources.qrc" )
qt4_wrap_cpp( tomahawkMoc ${tomahawkHeaders} )
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
${CMAKE_CURRENT_BINARY_DIR}/config.h)
SET( final_src ${final_src} ${tomahawkMoc} ${tomahawkSources} ${tomahawkHeaders} )
IF( "${gui}" STREQUAL "no" )
@@ -152,6 +161,8 @@ IF( UNIX AND NOT APPLE )
ENDIF( UNIX AND NOT APPLE )
IF( APPLE )
ADD_EXECUTABLE( tomahawk MACOSX_BUNDLE ${final_src} )
SET_TARGET_PROPERTIES(tomahawk PROPERTIES MACOSX_BUNDLE_INFO_PLIST "../admin/mac/Info.plist"
)
ENDIF( APPLE )
IF( WIN32 )
ADD_EXECUTABLE( tomahawk ${final_src} )

10
src/config.h.in Normal file
View File

@@ -0,0 +1,10 @@
#ifndef CONFIG_H_IN
#define CONFIG_H_IN
#define CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}"
#cmakedefine SNOW_LEOPARD
#cmakedefine LEOPARD
#cmakedefine HAVE_SPARKLE
#endif // CONFIG_H_IN

View File

@@ -1,8 +1,24 @@
#include "tomahawk/tomahawkapp.h"
#ifdef Q_WS_MAC
#include "tomahawkapp_mac.h"
#include </System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/AE.framework/Versions/A/Headers/AppleEvents.h>
static pascal OSErr appleEventHandler( const AppleEvent*, AppleEvent*, long );
#endif
#include <exception>
int main( int argc, char *argv[] )
{
#ifdef Q_WS_MAC
// Do Mac specific startup to get media keys working.
// This must go before QApplication initialisation.
Tomahawk::macMain();
// used for url handler
AEEventHandlerUPP h = AEEventHandlerUPP( appleEventHandler );
AEInstallEventHandler( 'GURL', 'GURL', h, 0, false );
#endif
try {
TomahawkApp a( argc, argv );
return a.exec();
@@ -10,3 +26,31 @@ int main( int argc, char *argv[] )
return 0;
}
}
#ifdef Q_WS_MAC
static pascal OSErr appleEventHandler( const AppleEvent* e, AppleEvent*, long )
{
OSType id = typeWildCard;
AEGetAttributePtr( e, keyEventIDAttr, typeType, 0, &id, sizeof(id), 0 );
switch (id)
{
case 'GURL':
{
DescType type;
Size size;
char buf[1024];
AEGetParamPtr( e, keyDirectObject, typeChar, &type, &buf, 1023, &size );
buf[size] = '\0';
QString url = QString::fromUtf8( buf );
static_cast<TomahawkApp*>(qApp)->loadUrl( url );
return noErr;
}
default:
return unimpErr;
}
}
#endif

View File

@@ -5,6 +5,8 @@
#include <QMetaType>
#include <QTime>
#include <QNetworkReply>
#include <QFile>
#include <QFileInfo>
#include "artist.h"
#include "album.h"
@@ -31,6 +33,10 @@
#include <QMessageBox>
#endif
#ifdef Q_WS_MAC
#include "tomahawkapp_mac.h"
#endif
#include <iostream>
#include <fstream>
@@ -176,6 +182,10 @@ TomahawkApp::TomahawkApp( int& argc, char *argv[] )
TomahawkUtils::setNam( new QNetworkAccessManager );
#endif
#ifdef Q_WS_MAC
Tomahawk::setApplicationHandler( this );
#endif
// Set up proxy
if( TomahawkSettings::instance()->proxyType() != QNetworkProxy::NoProxy &&
!TomahawkSettings::instance()->proxyHost().isEmpty() )
@@ -454,16 +464,20 @@ TomahawkApp::setupSIP()
}
}
void
TomahawkApp::messageReceived( const QString& msg )
void
TomahawkApp::activate()
{
qDebug() << "MESSAGE RECEIVED" << msg;
if( msg.isEmpty() ) {
return;
}
if( msg.contains( "tomahawk://" ) ) {
QString cmd = msg.mid( 11 );
#ifndef TOMAHAWK_HEADLESS
mainWindow()->show();
#endif
}
bool
TomahawkApp::loadUrl( const QString& url )
{
if( url.contains( "tomahawk://" ) ) {
QString cmd = url.mid( 11 );
qDebug() << "tomahawk!s" << cmd;
if( cmd.startsWith( "load/" ) ) {
cmd = cmd.mid( 5 );
@@ -474,7 +488,26 @@ TomahawkApp::messageReceived( const QString& msg )
l->load( QUrl( cmd.mid( 5 ) ) );
}
}
}
} else {
QFile f( url );
QFileInfo info( f );
if( f.exists() && info.suffix() == "xspf" ) {
XSPFLoader* l = new XSPFLoader( true, this );
qDebug() << "Loading spiff:" << url;
l->load( QUrl( url ) );
}
}
return true;
}
void
TomahawkApp::messageReceived( const QString& msg )
{
qDebug() << "MESSAGE RECEIVED" << msg;
if( msg.isEmpty() ) {
return;
}
loadUrl( msg );
}

28
src/tomahawkapp_mac.h Normal file
View File

@@ -0,0 +1,28 @@
#ifndef TOMAHAWKAPP_MAC_H
#define TOMAHAWKAPP_MAC_H
// this file and tomahawk_app.mm copied and inspired by mac_startup.* in clementine player,
// copyright David Sansome 2010
class QString;
namespace Tomahawk {
/// Interface between cocoa and tomahawk
class PlatformInterface {
public:
// Called when the application should show itself.
virtual void activate() = 0;
virtual bool loadUrl( const QString& url ) = 0;
virtual ~PlatformInterface() {}
};
void macMain();
//void setShortcutHandler(GlobalShortcuts* handler);
// used for opening files with tomahawk
void setApplicationHandler(PlatformInterface* handler);
};
#endif

229
src/tomahawkapp_mac.mm Normal file
View File

@@ -0,0 +1,229 @@
#include "tomahawkapp_mac.h"
#include "tomahawkapp_macdelegate.h"
#include <QDebug>
#import <AppKit/NSApplication.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSBundle.h>
#import <Foundation/NSError.h>
#import <Foundation/NSFileManager.h>
#import <Foundation/NSPathUtilities.h>
#import <Foundation/NSThread.h>
#import <Foundation/NSTimer.h>
#import <Foundation/NSAppleEventManager.h>
#import <Foundation/NSURL.h>
#import <AppKit/NSEvent.h>
#import <AppKit/NSNibDeclarations.h>
// Capture global media keys on Mac (Cocoa only!)
// See: http://www.rogueamoeba.com/utm/2007/09/29/apple-keyboard-media-key-event-handling/
@interface MacApplication :NSApplication {
// MacGlobalShortcutBackend* shortcut_handler_;
Tomahawk::PlatformInterface* application_handler_;
}
//- (MacGlobalShortcutBackend*) shortcut_handler;
//- (void) SetShortcutHandler: (MacGlobalShortcutBackend*)handler;
- (Tomahawk::PlatformInterface*) application_handler;
- (void) SetApplicationHandler: (Tomahawk::PlatformInterface*)handler;
- (void)getUrl:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent;
//- (void) mediaKeyEvent: (int)key state: (BOOL)state repeat: (BOOL)repeat;
@end
@implementation AppDelegate
- (id) init {
if ((self = [super init])) {
application_handler_ = nil;
// dock_menu_ = nil;
}
return self;
}
- (id) initWithHandler: (Tomahawk::PlatformInterface*)handler {
application_handler_ = handler;
return self;
}
- (BOOL) applicationShouldHandleReopen: (NSApplication*)app hasVisibleWindows:(BOOL)flag {
if (application_handler_) {
application_handler_->activate();
}
return YES;
}
/*
- (void) setDockMenu: (NSMenu*)menu {
dock_menu_ = menu;
}
- (NSMenu*) applicationDockMenu: (NSApplication*)sender {
return dock_menu_;
}
*/
- (BOOL) application: (NSApplication*)app openFile:(NSString*)filename {
qDebug() << "Wants to open:" << [filename UTF8String];
if (application_handler_->loadUrl(QString::fromUtf8([filename UTF8String]))) {
return YES;
}
return NO;
}
@end
@implementation MacApplication
- (id) init {
if ((self = [super init])) {
// [self SetShortcutHandler:nil];
[self SetApplicationHandler:nil];
NSAppleEventManager *em = [NSAppleEventManager sharedAppleEventManager];
[em
setEventHandler:self
andSelector:@selector(getUrl:withReplyEvent:)
forEventClass:kInternetEventClass
andEventID:kAEGetURL];
[em
setEventHandler:self
andSelector:@selector(getUrl:withReplyEvent:)
forEventClass:'WWW!'
andEventID:'OURL'];
NSString *bundleID = [[NSBundle mainBundle] bundleIdentifier];
OSStatus httpResult = LSSetDefaultHandlerForURLScheme((CFStringRef)@"tomahawk", (CFStringRef)bundleID);
//TODO: Check httpResult and httpsResult for errors
}
return self;
}
/*
- (MacGlobalShortcutBackend*) shortcut_handler {
return shortcut_handler_;
}
- (void) SetShortcutHandler: (MacGlobalShortcutBackend*)handler {
shortcut_handler_ = handler;
}
*/
- (Tomahawk::PlatformInterface*) application_handler {
return application_handler_;
}
- (void) SetApplicationHandler: (Tomahawk::PlatformInterface*)handler {
AppDelegate* delegate = [[AppDelegate alloc] initWithHandler:handler];
[self setDelegate:delegate];
}
-(void) sendEvent: (NSEvent*)event {
if ([event type] == NSSystemDefined && [event subtype] == 8) {
int keycode = (([event data1] & 0xFFFF0000) >> 16);
int keyflags = ([event data1] & 0x0000FFFF);
int keystate = (((keyflags & 0xFF00) >> 8)) == 0xA;
int keyrepeat = (keyflags & 0x1);
//[self mediaKeyEvent: keycode state: keystate repeat: keyrepeat];
}
[super sendEvent: event];
}
/*
-(void) mediaKeyEvent: (int)key state: (BOOL)state repeat: (BOOL)repeat {
if (!shortcut_handler_) {
return;
}
if (state == 0) {
shortcut_handler_->MacMediaKeyPressed(key);
}
} */
- (void)getUrl:(NSAppleEventDescriptor *)event
withReplyEvent:(NSAppleEventDescriptor *)replyEvent
{
// Get the URL
NSString *urlStr = [[event paramDescriptorForKeyword:keyDirectObject]
stringValue];
qDebug() << "Wants to open:" << [urlStr UTF8String];
//TODO: Your custom URL handling code here
}
@end
void Tomahawk::macMain() {
[[NSAutoreleasePool alloc] init];
// Creates and sets the magic global variable so QApplication will find it.
[MacApplication sharedApplication];
#ifdef HAVE_SPARKLE
// Creates and sets the magic global variable for Sparkle.
[[SUUpdater sharedUpdater] setDelegate: NSApp];
#endif
}
/*
void setShortcutHandler(MacGlobalShortcutBackend* handler) {
[NSApp SetShortcutHandler: handler];
}
*/
void Tomahawk::setApplicationHandler(Tomahawk::PlatformInterface* handler) {
[NSApp SetApplicationHandler: handler];
}
void CheckForUpdates() {
#ifdef HAVE_SPARKLE
[[SUUpdater sharedUpdater] checkForUpdates: NSApp];
#endif
}
QString GetBundlePath() {
CFURLRef app_url = CFBundleCopyBundleURL(CFBundleGetMainBundle());
CFStringRef mac_path = CFURLCopyFileSystemPath(app_url, kCFURLPOSIXPathStyle);
const char* path = CFStringGetCStringPtr(mac_path, CFStringGetSystemEncoding());
QString bundle_path = QString::fromUtf8(path);
CFRelease(app_url);
CFRelease(mac_path);
return bundle_path;
}
QString GetResourcesPath() {
QString bundle_path = GetBundlePath();
return bundle_path + "/Contents/Resources";
}
QString GetApplicationSupportPath() {
NSAutoreleasePool* pool = [NSAutoreleasePool alloc];
[pool init];
NSArray* paths = NSSearchPathForDirectoriesInDomains(
NSApplicationSupportDirectory,
NSUserDomainMask,
YES);
QString ret;
if ([paths count] > 0) {
NSString* user_path = [paths objectAtIndex:0];
ret = QString::fromUtf8([user_path UTF8String]);
} else {
ret = "~/Library/Application Support";
}
[pool drain];
return ret;
}
QString GetMusicDirectory() {
NSAutoreleasePool* pool = [NSAutoreleasePool alloc];
[pool init];
NSArray* paths = NSSearchPathForDirectoriesInDomains(
NSMusicDirectory,
NSUserDomainMask,
YES);
QString ret;
if ([paths count] > 0) {
NSString* user_path = [paths objectAtIndex:0];
ret = QString::fromUtf8([user_path UTF8String]);
} else {
ret = "~/Music";
}
[pool drain];
return ret;
}

View File

@@ -0,0 +1,25 @@
#import <AppKit/NSApplication.h>
#include "config.h"
// this file copied and inspired by mac_startup.* in clementine player,
// copyright David Sansome 2010
namespace Tomahawk {
class PlatformInterface;
}
#ifdef SNOW_LEOPARD
@interface AppDelegate : NSObject <NSApplicationDelegate> {
#else
@interface AppDelegate : NSObject {
#endif
Tomahawk::PlatformInterface* application_handler_;
//NSMenu* dock_menu_;
}
- (id) initWithHandler: (Tomahawk::PlatformInterface*)handler;
// NSApplicationDelegate
- (BOOL) applicationShouldHandleReopen: (NSApplication*)app hasVisibleWindows:(BOOL)flag;
//- (NSMenu*) applicationDockMenu: (NSApplication*)sender;
//- (void) setDockMenu: (NSMenu*)menu;
@end