Skip to content

Commit

Permalink
Support TV app and missing iTunes
Browse files Browse the repository at this point in the history
On a fresh installation of Catalina iTunes does not exist and so the
AppleScript plugins that deal with refreshing iTunes fail in that
situation. And even when iTunes is found on Catalina MetaZ should
instead talk to the TV app.

Catalina also included a new TV app which contains the Movie and TV Show
library previously in iTunes. This commit adds plugins, services and
clipboard support for the TV app on Catalina and all functionality that
MetaZ provided for iTunes is now supported for the TV app.
  • Loading branch information
griff committed Mar 17, 2020
1 parent df409ef commit 6f33710
Show file tree
Hide file tree
Showing 34 changed files with 504 additions and 81 deletions.
16 changes: 16 additions & 0 deletions App/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,20 @@
<string>com.apple.iTunes</string>
</dict>
</dict>
<dict>
<key>NSMessage</key>
<string>doTVApp</string>
<key>NSMenuItem</key>
<dict>
<key>default</key>
<string>Open selected tracks in MetaZ</string>
</dict>
<key>NSRequiredContext</key>
<dict>
<key>NSApplicationIdentifier</key>
<string>com.apple.TV</string>
</dict>
</dict>
</array>
<key>OSAScriptingDefinition</key>
<string>MetaZ.sdef</string>
Expand All @@ -186,6 +200,8 @@
<string>https://metaz.io/appcast.xml</string>
<key>SUPublicDSAKeyFile</key>
<string>sparkle_public.pem</string>
<key>NSAppleEventsUsageDescription</key>
<string>Please give access to sync metadata with iTunes and TV app</string>
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
Expand Down
12 changes: 12 additions & 0 deletions App/resources/Return TV app selected.applescript
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
tell application "TV"
set sel to selection
set ret to {}
set retRef to a reference to ret
set len to length of sel
repeat with n from 1 to len
set obj to item n of sel
set i to {mylocation:location of obj, myid:persistent ID of obj}
copy i to the end of retRef
end repeat
end tell
return ret
14 changes: 14 additions & 0 deletions App/resources/Return TV app selected.scptd/Contents/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>com.apple.ScriptEditor.id.Return-TV-selected</string>
<key>CFBundleName</key>
<string>Return TV selected</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>LSMinimumSystemVersion</key>
<string>10.15</string>
</dict>
</plist>
Binary file not shown.
14 changes: 14 additions & 0 deletions App/resources/Return iTunes selected.scptd/Contents/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>com.apple.ScriptEditor.id.Return-iTunes-selected</string>
<key>CFBundleName</key>
<string>Return iTunes selected</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>MZMaximumSystemVersion</key>
<string>10.14</string>
</dict>
</plist>
File renamed without changes.
39 changes: 33 additions & 6 deletions App/src/AppController.m
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,11 @@ - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sende

-(void)doiTunesMetadata:(NSPasteboard *)pboard userData:(NSString *)userData error:(NSString **)error {
NSDictionary* prop = [pboard propertyListForType:iTunesMetadataPboardType];
BOOL tv = NO;
if(!prop) {
prop = [pboard propertyListForType:TVAppMetadataPboardType];
tv = YES;
}
if(!prop)
prop = [pboard propertyListForType:iTunesPboardType];

Expand All @@ -725,15 +730,35 @@ -(void)doiTunesMetadata:(NSPasteboard *)pboard userData:(NSString *)userData err
[names addObject:[location path]];

NSString* persistentId = [track objectForKey:@"Persistent ID"];
NSDictionary* data = [NSDictionary dictionaryWithObject:persistentId forKey:MZiTunesPersistentIDTagIdent];
NSDictionary* data;
if (tv) {
data = [NSDictionary dictionaryWithObject:persistentId
forKey:MZTVAppPersistentIDTagIdent];
} else {
data = [NSDictionary dictionaryWithObject:persistentId
forKey:MZiTunesPersistentIDTagIdent];
}
[dataDicts addObject:data];
}
[[MZMetaLoader sharedLoader] loadFromFiles:names withMetaData:dataDicts];
}
}

-(void)doiTunes:(NSPasteboard *)pboard userData:(NSString *)userData error:(NSString **)error {
NSString* path = [[NSBundle mainBundle] pathForResource:@"Return iTunes selected" ofType:@"scpt"];
[self doiTunes:@"Return iTunes selected"
tag:MZiTunesPersistentIDTagIdent
error:error];
}

-(void)doTVApp:(NSPasteboard *)pboard userData:(NSString *)userData error:(NSString **)error {
[self doiTunes:@"Return TV app selected"
tag:MZTVAppPersistentIDTagIdent
error:error];
}


-(void)doiTunes:(NSString *)filename tag:(NSString *)tagName error:(NSString **)error {
NSString* path = [[NSBundle mainBundle] pathForResource:filename ofType:@"scptd"];
NSURL* url = [NSURL fileURLWithPath:path];
NSDictionary* errDict = nil;
NSAppleScript* script = [[[NSAppleScript alloc] initWithContentsOfURL:url error:&errDict] autorelease];
Expand Down Expand Up @@ -773,7 +798,7 @@ -(void)doiTunes:(NSPasteboard *)pboard userData:(NSString *)userData error:(NSSt
[names addObject:[o objectForKey:@"mylocation"]];
if(!dataDicts)
dataDicts = [NSMutableArray array];
[dataDicts addObject:[NSDictionary dictionaryWithObject:[o objectForKey:@"myid"] forKey:MZiTunesPersistentIDTagIdent]];
[dataDicts addObject:[NSDictionary dictionaryWithObject:[o objectForKey:@"myid"] forKey:tagName]];
}
else
{
Expand All @@ -789,10 +814,12 @@ -(void)doiTunes:(NSPasteboard *)pboard userData:(NSString *)userData error:(NSSt
}
else if([obj isKindOfClass:[NSString class]])
[[MZMetaLoader sharedLoader] loadFromFile:obj];
else if([obj isKindOfClass:[NSDictionary class]])
else if([obj isKindOfClass:[NSDictionary class]]) {
NSDictionary* data = [NSDictionary dictionaryWithObject:[obj objectForKey:@"myid"]
forKey:tagName];
[[MZMetaLoader sharedLoader] loadFromFile:[obj objectForKey:@"mylocation"]
withMetaData:[NSDictionary dictionaryWithObject:[obj objectForKey:@"myid"]
forKey:MZiTunesPersistentIDTagIdent]];
withMetaData:data];
}
else {
NSString* err = [NSString stringWithFormat:@"Unsupported return type %@", obj];
if(error)
Expand Down
83 changes: 64 additions & 19 deletions App/src/FilesTableView.m
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ - (id)initWithFrame:(NSRect)frame
[self registerForDraggedTypes:
[NSArray arrayWithObjects:MZFilesTableRows,
MZMetaEditsDataType, iTunesMetadataPboardType,
iTunesPboardType, NSFilenamesPboardType,
NSStringPboardType, nil] ];
TVAppMetadataPboardType, iTunesPboardType,
NSFilenamesPboardType, NSStringPboardType, nil] ];
}
return self;
}
Expand All @@ -61,8 +61,8 @@ - (id)initWithCoder:(NSCoder*)decoder
[self registerForDraggedTypes:
[NSArray arrayWithObjects:MZFilesTableRows,
MZMetaEditsDataType, iTunesMetadataPboardType,
iTunesPboardType, NSFilenamesPboardType,
NSStringPboardType, nil] ];
TVAppMetadataPboardType, iTunesPboardType,
NSFilenamesPboardType, NSStringPboardType, nil] ];
}
return self;
}
Expand Down Expand Up @@ -116,9 +116,11 @@ -(IBAction)copy:(id)sender
-(IBAction)paste:(id)sender
{
NSPasteboard *pb = [NSPasteboard generalPasteboard];
NSLog(@"Pasteboard Types %@", pb.types);
NSArray *types = [NSArray arrayWithObjects:MZMetaEditsDataType,
iTunesMetadataPboardType, iTunesPboardType, NSFilenamesPboardType,
NSStringPboardType, nil];
iTunesMetadataPboardType, TVAppMetadataPboardType,
iTunesPboardType, NSFilenamesPboardType,
NSStringPboardType, nil];
NSString *bestType = [pb availableTypeFromArray:types];
if (bestType != nil)
{
Expand Down Expand Up @@ -151,9 +153,16 @@ -(IBAction)paste:(id)sender
for(MetaEdits* edit in edits)
[self registerUndoName:edit.undoManager];
}
if([bestType isEqualToString:iTunesMetadataPboardType] || [bestType isEqualToString:iTunesMetadataPboardType])
if([bestType isEqualToString:iTunesMetadataPboardType] ||
[bestType isEqualToString:TVAppMetadataPboardType] ||
[bestType isEqualToString:iTunesPboardType])
{
NSDictionary* prop = [pb propertyListForType:iTunesMetadataPboardType];
BOOL tv = NO;
if(!prop) {
prop = [pb propertyListForType:TVAppMetadataPboardType];
tv = YES;
}
if(!prop)
prop = [pb propertyListForType:iTunesPboardType];

Expand All @@ -168,7 +177,14 @@ -(IBAction)paste:(id)sender
[names addObject:[location path]];

NSString* persistentId = [track objectForKey:@"Persistent ID"];
NSDictionary* data = [NSDictionary dictionaryWithObject:persistentId forKey:MZiTunesPersistentIDTagIdent];
NSDictionary* data;
if (tv) {
data = [NSDictionary dictionaryWithObject:persistentId
forKey:MZTVAppPersistentIDTagIdent];
} else {
data = [NSDictionary dictionaryWithObject:persistentId
forKey:MZiTunesPersistentIDTagIdent];
}
[dataDicts addObject:data];
}
[[MZMetaLoader sharedLoader] loadFromFiles:names withMetaData:dataDicts];
Expand All @@ -193,9 +209,11 @@ -(IBAction)paste:(id)sender

- (BOOL)pasteboardHasTypes {
NSPasteboard *pb = [NSPasteboard generalPasteboard];
NSLog(@"Pasteboard Types %@", pb.types);
NSArray *types = [NSArray arrayWithObjects:MZMetaEditsDataType,
iTunesMetadataPboardType, iTunesPboardType, NSFilenamesPboardType,
NSStringPboardType, nil];
iTunesMetadataPboardType, TVAppMetadataPboardType,
iTunesPboardType, NSFilenamesPboardType,
NSStringPboardType, nil];
NSString *bestType = [pb availableTypeFromArray:types];
if(bestType != nil && [bestType isEqualToString:MZMetaEditsDataType])
return [self numberOfSelectedRows] > 0;
Expand All @@ -217,10 +235,14 @@ - (BOOL)pasteboardHasTypes {
return NO;
}
}
if(bestType != nil && ([bestType isEqualToString:iTunesMetadataPboardType] ||
[bestType isEqualToString:iTunesPboardType]))
if(bestType != nil &&
([bestType isEqualToString:iTunesMetadataPboardType] ||
[bestType isEqualToString:TVAppMetadataPboardType] ||
[bestType isEqualToString:iTunesPboardType]))
{
NSDictionary* prop = [pb propertyListForType:iTunesMetadataPboardType];
if(!prop)
prop = [pb propertyListForType:TVAppMetadataPboardType];
if(!prop)
prop = [pb propertyListForType:iTunesPboardType];

Expand Down Expand Up @@ -351,7 +373,8 @@ - (NSDragOperation)tableView:(NSTableView*)tv

NSPasteboard* pboard = [info draggingPasteboard];
NSArray *types = [NSArray arrayWithObjects:MZFilesTableRows,
MZMetaEditsDataType, iTunesMetadataPboardType, iTunesPboardType,
MZMetaEditsDataType, iTunesMetadataPboardType,
TVAppMetadataPboardType, iTunesPboardType,
NSFilenamesPboardType, NSStringPboardType, nil];
//NSDragOperation operation = [info draggingSourceOperationMask];
NSString *bestType = [pboard availableTypeFromArray:types];
Expand Down Expand Up @@ -380,7 +403,8 @@ - (NSDragOperation)tableView:(NSTableView*)tv
}
return NSDragOperationGeneric;
}
if([bestType isEqualToString:iTunesMetadataPboardType] ||
if([bestType isEqualToString:iTunesMetadataPboardType] ||
[bestType isEqualToString:TVAppMetadataPboardType] ||
[bestType isEqualToString:iTunesPboardType])
{
return NSDragOperationGeneric;
Expand All @@ -395,8 +419,9 @@ - (BOOL)tableView:(NSTableView *)aTableView acceptDrop:(id <NSDraggingInfo>)info
{
NSPasteboard* pboard = [info draggingPasteboard];
NSArray *types = [NSArray arrayWithObjects:MZFilesTableRows,
MZMetaEditsDataType, iTunesMetadataPboardType, iTunesPboardType,
NSFilenamesPboardType, NSStringPboardType, nil];
MZMetaEditsDataType, iTunesMetadataPboardType,
TVAppMetadataPboardType, iTunesPboardType,
NSFilenamesPboardType, NSStringPboardType, nil];
NSString *bestType = [pboard availableTypeFromArray:types];
if (bestType != nil)
{
Expand All @@ -409,9 +434,16 @@ - (BOOL)tableView:(NSTableView *)aTableView acceptDrop:(id <NSDraggingInfo>)info
[[MZMetaLoader sharedLoader] moveObjects:edits toIndex:row];
return YES;
}
if([bestType isEqualToString:iTunesMetadataPboardType] || [bestType isEqualToString:iTunesMetadataPboardType])
if([bestType isEqualToString:iTunesMetadataPboardType] ||
[bestType isEqualToString:TVAppMetadataPboardType] ||
[bestType isEqualToString:iTunesPboardType])
{
NSDictionary* prop = [pboard propertyListForType:iTunesMetadataPboardType];
BOOL tv = NO;
if(!prop) {
prop = [pboard propertyListForType:TVAppMetadataPboardType];
tv = YES;
}
if(!prop)
prop = [pboard propertyListForType:iTunesPboardType];

Expand All @@ -426,7 +458,9 @@ - (BOOL)tableView:(NSTableView *)aTableView acceptDrop:(id <NSDraggingInfo>)info
}
if(![filesController commitEditing])
return NO;
NSArray* params = [NSArray arrayWithObjects:prop, [NSNumber numberWithInteger:row], nil];
NSArray* params = [NSArray arrayWithObjects:prop,
[NSNumber numberWithInteger:row],
[NSNumber numberWithBool:tv], nil];
[self performSelector:@selector(loadFiles:) withObject:params afterDelay:1];
return YES;
}
Expand Down Expand Up @@ -470,6 +504,10 @@ - (void)loadFiles:(NSArray *)params
{
id first = [params objectAtIndex:0];
NSInteger row = [[params objectAtIndex:1] integerValue];
BOOL tv = NO;
if ([params count] == 3) {
tv = [[params objectAtIndex:2] boolValue];
}

if([first isKindOfClass:[NSDictionary class]])
{
Expand All @@ -482,7 +520,14 @@ - (void)loadFiles:(NSArray *)params
[names addObject:[location path]];

NSString* persistentId = [track objectForKey:@"Persistent ID"];
NSDictionary* data = [NSDictionary dictionaryWithObject:persistentId forKey:MZiTunesPersistentIDTagIdent];
NSDictionary* data;
if (tv) {
data = [NSDictionary dictionaryWithObject:persistentId
forKey:MZTVAppPersistentIDTagIdent];
} else {
data = [NSDictionary dictionaryWithObject:persistentId
forKey:MZiTunesPersistentIDTagIdent];
}
[dataDicts addObject:data];
}
[[MZMetaLoader sharedLoader] loadFromFiles:names toIndex:row withMetaData:dataDicts];
Expand Down
26 changes: 26 additions & 0 deletions App/src/main.m
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,32 @@ int main(int argc, const char *argv[])
[[NSUserDefaults standardUserDefaults] setInteger:version forKey:@"version"];
}

NSString* lastRunVersionStr = [[NSUserDefaults standardUserDefaults] stringForKey:@"lastRunVersion"];
MZVersion* lastRunVersion = nil;
if (lastRunVersionStr) {
lastRunVersion = [MZVersion versionWithString:lastRunVersionStr];
}
MZVersion* catalina = [MZVersion versionWithString:@"10.15.0"];
MZVersion* system = [MZVersion systemVersion];
if ([system isGreaterThanOrEqualTo:catalina] &&
(!lastRunVersion || [lastRunVersion isLessThan:system]))
{
// Upgraded to Catalina
NSArray* actions = [[NSUserDefaults standardUserDefaults] arrayForKey:@"enabledActionPlugins"];
NSMutableArray* enabled = [NSMutableArray array];
for (NSString* key in actions) {
if([key isEqualToString:@"Add to iTunes"]) {
[enabled addObject:@"Add to TV app"];
} else if ([key isEqualToString:@"Update iTunes"]) {
[enabled addObject:@"Update TV app"];
} else {
[enabled addObject:key];
}
}
[[NSUserDefaults standardUserDefaults] setObject:enabled forKey:@"enabledActionPlugins"];
}
[[NSUserDefaults standardUserDefaults] setObject:system.description forKey:@"lastRunVersion"];

[pool release];
return NSApplicationMain(argc, argv);
}
2 changes: 2 additions & 0 deletions Framework/src/MZConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ MZKIT_EXTERN NSString* const MZASINTagIdent;
MZKIT_EXTERN NSString* const MZDVDSeasonTagIdent;
MZKIT_EXTERN NSString* const MZDVDEpisodeTagIdent;
MZKIT_EXTERN NSString* const MZiTunesPersistentIDTagIdent;
MZKIT_EXTERN NSString* const MZTVAppPersistentIDTagIdent;

/* Notifications */
MZKIT_EXTERN NSString* const MZDataProviderLoadedNotification;
Expand Down Expand Up @@ -222,6 +223,7 @@ MZKIT_EXTERN NSString* const MZNSErrorKey;
// Standard alert ids
MZKIT_EXTERN NSString* const MZDataProviderFileAlreadyLoadedWarningKey;

MZKIT_EXTERN NSString* const TVAppMetadataPboardType;
MZKIT_EXTERN NSString* const iTunesMetadataPboardType;
MZKIT_EXTERN NSString* const iTunesPboardType;

Expand Down

0 comments on commit 6f33710

Please sign in to comment.