Skip to content

Commit

Permalink
Merge pull request #15 from sitomani/SamplePlayer-dynamicui
Browse files Browse the repository at this point in the history
Make SamplePlayer UI dynamic + integrate LibOpenMPT as framework.
  • Loading branch information
sitomani committed Oct 3, 2022
2 parents 7d8d020 + 6c76414 commit 45d80b5
Show file tree
Hide file tree
Showing 11 changed files with 134 additions and 120 deletions.
10 changes: 4 additions & 6 deletions 4champ.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@
45855FC9244467420079C767 /* DownloadView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45855FC8244467420079C767 /* DownloadView.swift */; };
45855FCB244475050079C767 /* DownloadHostingController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45855FCA244475050079C767 /* DownloadHostingController.swift */; };
45855FCD2444AC6B0079C767 /* ModuleSharing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45855FCC2444AC6B0079C767 /* ModuleSharing.swift */; };
45A4F13C257EAF81006FF21B /* liblibopenmpt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 45A4F130257EA970006FF21B /* liblibopenmpt.a */; };
45AA7AED2101BDB10096D7E7 /* ModulePlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45AA7AEC2101BDB10096D7E7 /* ModulePlayer.swift */; };
45AA90F520FF2F6600794147 /* RESTRoutes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45AA90F420FF2F6600794147 /* RESTRoutes.swift */; };
45AA910220FF36C200794147 /* Replay.m in Sources */ = {isa = PBXBuildFile; fileRef = 45AA90F720FF36C200794147 /* Replay.m */; };
Expand Down Expand Up @@ -94,6 +93,7 @@
735A273E264FDFAD004EAC0C /* Gzip in Frameworks */ = {isa = PBXBuildFile; productRef = 735A273D264FDFAD004EAC0C /* Gzip */; };
735A2742264FDFDE004EAC0C /* SwiftyBeaver in Frameworks */ = {isa = PBXBuildFile; productRef = 735A2741264FDFDE004EAC0C /* SwiftyBeaver */; };
735A2746264FE01D004EAC0C /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = 735A2745264FE01D004EAC0C /* Alamofire */; };
73759FD228EB34DF00535F8E /* libopenmpt.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73759FD128EB34DF00535F8E /* libopenmpt.xcframework */; };
739B4BF42720850200C2D69F /* RadioSessionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 739B4BF32720850200C2D69F /* RadioSessionCell.swift */; };
/* End PBXBuildFile section */

Expand Down Expand Up @@ -170,7 +170,6 @@
45855FCA244475050079C767 /* DownloadHostingController.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = DownloadHostingController.swift; sourceTree = "<group>"; tabWidth = 2; };
45855FCC2444AC6B0079C767 /* ModuleSharing.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = ModuleSharing.swift; sourceTree = "<group>"; tabWidth = 2; };
45A080E424327ED500AEA85F /* Entitlements.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Entitlements.plist; sourceTree = "<group>"; };
45A4F130257EA970006FF21B /* liblibopenmpt.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = liblibopenmpt.a; path = ../openmpt/liblibopenmpt.a; sourceTree = "<group>"; };
45AA7AEC2101BDB10096D7E7 /* ModulePlayer.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = ModulePlayer.swift; sourceTree = "<group>"; tabWidth = 2; };
45AA90F420FF2F6600794147 /* RESTRoutes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RESTRoutes.swift; sourceTree = "<group>"; };
45AA90F720FF36C200794147 /* Replay.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = Replay.m; sourceTree = "<group>"; tabWidth = 2; };
Expand All @@ -182,7 +181,6 @@
45AA90FE20FF36C200794147 /* Replay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Replay.h; sourceTree = "<group>"; };
45AA910020FF36C200794147 /* MPTReplayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPTReplayer.h; sourceTree = "<group>"; };
45AA910120FF36C200794147 /* MPTReplayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPTReplayer.m; sourceTree = "<group>"; };
45AA910920FF389800794147 /* liblibopenmpt-small.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "liblibopenmpt-small.a"; path = "../openmpt/liblibopenmpt-small.a"; sourceTree = "<group>"; };
45AA910B20FF3A3B00794147 /* 4champ-bridging-header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "4champ-bridging-header.h"; path = "4champ/4champ-bridging-header.h"; sourceTree = SOURCE_ROOT; };
45AA910D20FF5E8A00794147 /* Structs.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = Structs.swift; sourceTree = "<group>"; tabWidth = 2; };
45AA910F2100C48500794147 /* MainViewController.swift */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = "<group>"; tabWidth = 2; };
Expand All @@ -209,6 +207,7 @@
45D61F5C20E17D8F00869814 /* Alamofire.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Alamofire.framework; path = Carthage/Build/iOS/Alamofire.framework; sourceTree = "<group>"; };
45D61F6220E1863600869814 /* Gzip.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Gzip.framework; path = Carthage/Build/iOS/Gzip.framework; sourceTree = "<group>"; };
735A274D264FE9EA004EAC0C /* AmpCDModel 9 (imports).xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "AmpCDModel 9 (imports).xcdatamodel"; sourceTree = "<group>"; };
73759FD128EB34DF00535F8E /* libopenmpt.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = libopenmpt.xcframework; path = ../openmpt/libopenmpt.xcframework; sourceTree = "<group>"; };
739B4BF32720850200C2D69F /* RadioSessionCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadioSessionCell.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

Expand All @@ -217,7 +216,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
45A4F13C257EAF81006FF21B /* liblibopenmpt.a in Frameworks */,
73759FD228EB34DF00535F8E /* libopenmpt.xcframework in Frameworks */,
735A2746264FE01D004EAC0C /* Alamofire in Frameworks */,
735A273E264FDFAD004EAC0C /* Gzip in Frameworks */,
735A2742264FDFDE004EAC0C /* SwiftyBeaver in Frameworks */,
Expand Down Expand Up @@ -498,9 +497,8 @@
45D61F5E20E17D9600869814 /* Frameworks */ = {
isa = PBXGroup;
children = (
45A4F130257EA970006FF21B /* liblibopenmpt.a */,
73759FD128EB34DF00535F8E /* libopenmpt.xcframework */,
455CC0A52104A0E20094A5D3 /* SwiftyBeaver.framework */,
45AA910920FF389800794147 /* liblibopenmpt-small.a */,
45D61F6220E1863600869814 /* Gzip.framework */,
45D61F5C20E17D8F00869814 /* Alamofire.framework */,
);
Expand Down
2 changes: 1 addition & 1 deletion 4champ/Replay/Hively/HVLReplayer.mm
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ - (NSInteger) volumeOnChannel:(NSInteger)channel {
- (bool) loadModule:(NSString *)path type:(NSString*) type {
currentHVLtune = hvl_LoadTune((TEXT*)[path UTF8String], 44100, hvlStereoSeparation );
if (currentHVLtune == nil) {
return nil;
return false;
}

curpos = 0;
Expand Down
21 changes: 21 additions & 0 deletions 4champ/Scenes/MainViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,27 @@ class MainViewController: UITabBarController {
npView.heightAnchor.constraint(equalToConstant: 50.0).isActive = true
npView?.alpha = 0

let tabBarAppearance: UITabBarAppearance = UITabBarAppearance()
tabBarAppearance.configureWithDefaultBackground()
tabBarAppearance.backgroundColor = Appearance.tabColor
UITabBar.appearance().standardAppearance = tabBarAppearance

if #available(iOS 15.0, *) {
UITabBar.appearance().scrollEdgeAppearance = tabBarAppearance
}

let navBarAppearance: UINavigationBarAppearance = UINavigationBarAppearance()
navBarAppearance.configureWithDefaultBackground()
navBarAppearance.backgroundColor = Appearance.tabColor
navBarAppearance.titleTextAttributes = [.foregroundColor: Appearance.barTitleColor,
.font: UIFont.systemFont(ofSize: 16.0, weight: .heavy)]
UINavigationBar.appearance().standardAppearance = navBarAppearance

if #available(iOS 15.0, *) {
UINavigationBar.appearance().scrollEdgeAppearance = navBarAppearance
}


self.becomeFirstResponder()
modulePlayer.addPlayerObserver(self)
moduleStorage.addStorageObserver(self)
Expand Down
37 changes: 20 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# 4champ

4champ is an app that provides a mobile interface to [Amiga Music Preservation](http://amp.dascene.net) database on iOS devices.

Many of us who grew up with computers in the 80's and early 90's remember Amiga and particularly its mind-blowing audio capabilities which were unrivaled at the era. Amiga inspired a lot of musicians to
produce a vast amount of compositions, or modules as they were called. [Amiga Music Preservation](http://amp.dascene.net) is a non-profit
Many of us who grew up with computers in the 80's and early 90's remember Amiga and particularly its mind-blowing audio capabilities which were unrivaled at the era. Amiga inspired a lot of musicians to
produce a vast amount of compositions, or modules as they were called. [Amiga Music Preservation](http://amp.dascene.net) is a non-profit
project that collects anything related to Amiga music production. AMP database boasts over 160 000 modules, 4champ app is your direct access to all that goodness.

### Development journal
Expand All @@ -18,34 +19,36 @@ You can read more about the history of the app and follow the rewrite process on
You can also follow the [@4champ_app](https://twitter.com/4champ_app) Twitter account to stay up to date on what's happening with the app.

### Main Features and their current status in this repository
* Radio: You can listen to a random set of tunes from the whole collection of over 150000 modules, or stream from the head, i.e. the most recently added ones. You can also play from the local collection from set of modules that you've selected to keep for offline mode. This was implemented first in the rewrite.
* Search (search the AMP database by module, composer, group name or sampletexts): Implemented in October 2018.
* Playlists (build your own playlists): Playlists implemented in April 2020.
* Local Collection (store modules locally): Persistent storage for off-line listening of modules implemented June 2019.
* Settings (control stereo separation etc): Stereo separation setting implemented in November 2018.
* Import modules from filesystem (local / cloud / network). The first complete new feature that never existed in the old generation app. August 2021.

- Radio: You can listen to a random set of tunes from the whole collection of over 150000 modules, or stream from the head, i.e. the most recently added ones. You can also play from the local collection from set of modules that you've selected to keep for offline mode. This was implemented first in the rewrite.
- Search (search the AMP database by module, composer, group name or sampletexts): Implemented in October 2018.
- Playlists (build your own playlists): Playlists implemented in April 2020.
- Local Collection (store modules locally): Persistent storage for off-line listening of modules implemented June 2019.
- Settings (control stereo separation etc): Stereo separation setting implemented in November 2018.
- Import modules from filesystem (local / cloud / network). The first complete new feature that never existed in the old generation app. August 2021.

### Dependencies

##### A. Frameworks configured through Swift Package Manager

**[Alamofire](https://github.com/Alamofire/Alamofire)** is used for network comms.
**[GzipSwift](https://github.com/1024jp/GzipSwift)** is used to unpack the gzipped module files.
**[SwiftyBeaver](https://github.com/SwiftyBeaver/SwiftyBeaver)** is used for logging.

##### B. Module Playback Libraries

4champ uses [libOpenMPT](https://github.com/OpenMPT/openmpt) and [Hivelytracker](https://github.com/pete-gordon/hivelytracker) for module playback.
4champ uses [libOpenMPT](https://github.com/OpenMPT/openmpt) and [Hivelytracker](https://github.com/pete-gordon/hivelytracker) for module playback.

**Hivelytracker** replayer code is included in [4champ/Replay/Hively](4champ/replay/hively) folder, so it will be built automatically when you build xcode projects in this repository, no further actions needed.
**Hivelytracker** replayer code is included in [4champ/Replay/Hively](4champ/replay/hively) folder, so it will be built automatically when you build xcode projects in this repository, no further actions needed.

**LibOpenMPT** repo does not build for iOS without small tweaks, which I have done on my own fork of the lib at https://github.com/sitomani/openmpt. In order to build it for use in connection with 4champ and the SamplePlayer demo app in this repository, you will need to take the following steps:

1. Make sure you have the [GENie](https://github.com/bkaradzic/GENie) project generator tool installed to your system
2. Clone https://github.com/sitomani/openmpt at same folder where you cloned this repository at (the repositories will be subfolders in same level in the directory tree).
3. Navigate in terminal to the openmpt repository root folder
4. Execute `iOS_genproject.sh` to generate the xcode project files for libopenmpt.
5. Execute `iOS_build.sh` to build the fat lib file for iOS use (both X86_64 and ARM64 slices combined).
6. After successful build, the library file `liblibopenmpt.a` will be found under openmpt repository root, and 4champ repository projects are configured to find it there, provided that you have cloned this repository and openmpt repository in the same folder.
5. Execute `iOS_build.sh` to build the fat framework file for iOS use (supports simulators on both Intel and M1 macs and all Arm64 iOS devices)
6. After successful build, the framework file `libopenmpt.framework` will be found under openmpt repository root, and 4champ repository projects are configured to find it there, provided that you have cloned this repository and openmpt repository in the same folder.

### Building the app

Expand All @@ -59,9 +62,9 @@ The Xcode generated developer certificate will only be valid for 7 days, which m

The code in this repository is copyright © Aleksi Sitomaniemi and licensed under [MIT license](LICENSE), **except** for HivelyTracker replay routine code which is by licenced under [BSD-3](4champ/replay/hively/LICENSE) by [Pete Gordon](https://github.com/pete-gordon).

Module files included under *SamplePlayer* test project that I've used to verify the the replay routine are work of the original authors:
Module files included under _SamplePlayer_ test project that I've used to verify the the replay routine are work of the original authors:

*1st_intro.mod* by florist (Aleksi Sitomaniemi - yup that's me!)<br/>
*all.in.eightchannels.xm* by Daze (Patrick Glasby-Baldwin)<br/>
*mislead.ahx* by Pink (Manfred Linzner)<br/>
*peanuts!.hvl* by Lavaburn (Dale Whinham)<br/>
_1st_intro.mod_ by florist (Aleksi Sitomaniemi - yup that's me!)<br/>
_all.in.eightchannels.xm_ by Daze (Patrick Glasby-Baldwin)<br/>
_mislead.ahx_ by Pink (Manfred Linzner)<br/>
_peanuts!.hvl_ by Lavaburn (Dale Whinham)<br/>

0 comments on commit 45d80b5

Please sign in to comment.