From af9243087c60c645aa5aab51dcf31ad4b8dd47e6 Mon Sep 17 00:00:00 2001 From: Aleksi Sitomaniemi Date: Fri, 21 Oct 2022 11:02:51 +0300 Subject: [PATCH 1/5] UADE Integration: Add preliminary replayer implementation --- 4champ/Replay/Hively/HVLReplayer.mm | 9 +- 4champ/Replay/ModulePlayer.swift | 1 + 4champ/Replay/OpenMPT/MPTReplayer.m | 57 ++- 4champ/Replay/Replay.h | 11 + 4champ/Replay/Replay.m | 37 +- 4champ/Replay/UADE/UADEReplayer.h | 15 + 4champ/Replay/UADE/UADEReplayer.m | 372 ++++++++++++++++++ .../SamplePlayer.xcodeproj/project.pbxproj | 40 +- .../Modules.bundle/sweet_dreams.aon | Bin 0 -> 55836 bytes 9 files changed, 524 insertions(+), 18 deletions(-) create mode 100644 4champ/Replay/UADE/UADEReplayer.h create mode 100644 4champ/Replay/UADE/UADEReplayer.m create mode 100644 SamplePlayer/SamplePlayer/Modules.bundle/sweet_dreams.aon diff --git a/4champ/Replay/Hively/HVLReplayer.mm b/4champ/Replay/Hively/HVLReplayer.mm index 861e378..0bbe035 100644 --- a/4champ/Replay/Hively/HVLReplayer.mm +++ b/4champ/Replay/Hively/HVLReplayer.mm @@ -25,10 +25,11 @@ @implementation HVLReplayer { int hvlStereoSeparation; } - - static int iHivelyBufPos = 0; ++ (NSArray*)supportedFormats { + return @[@"THX", @"AHX", @"HVL"]; +} - (HVLReplayer*) init { self = [super init]; @@ -59,6 +60,10 @@ defstereo is the stereo seperation for playing AHX tunes (HVL tunes override } - (void)dealloc { + NSLog(@"HVLReplayer deallocated"); +} + +- (void) cleanup { if (currentHVLtune) { hvl_FreeTune(currentHVLtune); free(leftByte); diff --git a/4champ/Replay/ModulePlayer.swift b/4champ/Replay/ModulePlayer.swift index e1186e1..de0966f 100644 --- a/4champ/Replay/ModulePlayer.swift +++ b/4champ/Replay/ModulePlayer.swift @@ -13,6 +13,7 @@ enum PlayerError: Error { case unknown } + /// possible states of a ModulePlayer enum PlayerStatus:Int { case initialised diff --git a/4champ/Replay/OpenMPT/MPTReplayer.m b/4champ/Replay/OpenMPT/MPTReplayer.m index 42e57ee..4e7da7f 100644 --- a/4champ/Replay/OpenMPT/MPTReplayer.m +++ b/4champ/Replay/OpenMPT/MPTReplayer.m @@ -12,6 +12,53 @@ @implementation MPTReplayer { openmpt_module* currentOMPTFile; } ++ (NSArray*)supportedFormats { + return @[@"669", + @"AMF", + @"AMS", + @"DBM", + @"DIGI", + @"DMF", + @"DSM", + @"DTM", + @"FAR", + @"IT", + @"GDM", + @"ST26", + @"IMF", + @"J2B", + @"M15", + //@"MED", UADE + @"MDL", + @"MOD", + @"MT2", + @"MTM", + @"NST", + @"OCT", + @"OKT", + @"OSS", + @"PTM", + @"PSM", + @"S3M", + @"STM", + @"SFX", + @"SFX2", + @"ULT", + @"UMX", + @"WOW", + @"XM", + @"FST", + @"STK", + @"MMCMP", + @"MMS", + @"MO3", + @"MPTM", + @"OK", + @"PLM", + @"PPM", + @"PT36"]; +} + - (bool) loadModule:(NSString *)path type:(NSString*)type { NSData* data = [[NSFileManager defaultManager] contentsAtPath:path]; if (!data) return false; @@ -22,9 +69,13 @@ - (bool) loadModule:(NSString *)path type:(NSString*)type { } - (void)dealloc { - if (currentOMPTFile) { - openmpt_module_destroy(currentOMPTFile); - } + NSLog(@"MTPReplayer deallocated"); +} + +- (void) cleanup { + if (currentOMPTFile) { + openmpt_module_destroy(currentOMPTFile); + } } - (int) readFrames:(size_t)count bufLeft:(int16_t*)bufLeft bufRight:(int16_t*)bufRight { diff --git a/4champ/Replay/Replay.h b/4champ/Replay/Replay.h index 0fae183..0073634 100644 --- a/4champ/Replay/Replay.h +++ b/4champ/Replay/Replay.h @@ -9,6 +9,11 @@ @protocol ReplayControl // Control API +/** + Supported @formats + */ +@property (class, nonatomic, strong, readonly) NSArray* supportedFormats; + /** Loads module for playback from given path. @param path identifies the module file. Path extension can identify format (type) @@ -35,6 +40,12 @@ in libpopenmpt.h */ - (void) setInterpolationFilterLength:(NSInteger)value; + +/** + Free replayer resources + */ +- (void) cleanup; + @end @protocol ReplayInformation diff --git a/4champ/Replay/Replay.m b/4champ/Replay/Replay.m index 55f9ab5..6ba9ee4 100644 --- a/4champ/Replay/Replay.m +++ b/4champ/Replay/Replay.m @@ -7,6 +7,7 @@ #import "Replay.h" #import "MPTReplayer.h" +#import "UADEReplayer.h" #import "HVLReplayer.h" #import #import @@ -22,6 +23,7 @@ @interface Replay () { @property (nonatomic, strong) AVAudioPlayer *audioPlayer; @property (nonatomic, strong) NSDictionary* replayerMap; +@property (nonatomic, strong) NSArray* replayers; #define checkStatus( err) \ if(err) {\ NSLog(@"Error in audio %@", @(err));\ @@ -35,15 +37,19 @@ @implementation Replay static SInt16* bufLeft; static SInt16* bufRight; ++ (NSArray*)supportedFormats { + NSMutableArray* formats = [[NSMutableArray alloc] init]; + [formats addObjectsFromArray:[MPTReplayer supportedFormats]]; + [formats addObjectsFromArray:[HVLReplayer supportedFormats]]; + [formats addObjectsFromArray:[UADEReplayer supportedFormats]]; + return formats; +} + -(id)init { self=[super init]; if (self) { - //Map AHX and HVL to HVLReplayer, everything else plays with OpenMPT - self.replayerMap = @{@"AHX": [HVLReplayer class], - @"HVL": [HVLReplayer class], - @"THX": [HVLReplayer class] - }; + self.replayers = @[[MPTReplayer class], [HVLReplayer class], [UADEReplayer class]]; } return self; } @@ -126,15 +132,23 @@ - (bool) loadModule:(NSString *)path type:(NSString*)type type = [[path pathExtension] uppercaseString]; } Class replayerClass; - if ([self.replayerMap.allKeys containsObject:type]) { - replayerClass = [self.replayerMap objectForKey:type]; - } else { - replayerClass = [MPTReplayer class]; +// if ([self.replayerMap.allKeys containsObject:type]) { +// replayerClass = [self.replayerMap objectForKey:type]; +// } else { +// replayerClass = [MPTReplayer class]; +// } + for (int i=0; i< self.replayers.count; i++) { + if ([[self.replayers[i] supportedFormats] containsObject:(type)]) { + replayerClass = self.replayers[i]; + } } if (renderer) { [self pause]; } if (![[renderer class] isEqual:replayerClass]) { + if(renderer) { + [renderer cleanup]; + } renderer = [[replayerClass alloc] init]; } return [renderer loadModule:path type:type]; @@ -238,6 +252,11 @@ - (void) setInterpolationFilterLength:(NSInteger)value { } } +- (void)cleanup { + //noop, done in loadModule for the replayer +} + + -(void)dealloc { diff --git a/4champ/Replay/UADE/UADEReplayer.h b/4champ/Replay/UADE/UADEReplayer.h new file mode 100644 index 0000000..63f8a97 --- /dev/null +++ b/4champ/Replay/UADE/UADEReplayer.h @@ -0,0 +1,15 @@ +// +// UADEReplayer.h +// SamplePlayer +// +// Created by Aleksi Sitomaniemi on 27.8.2022. +// Copyright © 2022 4champ. All rights reserved. +// + +#import +#import +#import "Replay.h" + +@interface UADEReplayer : NSObject + +@end diff --git a/4champ/Replay/UADE/UADEReplayer.m b/4champ/Replay/UADE/UADEReplayer.m new file mode 100644 index 0000000..9f41151 --- /dev/null +++ b/4champ/Replay/UADE/UADEReplayer.m @@ -0,0 +1,372 @@ +// +// UADEReplayer.m +// SamplePlayer +// +// Created by Aleksi Sitomaniemi on 27.8.2022. +// Copyright © 2022 4champ. All rights reserved. +// + +#import "UADEReplayer.h" + +static volatile int uadethread_running; + +#include +#include +#include +#include +#include +#include "uae.h" + +int uadeconf_loaded; +char uadeconfname[256]; +enum uade_control_state ctrlstate = UADE_S_STATE; + +int new_subsong = -1; +#define MAX_LEN 256 +char current_format[80] = ""; + +@implementation UADEReplayer{ + struct uade_config* cfg; + struct uade_state* ustate; + + int16_t* leftByte; + int16_t* rightByte; + char uadescorename[PATH_MAX]; + char basedir[PATH_MAX]; + struct uade_file* playername; + int fds[2]; + } + ++ (NSArray*)supportedFormats { + return @[@"AAM", // ArtAndMagic, + @"ABK", // Amos ABK + @"ADPCM",// ADPCM_mono + @"ADSC", // AudioSculpture + //@"AHX" // -> HivelyPlayer + @"AMC", // A.M. Composer + @"AON", @"AON4", @"AON8", // Art of noise + @"APS", // AProSys + @"ASH", // Ashley Hogg + @"AST", // ActionAmics + @"BD", @"BDS", // Ben Daglish + @"BFC", @"BSI", // Future Composer (BSI) + @"BSS", // BeathovenSynthesizer + @"BP", @"BP3", // SoundMon + @"BYE", // Andrew Parton + @"CIN", // Chinemaware + @"CORE",// Core Design + @"DB",@"DIGI", // DigiBooster + @"DH", // David Hanney + @"DL",@"DL_DELI",@"DLN", // Dave Lowe + @"DM1", @"DM2", @"DLM1", @"DLM2", // Delta Music + @"DMU", @"DMU2", @"MUG", @"MUG2", // Mugician + //@"DIGI" OpenMPT + @"DNS", // DynamicSynthesizer + @"DSC", // DigitalSonixChrome + @"DSS", // DigitalSoundStudio + @"DSR", // Desire + @"DUM", // Infogrames + @"DW", // David Whittaker + @"DZ", // DariusZendeh + @"EA", @"MG", // EarAche + @"EMOD", @"QC", // Quadra Composer + @"EMS", @"EMSV6", // EMS + @"EX", // FashionTracker + @"FC", @"FC13", @"FC14", @"FC3", @"FC4", // Future Composer + @"FC-M",// FC-M Packer + @"FP", // Future Player + @"FRED",// Fred + @"FUZZ",// Fuzzac Packer + @"GLUE", @"GM",// GlueMon + @"GRAY",// Fred Gray + @"GMC", // GMC + @"HD", // Howie Davies + @"HIP", @"SOG", @"MCMD", // Jochen Hippel + @"HIP7", @"S7G", // Jochen Hippel 7V + @"HST", // Jochen Hippel ST + @"HOT", // Anders Øland + @"IMS", // ImageMusicSystem + @"IS", // In Stereo + @"IS20",// In Stereo 2 + @"JAM", @"JC", // JamCracker + @"JCB", @"JCBO", // Jason Brooke + @"JD", @"DODA", //Special FX + @"JO", // Jesper Olsen + @"JP", @"JPN", @"JPND", // Jason Page + @"JPO", @"JPOLD", // Steve Turner + @"JMF", // Janko Mrsic-Flogel + @"JT", @"MON_OLD", // Jeroen Tel + @"KH", // Kris Hatlelid + @"KIM", // Kim Christensen + @"KRIS",// ChipTracker + @"LME", // LegglessMusicEditor + @"MA", // Music Assembler + @"MAX", // Maximum Effect + @"MC", @"MCR", @"MCO", // Major Coooksey + @"MCMD", + @"MD", // Mike Davies + @"MMDC", + @"MM4", @"MM8", // Music Maker + @"MMS", @"SFX20", // MultiMedia Sound + @"MED", @"MMD0", @"MMD1", @"MMD2", @"OCTAMED", // Octamed + @"MK2", @"MKII", // MarkII + @"MXTX",// Maxtrax + @"MCMD",// MCMD + @"MIDI",// MIDI-loriciel + @"ML", // MusicLine Editor + @"MOK", // Silmarilis + @"MON", // ManiacsOfNoise + @"MSO", // Medley + @"MTP2", @"HN", @"THN", // Major Tom's Player + @"MW", @"AVP", // Martin Walker + @"NTP", // NovoTrade Packer + @"OKT", // Oktalyzer + @"ONE", // OnEscapee + @"OSP", // Synth Pack + @"PAT", // Paul Tonge + @"PAP", // Pierre Adane + @"PM20",// Promizer + @"PM40",// Promizer + @"PN", // Pokey Noise + @"POWT", @"PT", // Laxity + @"PRU1",// ProRunner + @"PRU2",// ProRunner + @"PS", // Paul Shields + @"PSA", // ProfessionalSoundArtists + @"PSF", // SoundFactory + @"PUMA",// PumaTracker + @"PVP", // PeterVerswyvelen + @"RIFF",// Riff Raff + @"RJ", @"RJP", // Richard Joseph + @"RH", @"RHO", // Rob Hubbard + @"SC", @"SCT", // Sound Control + @"SCN", @"S-C", // Sean Connolly + @"SA", @"SONIC", // Sonic Arranger + @"SB", // SteveBarrett + @"SAS", // SpeedyA1System + @"SCR", // Sean Conran + @"SDR", // Synthdream + @"SFX", @"SFX13", // Sound-FX + @"SID1", @"SID2", @"SMN", // SidMon 1,2 + @"SJS", // SoundPlayer + @"SM", @"SM1", @"SM2", @"SM3", @"SMPRO", // SoundMaster + @"SNK", // Paul Summers + @"SNG", // ZoundMonitor + @"SNX", @"SMUS", @"TINY", // Sonix Music Driver + @"SPL", // Sound Programming Language + @"SS", // SpeedySystem + @"ST", @"SYNMOD", // SynTracker + @"SUN", // SunTronic + @"SYN", // Synth + @"SYNMOD", // Syntracker + @"TCB", // TCB Tracker + @"THM", // Thomas Hermann + @"TMK", // Time Tracker + @"TF", // Tim Follin + @"TMFX", @"TMFX1.5", @"TFHD1.5", @"TMFX7V", @"TFHD7V", @"TMFXPRO", @"MDST", @"MDAT",// TFMX + @"TME", // TheMusicalEnlightement + @"TPU", // Dirk Bialluch + @"TRC", @"TRO", @"DP", @"TRONIC", // Tronic + @"TWO", // NTSP-System + @"TW", // SoundImages + @"UFO", @"MUS", // UFO + @"VSS", // Voodoo Supreme Synthesizer + @"WB", // Wally Beben + @"YM", // YM-2149, + @"QPA", @"SQT", @"QTS", // Quartet - PSG - ST + ]; +} + +// Handle main UADE thread (amiga emu) +-(void) uadeThread:(NSArray*)params { + uadethread_running = 1; + NSLog(@"UADECore enter"); + @autoreleasepool { + const char* inParam = [[params objectAtIndex:0] UTF8String]; + const char* outParam = [[params objectAtIndex:1] UTF8String]; + + [[NSThread currentThread] setThreadPriority:0.9f]; + const char *argv[5] = {"uadecore", "-i", inParam, "-o", outParam}; + uadecore_main(5,(char**)argv); + } + NSLog(@"UADECore exit"); + uadethread_running=0; +} + +- (UADEReplayer*) init { + self = [super init]; + if (self) { + // get basedir from bundle + NSString *bd = [[NSBundle mainBundle] pathForResource:@"UADERes" ofType:@"bundle"]; + strcpy(basedir, [bd UTF8String]); + + struct uade_config *cfg = uade_new_config(); + sprintf(uadescorename, "%s/score",basedir); + uade_config_set_option(cfg, UC_VERBOSE, [@"1" UTF8String]); + uade_config_set_option(cfg, UC_BASE_DIR, basedir); + uade_config_set_option(cfg, UC_SCORE_FILE, uadescorename); + ustate = [self create_state:cfg]; + free(cfg); + + } + return self; +} + +- (void)dealloc { + NSLog(@"UADEReplayer deallocated"); +} + +- (void) cleanup { + uae_quit(); + uade_stop(ustate); + uade_cleanup_state(ustate); + while(uadethread_running) { + } + quit_program = 0; + close(fds[0]); + close(fds[1]); +} + + +/// Create UADE state. Implementation is identical with `uade_new_state` provided by libuade, +/// with the exception that uadecore is spawned in a thread, not a separate process. +/// @param extraconfig any client-specific configuration +- (struct uade_state*) create_state:(struct uade_config*)extraconfig { + + struct uade_state *state; + char path[PATH_MAX]; + const char *basedir; + + state = calloc(1, sizeof *state); + if (!state) + return NULL; + + basedir = NULL; + if (extraconfig != NULL && extraconfig->basedir_set) + basedir = extraconfig->basedir.name; + + if (!uade_load_initial_config(state, basedir)) + NSLog(@"uadeconfig not loaded"); + + if (extraconfig) + state->extraconfig = *extraconfig; + else + uade_config_set_defaults(&state->extraconfig); + + state->config = state->permconfig; + uade_merge_configs(&state->config, &state->extraconfig); + + uade_load_initial_song_conf(state); +// load_content_db(state); + + snprintf(path, sizeof path, "%s/uadecore", state->config.basedir.name); + uade_config_set_option(&state->config, UC_UADECORE_FILE, + path); + + snprintf(path, sizeof path, "%s/uaerc", state->config.basedir.name); + uade_config_set_option(&state->config, UC_UAE_CONFIG_FILE, path); + + uade_merge_configs(&state->config, &state->extraconfig); + + if (access(state->config.uae_config_file.name, R_OK)) { + NSLog(@"Could not read uae config file: %s\n", + state->config.uae_config_file.name); + uade_cleanup_state(state); + return NULL; + } + + // set up ipc + if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds)) { + NSLog(@"Cannot create socket pair"); + return nil; + }; + + NSArray* params = @[[NSString stringWithFormat:@"%d", fds[0]], [NSString stringWithFormat:@"%d", fds[0]]]; + [NSThread detachNewThreadSelector:@selector(uadeThread:) toTarget:self withObject:params]; + + uade_set_peer(&state->ipc, 1, fds[1], fds[1]); + + if (uade_send_string(UADE_COMMAND_CONFIG, state->config.uae_config_file.name, &state->ipc)) { + NSLog(@"Can not send config name: %s\n", strerror(errno)); + uade_cleanup_state(state); + return NULL; + } + return state; + +} + +- (bool)loadModule:(NSString *)path type:(NSString *)type { + + NSData* data = [[NSFileManager defaultManager] contentsAtPath:path]; + if (!data) return false; + + uade_stop(ustate); + if (!uade_is_our_file_from_buffer([path UTF8String], data.bytes, data.length, ustate)) { + NSLog(@"Not our file"); + return false; + } +// uade_play([path UTF8String], 0, ustate); +// const char *fname, const void *buf, size_t size, +// int subsong, struct uade_state *state + NSString* nameOnly = [[path componentsSeparatedByString:@"/"] lastObject]; + uade_play_from_buffer([path UTF8String], data.bytes, data.length, 0, ustate); + + return true; +} + +- (void)setCurrentPosition:(int)newPosition { +} + +- (void)setInterpolationFilterLength:(NSInteger)value { +} + +- (void)setStereoSeparation:(NSInteger)value { + float newValue = (float)value/100.0*2.0; // (parameter range 0-100, uade range 0-2) + uade_effect_pan_set_amount(ustate, newValue); +} + +- (int)currentPosition { + const struct uade_song_info *info = uade_get_song_info(ustate); + + return 0; +} + +- (NSArray *)getInstruments { + return @[]; +} + +- (NSArray *)getSamples { + return @[]; +} + +- (int)moduleLength { + if(ustate) { + return ustate->song.info.duration; + } + return 0; +} + +- (NSInteger)numberOfChannels { + return 4; +} + +- (NSInteger)volumeOnChannel:(NSInteger)channel { + return 1; +} + +- (int)readFrames:(size_t)count bufLeft:(int16_t *)bufLeft bufRight:(int16_t *)bufRight { + int16_t buf[count*2]; + ssize_t retVal = uade_read(&buf, sizeof buf, ustate); + + if(retVal<0) { + NSLog(@"Error reading data"); + return 0; + } + for(int ptr=0; ptr<(count*2); ptr+=2) { + *bufLeft++ = buf[ptr]; + *bufRight++ = buf[ptr+1]; + } + return (int)retVal; +} + +@end diff --git a/SamplePlayer/SamplePlayer.xcodeproj/project.pbxproj b/SamplePlayer/SamplePlayer.xcodeproj/project.pbxproj index 1ea890d..93ec7ea 100644 --- a/SamplePlayer/SamplePlayer.xcodeproj/project.pbxproj +++ b/SamplePlayer/SamplePlayer.xcodeproj/project.pbxproj @@ -16,9 +16,11 @@ 45D707E6208B7C52004CB16A /* HVLReplayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 45D707DA208B7C52004CB16A /* HVLReplayer.mm */; }; 45D707E7208B7C52004CB16A /* MPTReplayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 45D707DD208B7C52004CB16A /* MPTReplayer.m */; }; 45D707E8208B7C52004CB16A /* Replay.m in Sources */ = {isa = PBXBuildFile; fileRef = 45D707DF208B7C52004CB16A /* Replay.m */; }; + 735012E028EC9702003EF294 /* UADEReplayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 735012DF28EC9702003EF294 /* UADEReplayer.m */; }; 73759FCA28EB271A00535F8E /* libopenmpt.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73759FC928EB271A00535F8E /* libopenmpt.xcframework */; }; 73759FD028EB2B0A00535F8E /* Modules.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 73759FCF28EB2B0A00535F8E /* Modules.bundle */; }; 739D39B82652A0EC001EBC9E /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 739D39B72652A0EC001EBC9E /* libz.tbd */; }; + 73D4C0EF28F688E800B59CAE /* uade_ios.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73D4C0EE28F688E800B59CAE /* uade_ios.xcframework */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -38,9 +40,12 @@ 45D707DD208B7C52004CB16A /* MPTReplayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPTReplayer.m; sourceTree = ""; }; 45D707DE208B7C52004CB16A /* Replay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Replay.h; sourceTree = ""; }; 45D707DF208B7C52004CB16A /* Replay.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Replay.m; sourceTree = ""; }; + 735012DE28EC9702003EF294 /* UADEReplayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UADEReplayer.h; sourceTree = ""; }; + 735012DF28EC9702003EF294 /* UADEReplayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UADEReplayer.m; sourceTree = ""; }; 73759FC928EB271A00535F8E /* libopenmpt.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = libopenmpt.xcframework; path = ../../openmpt/libopenmpt.xcframework; sourceTree = ""; }; 73759FCF28EB2B0A00535F8E /* Modules.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Modules.bundle; sourceTree = ""; }; 739D39B72652A0EC001EBC9E /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; + 73D4C0EE28F688E800B59CAE /* uade_ios.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = uade_ios.xcframework; path = "../../uade-ios/uade_ios.xcframework"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -48,6 +53,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 73D4C0EF28F688E800B59CAE /* uade_ios.xcframework in Frameworks */, 73759FCA28EB271A00535F8E /* libopenmpt.xcframework in Frameworks */, 739D39B82652A0EC001EBC9E /* libz.tbd in Frameworks */, ); @@ -93,6 +99,7 @@ 45D707D5208B7C52004CB16A /* Replay */ = { isa = PBXGroup; children = ( + 735012DD28EC9702003EF294 /* UADE */, 45D707D6208B7C52004CB16A /* Hively */, 45D707DB208B7C52004CB16A /* OpenMPT */, 45D707DE208B7C52004CB16A /* Replay.h */, @@ -125,6 +132,7 @@ 45D707EA208B7CEA004CB16A /* Frameworks */ = { isa = PBXGroup; children = ( + 73D4C0EE28F688E800B59CAE /* uade_ios.xcframework */, 73759FC928EB271A00535F8E /* libopenmpt.xcframework */, 739D39B72652A0EC001EBC9E /* libz.tbd */, ); @@ -138,6 +146,15 @@ path = Modules; sourceTree = ""; }; + 735012DD28EC9702003EF294 /* UADE */ = { + isa = PBXGroup; + children = ( + 735012DE28EC9702003EF294 /* UADEReplayer.h */, + 735012DF28EC9702003EF294 /* UADEReplayer.m */, + ); + path = UADE; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -216,6 +233,7 @@ 45D707E8208B7C52004CB16A /* Replay.m in Sources */, 45C005B7208B7B1800126E78 /* ViewController.swift in Sources */, 45C005B5208B7B1800126E78 /* AppDelegate.swift in Sources */, + 735012E028EC9702003EF294 /* UADEReplayer.m in Sources */, 45D707E7208B7C52004CB16A /* MPTReplayer.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -358,13 +376,20 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 2G92PSCBJ9; - HEADER_SEARCH_PATHS = ../../openmpt/libopenmpt; + HEADER_SEARCH_PATHS = ( + ../../uade/src/frontends/include, + ../../openmpt/libopenmpt, + ../../uade/src/include, + ); INFOPLIST_FILE = SamplePlayer/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - LIBRARY_SEARCH_PATHS = ../../openmpt; + LIBRARY_SEARCH_PATHS = ( + ../../openmpt, + ../../uade, + ); PRODUCT_BUNDLE_IDENTIFIER = com.4champ.SamplePlayer; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -382,13 +407,20 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 2G92PSCBJ9; - HEADER_SEARCH_PATHS = ../../openmpt/libopenmpt; + HEADER_SEARCH_PATHS = ( + ../../uade/src/frontends/include, + ../../openmpt/libopenmpt, + ../../uade/src/include, + ); INFOPLIST_FILE = SamplePlayer/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - LIBRARY_SEARCH_PATHS = ../../openmpt; + LIBRARY_SEARCH_PATHS = ( + ../../openmpt, + ../../uade, + ); PRODUCT_BUNDLE_IDENTIFIER = com.4champ.SamplePlayer; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/SamplePlayer/SamplePlayer/Modules.bundle/sweet_dreams.aon b/SamplePlayer/SamplePlayer/Modules.bundle/sweet_dreams.aon new file mode 100644 index 0000000000000000000000000000000000000000..6bebd911ea37f83d2ba070bf42262bb1220dde2e GIT binary patch literal 55836 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 MPtRXGJbCi}2j Date: Wed, 26 Oct 2022 11:23:35 +0300 Subject: [PATCH 2/5] Integrated SamplePlayer app with uade library --- 4champ/Replay/UADE/UADEReplayer.m | 110 +++++++++--------- .../SamplePlayer.xcodeproj/project.pbxproj | 54 +++++---- .../AppIcon.appiconset/Contents.json | 79 +++++++------ .../SamplePlayer/Base.lproj/Main.storyboard | 7 +- .../SamplePlayer/Modules.bundle/jinx.jam | Bin 0 -> 94484 bytes .../SamplePlayer/ViewController.swift | 8 ++ 6 files changed, 141 insertions(+), 117 deletions(-) create mode 100644 SamplePlayer/SamplePlayer/Modules.bundle/jinx.jam diff --git a/4champ/Replay/UADE/UADEReplayer.m b/4champ/Replay/UADE/UADEReplayer.m index 9f41151..63dc83b 100644 --- a/4champ/Replay/UADE/UADEReplayer.m +++ b/4champ/Replay/UADE/UADEReplayer.m @@ -16,14 +16,7 @@ #include #include #include "uae.h" - -int uadeconf_loaded; -char uadeconfname[256]; -enum uade_control_state ctrlstate = UADE_S_STATE; - -int new_subsong = -1; -#define MAX_LEN 256 -char current_format[80] = ""; +#include @implementation UADEReplayer{ struct uade_config* cfg; @@ -35,7 +28,7 @@ @implementation UADEReplayer{ char basedir[PATH_MAX]; struct uade_file* playername; int fds[2]; - } +} + (NSArray*)supportedFormats { return @[@"AAM", // ArtAndMagic, @@ -113,7 +106,7 @@ @implementation UADEReplayer{ @"MXTX",// Maxtrax @"MCMD",// MCMD @"MIDI",// MIDI-loriciel - @"ML", // MusicLine Editor + //@"ML",@"Ml" // MusicLine Editor - disabled since ML player does not handle file paths longer than 127 chars. @"MOK", // Silmarilis @"MON", // ManiacsOfNoise @"MSO", // Medley @@ -174,7 +167,7 @@ @implementation UADEReplayer{ @"WB", // Wally Beben @"YM", // YM-2149, @"QPA", @"SQT", @"QTS", // Quartet - PSG - ST - ]; + ]; } // Handle main UADE thread (amiga emu) @@ -182,12 +175,12 @@ -(void) uadeThread:(NSArray*)params { uadethread_running = 1; NSLog(@"UADECore enter"); @autoreleasepool { - const char* inParam = [[params objectAtIndex:0] UTF8String]; - const char* outParam = [[params objectAtIndex:1] UTF8String]; - - [[NSThread currentThread] setThreadPriority:0.9f]; - const char *argv[5] = {"uadecore", "-i", inParam, "-o", outParam}; - uadecore_main(5,(char**)argv); + const char* inParam = [[params objectAtIndex:0] UTF8String]; + const char* outParam = [[params objectAtIndex:1] UTF8String]; + + [[NSThread currentThread] setThreadPriority:0.9f]; + const char *argv[5] = {"uadecore", "-i", inParam, "-o", outParam}; + uadecore_main(5,(char**)argv); } NSLog(@"UADECore exit"); uadethread_running=0; @@ -196,8 +189,8 @@ -(void) uadeThread:(NSArray*)params { - (UADEReplayer*) init { self = [super init]; if (self) { - // get basedir from bundle - NSString *bd = [[NSBundle mainBundle] pathForResource:@"UADERes" ofType:@"bundle"]; + NSBundle* uadeBundle = [NSBundle bundleWithIdentifier: @"com.apple.xcode.dsym.libuade"]; + NSString *bd = [uadeBundle pathForResource:@"UADERes" ofType:@"bundle"]; strcpy(basedir, [bd UTF8String]); struct uade_config *cfg = uade_new_config(); @@ -207,7 +200,7 @@ - (UADEReplayer*) init { uade_config_set_option(cfg, UC_SCORE_FILE, uadescorename); ustate = [self create_state:cfg]; free(cfg); - + } return self; } @@ -227,54 +220,65 @@ - (void) cleanup { close(fds[1]); } - /// Create UADE state. Implementation is identical with `uade_new_state` provided by libuade, /// with the exception that uadecore is spawned in a thread, not a separate process. /// @param extraconfig any client-specific configuration - (struct uade_state*) create_state:(struct uade_config*)extraconfig { - struct uade_state *state; + DIR *bd; char path[PATH_MAX]; const char *basedir; - + state = calloc(1, sizeof *state); if (!state) return NULL; - + basedir = NULL; if (extraconfig != NULL && extraconfig->basedir_set) basedir = extraconfig->basedir.name; - - if (!uade_load_initial_config(state, basedir)) - NSLog(@"uadeconfig not loaded"); - - if (extraconfig) - state->extraconfig = *extraconfig; - else - uade_config_set_defaults(&state->extraconfig); - + + if (!uade_load_initial_config(state, basedir)) { + // uade_warning("uadeconfig not loaded\n"); + + if (extraconfig) { + state->extraconfig = *extraconfig; + } + else { + uade_config_set_defaults(&state->extraconfig); + } + } + state->config = state->permconfig; uade_merge_configs(&state->config, &state->extraconfig); - + uade_load_initial_song_conf(state); -// load_content_db(state); - - snprintf(path, sizeof path, "%s/uadecore", state->config.basedir.name); + //load_content_db(state); + + bd = opendir(state->config.basedir.name); + if (bd == NULL) { + NSLog(@"Could not access dir %s", state->config.basedir.name); + return nil; + } + closedir(bd); + uade_config_set_option(&state->config, UC_UADECORE_FILE, - path); + UADE_CONFIG_UADE_CORE); snprintf(path, sizeof path, "%s/uaerc", state->config.basedir.name); uade_config_set_option(&state->config, UC_UAE_CONFIG_FILE, path); - + uade_merge_configs(&state->config, &state->extraconfig); - + + /* TODO: Remove this, but make uadecore respond with a HELLO message. */ + if (access(state->config.uadecore_file.name, X_OK)) { + NSLog(@"Could not execute %s", state->config.uadecore_file.name); + return nil; + } if (access(state->config.uae_config_file.name, R_OK)) { - NSLog(@"Could not read uae config file: %s\n", - state->config.uae_config_file.name); - uade_cleanup_state(state); - return NULL; + NSLog(@"Could not read uae config file: %s", state->config.uae_config_file.name); + return nil; } - + // set up ipc if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds)) { NSLog(@"Cannot create socket pair"); @@ -285,29 +289,27 @@ - (struct uade_state*) create_state:(struct uade_config*)extraconfig { [NSThread detachNewThreadSelector:@selector(uadeThread:) toTarget:self withObject:params]; uade_set_peer(&state->ipc, 1, fds[1], fds[1]); - if (uade_send_string(UADE_COMMAND_CONFIG, state->config.uae_config_file.name, &state->ipc)) { - NSLog(@"Can not send config name: %s\n", strerror(errno)); - uade_cleanup_state(state); - return NULL; + NSLog(@"Can not send config name: %s", strerror(errno)); + return nil; } + return state; - } - (bool)loadModule:(NSString *)path type:(NSString *)type { NSData* data = [[NSFileManager defaultManager] contentsAtPath:path]; if (!data) return false; - + uade_stop(ustate); if (!uade_is_our_file_from_buffer([path UTF8String], data.bytes, data.length, ustate)) { NSLog(@"Not our file"); return false; } -// uade_play([path UTF8String], 0, ustate); -// const char *fname, const void *buf, size_t size, -// int subsong, struct uade_state *state + // uade_play([path UTF8String], 0, ustate); + // const char *fname, const void *buf, size_t size, + // int subsong, struct uade_state *state NSString* nameOnly = [[path componentsSeparatedByString:@"/"] lastObject]; uade_play_from_buffer([path UTF8String], data.bytes, data.length, 0, ustate); diff --git a/SamplePlayer/SamplePlayer.xcodeproj/project.pbxproj b/SamplePlayer/SamplePlayer.xcodeproj/project.pbxproj index 93ec7ea..b6127d7 100644 --- a/SamplePlayer/SamplePlayer.xcodeproj/project.pbxproj +++ b/SamplePlayer/SamplePlayer.xcodeproj/project.pbxproj @@ -17,12 +17,27 @@ 45D707E7208B7C52004CB16A /* MPTReplayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 45D707DD208B7C52004CB16A /* MPTReplayer.m */; }; 45D707E8208B7C52004CB16A /* Replay.m in Sources */ = {isa = PBXBuildFile; fileRef = 45D707DF208B7C52004CB16A /* Replay.m */; }; 735012E028EC9702003EF294 /* UADEReplayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 735012DF28EC9702003EF294 /* UADEReplayer.m */; }; - 73759FCA28EB271A00535F8E /* libopenmpt.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73759FC928EB271A00535F8E /* libopenmpt.xcframework */; }; + 73759FCA28EB271A00535F8E /* libopenmpt.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73759FC928EB271A00535F8E /* libopenmpt.xcframework */; settings = {ATTRIBUTES = (Required, ); }; }; 73759FD028EB2B0A00535F8E /* Modules.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 73759FCF28EB2B0A00535F8E /* Modules.bundle */; }; + 7397C1E929092561002D5CDB /* uade_ios.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73E345A6290595DA00B3C937 /* uade_ios.xcframework */; }; + 7397C1EA29092561002D5CDB /* uade_ios.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 73E345A6290595DA00B3C937 /* uade_ios.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 739D39B82652A0EC001EBC9E /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 739D39B72652A0EC001EBC9E /* libz.tbd */; }; - 73D4C0EF28F688E800B59CAE /* uade_ios.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73D4C0EE28F688E800B59CAE /* uade_ios.xcframework */; }; /* End PBXBuildFile section */ +/* Begin PBXCopyFilesBuildPhase section */ + 7397C1EB29092561002D5CDB /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 7397C1EA29092561002D5CDB /* uade_ios.xcframework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ 45C005B1208B7B1800126E78 /* SamplePlayer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SamplePlayer.app; sourceTree = BUILT_PRODUCTS_DIR; }; 45C005B4208B7B1800126E78 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -45,7 +60,7 @@ 73759FC928EB271A00535F8E /* libopenmpt.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = libopenmpt.xcframework; path = ../../openmpt/libopenmpt.xcframework; sourceTree = ""; }; 73759FCF28EB2B0A00535F8E /* Modules.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Modules.bundle; sourceTree = ""; }; 739D39B72652A0EC001EBC9E /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; - 73D4C0EE28F688E800B59CAE /* uade_ios.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = uade_ios.xcframework; path = "../../uade-ios/uade_ios.xcframework"; sourceTree = ""; }; + 73E345A6290595DA00B3C937 /* uade_ios.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = uade_ios.xcframework; path = "../../uade-ios/uade_ios.xcframework"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -53,7 +68,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 73D4C0EF28F688E800B59CAE /* uade_ios.xcframework in Frameworks */, + 7397C1E929092561002D5CDB /* uade_ios.xcframework in Frameworks */, 73759FCA28EB271A00535F8E /* libopenmpt.xcframework in Frameworks */, 739D39B82652A0EC001EBC9E /* libz.tbd in Frameworks */, ); @@ -84,7 +99,6 @@ isa = PBXGroup; children = ( 73759FCF28EB2B0A00535F8E /* Modules.bundle */, - 45D707EF208B7E2A004CB16A /* Modules */, 45C005B4208B7B1800126E78 /* AppDelegate.swift */, 45C005B6208B7B1800126E78 /* ViewController.swift */, 45C005B8208B7B1800126E78 /* Main.storyboard */, @@ -132,20 +146,13 @@ 45D707EA208B7CEA004CB16A /* Frameworks */ = { isa = PBXGroup; children = ( - 73D4C0EE28F688E800B59CAE /* uade_ios.xcframework */, + 73E345A6290595DA00B3C937 /* uade_ios.xcframework */, 73759FC928EB271A00535F8E /* libopenmpt.xcframework */, 739D39B72652A0EC001EBC9E /* libz.tbd */, ); name = Frameworks; sourceTree = ""; }; - 45D707EF208B7E2A004CB16A /* Modules */ = { - isa = PBXGroup; - children = ( - ); - path = Modules; - sourceTree = ""; - }; 735012DD28EC9702003EF294 /* UADE */ = { isa = PBXGroup; children = ( @@ -165,6 +172,7 @@ 45C005AD208B7B1800126E78 /* Sources */, 45C005AE208B7B1800126E78 /* Frameworks */, 45C005AF208B7B1800126E78 /* Resources */, + 7397C1EB29092561002D5CDB /* Embed Frameworks */, ); buildRules = ( ); @@ -308,7 +316,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.2; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -359,7 +367,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.2; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; @@ -377,9 +385,9 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 2G92PSCBJ9; HEADER_SEARCH_PATHS = ( - ../../uade/src/frontends/include, + "../../uade-ios/src/frontends/include", ../../openmpt/libopenmpt, - ../../uade/src/include, + "../../uade-ios/src/include", ); INFOPLIST_FILE = SamplePlayer/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -387,8 +395,8 @@ "@executable_path/Frameworks", ); LIBRARY_SEARCH_PATHS = ( - ../../openmpt, - ../../uade, + "../../openmpt/**", + "../../uade/**", ); PRODUCT_BUNDLE_IDENTIFIER = com.4champ.SamplePlayer; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -408,9 +416,9 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 2G92PSCBJ9; HEADER_SEARCH_PATHS = ( - ../../uade/src/frontends/include, + "../../uade-ios/src/frontends/include", ../../openmpt/libopenmpt, - ../../uade/src/include, + "../../uade-ios/src/include", ); INFOPLIST_FILE = SamplePlayer/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -418,8 +426,8 @@ "@executable_path/Frameworks", ); LIBRARY_SEARCH_PATHS = ( - ../../openmpt, - ../../uade, + "../../openmpt/**", + "../../uade/**", ); PRODUCT_BUNDLE_IDENTIFIER = com.4champ.SamplePlayer; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/SamplePlayer/SamplePlayer/Assets.xcassets/AppIcon.appiconset/Contents.json b/SamplePlayer/SamplePlayer/Assets.xcassets/AppIcon.appiconset/Contents.json index 1d060ed..9221b9b 100644 --- a/SamplePlayer/SamplePlayer/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/SamplePlayer/SamplePlayer/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -2,92 +2,97 @@ "images" : [ { "idiom" : "iphone", - "size" : "20x20", - "scale" : "2x" + "scale" : "2x", + "size" : "20x20" }, { "idiom" : "iphone", - "size" : "20x20", - "scale" : "3x" + "scale" : "3x", + "size" : "20x20" }, { "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" + "scale" : "2x", + "size" : "29x29" }, { "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" + "scale" : "3x", + "size" : "29x29" }, { "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" + "scale" : "2x", + "size" : "40x40" }, { "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" + "scale" : "3x", + "size" : "40x40" }, { "idiom" : "iphone", - "size" : "60x60", - "scale" : "2x" + "scale" : "2x", + "size" : "60x60" }, { "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" + "scale" : "3x", + "size" : "60x60" }, { "idiom" : "ipad", - "size" : "20x20", - "scale" : "1x" + "scale" : "1x", + "size" : "20x20" }, { "idiom" : "ipad", - "size" : "20x20", - "scale" : "2x" + "scale" : "2x", + "size" : "20x20" }, { "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" + "scale" : "1x", + "size" : "29x29" }, { "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" + "scale" : "2x", + "size" : "29x29" }, { "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" + "scale" : "1x", + "size" : "40x40" }, { "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" + "scale" : "2x", + "size" : "40x40" }, { "idiom" : "ipad", - "size" : "76x76", - "scale" : "1x" + "scale" : "1x", + "size" : "76x76" }, { "idiom" : "ipad", - "size" : "76x76", - "scale" : "2x" + "scale" : "2x", + "size" : "76x76" }, { "idiom" : "ipad", - "size" : "83.5x83.5", - "scale" : "2x" + "scale" : "2x", + "size" : "83.5x83.5" + }, + { + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +} diff --git a/SamplePlayer/SamplePlayer/Base.lproj/Main.storyboard b/SamplePlayer/SamplePlayer/Base.lproj/Main.storyboard index dafcd9e..af73ff0 100644 --- a/SamplePlayer/SamplePlayer/Base.lproj/Main.storyboard +++ b/SamplePlayer/SamplePlayer/Base.lproj/Main.storyboard @@ -34,7 +34,7 @@ - +