adding packages

This commit is contained in:
2026-01-15 14:38:46 -08:00
parent ef86e3ab6a
commit 6869cf47e5
5253 changed files with 726695 additions and 34 deletions
+2
View File
@@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto
+30
View File
@@ -0,0 +1,30 @@
name: github pages
on:
push:
branches:
- master
jobs:
deploy:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- name: Setup Flutter
uses: subosito/flutter-action@v1
with:
channel: 'dev'
- name: Install
run: |
flutter config --enable-web
flutter pub get
- name: Build
run: cd example && flutter build web
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./example/build/web
+8
View File
@@ -0,0 +1,8 @@
.DS_Store
.dart_tool/
.packages
.pub/
pubspec.lock
build/
+10
View File
@@ -0,0 +1,10 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: ec1044a8773e31b4630bf162d9c374236ad1eaaf
channel: master
project_type: plugin
+14
View File
@@ -0,0 +1,14 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Flutter",
"request": "launch",
"type": "dart",
"program": "example/lib/main.dart"
}
]
}
+47
View File
@@ -0,0 +1,47 @@
## 1.1.0
* Null Safety
## 1.0.2
* Updating Version
## 1.0.1
* Bumping Version
* Adding Web Example
* Adding Online Demo
## 1.0.0 - 05.04.2019
* Support for Desktop (Path Only)
## 0.2.0 - 04.06.2019
* Updating Example to be desktop aware
## 0.1.1
* Added Ability to Change .sf2 File Being Played
* Updated Example
## 0.1.0
* Removed Need to Bundle .sf2 on iOS
* Added .sf2 Support for Android
* Added Ability to Cancel any note for true polyphony
* Updated Example
* Changed way SoundFont is Loaded (From Asset Folder)
## 0.0.4
* Fixing Android Bug
* Added Midi to Android
## 0.0.2
* Optional force unmute
## 0.0.1
* Added Midi for iOS.
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 Rody Davis
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+51
View File
@@ -0,0 +1,51 @@
[![Buy Me A Coffee](https://img.shields.io/badge/Donate-Buy%20Me%20A%20Coffee-yellow.svg)](https://www.buymeacoffee.com/rodydavis)
[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WSH3GVC49GNNJ)
![github pages](https://github.com/rodydavis/flutter_midi/workflows/github%20pages/badge.svg)
[![GitHub stars](https://img.shields.io/github/stars/rodydavis/flutter_midi?color=blue)](https://github.com/rodydavis/flutter_midi)
[![flutter_midi](https://img.shields.io/pub/v/flutter_midi.svg)](https://pub.dev/packages/flutter_midi)
# flutter_midi
A FLutter Plugin to Play midi on iOS and Android. This uses SoundFont (.sf2) Files.
Online Demo: https://rodydavis.github.io/flutter_midi/
## Installation
Download a any sound font file, example: `sound_font.SF2` file.
Create an /assets folder and store the .sf2 files
Update pubspec.yaml
``` ruby
assets:
- assets/sf2/Piano.SF2
- assets/sf2/SmallTimGM6mb.sf2
```
Load the sound font to prepare to play;
```dart
@override
void initState() {
load('assets/sf2/Piano.SF2');
super.initState();
}
void load(String asset) async {
FlutterMidi.unmute(); // Optionally Unmute
ByteData _byte = await rootBundle.load(asset);
FlutterMidi.prepare(sf2: _byte);
}
```
Play and Stop the Midi Notes
```dart
FlutterMidi.playMidiNote(midi: 60);
FlutterMidi.playMidiNote(midi: 60, velocity: 120);
FlutterMidi.stopMidiNote(midi: 60);
FlutterMidi.stopMidiNote(midi: 60, velocity: 120);
```
+8
View File
@@ -0,0 +1,8 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
+41
View File
@@ -0,0 +1,41 @@
group 'com.appleeducate.fluttermidi'
version '1.0-SNAPSHOT'
buildscript {
repositories {
google()
jcenter()
maven { url "https://jitpack.io" }
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
}
}
rootProject.allprojects {
repositories {
google()
jcenter()
maven { url "https://jitpack.io" }
}
}
apply plugin: 'com.android.library'
android {
compileSdkVersion 28
defaultConfig {
minSdkVersion 16
targetSdkVersion 28
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
lintOptions {
disable 'InvalidPackage'
}
}
dependencies {
implementation 'com.github.appleeducate:MidiDriver-Android-SF2:1.0'
}
+1
View File
@@ -0,0 +1 @@
org.gradle.jvmargs=-Xmx1536M
Binary file not shown.
@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
+172
View File
@@ -0,0 +1,172 @@
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"
+84
View File
@@ -0,0 +1,84 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
+1
View File
@@ -0,0 +1 @@
rootProject.name = 'flutter_midi'
@@ -0,0 +1,3 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.appleeducate.fluttermidi">
</manifest>
@@ -0,0 +1,118 @@
package com.appleeducate.fluttermidi;
import android.content.Context;
import cn.sherlock.com.sun.media.sound.SF2Soundbank;
import cn.sherlock.com.sun.media.sound.SoftSynthesizer;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry.Registrar;
import io.flutter.plugin.common.BinaryMessenger;
import java.io.File;
import java.io.IOException;
import jp.kshoji.javax.sound.midi.InvalidMidiDataException;
import jp.kshoji.javax.sound.midi.MidiUnavailableException;
import jp.kshoji.javax.sound.midi.Receiver;
import jp.kshoji.javax.sound.midi.ShortMessage;
/** FlutterMidiPlugin */
public class FlutterMidiPlugin implements MethodCallHandler, FlutterPlugin {
private SoftSynthesizer synth;
private Receiver recv;
private MethodChannel methodChannel;
private Context applicationContext;
/** Plugin registration. */
@SuppressWarnings("deprecation")
public static void registerWith(Registrar registrar) {
final FlutterMidiPlugin instance = new FlutterMidiPlugin();
instance.onAttachedToEngine(registrar.context(), registrar.messenger());
}
@Override
public void onAttachedToEngine(FlutterPluginBinding binding) {
onAttachedToEngine(binding.getApplicationContext(), binding.getBinaryMessenger());
}
/*
"Also, note that the plugin should still contain the static registerWith() method
to remain compatible with apps that dont use the v2 Android embedding.
(See Upgrading pre 1.12 Android projects for details.) The easiest thing to
do (if possible) is move the logic from registerWith() into a private method that
both registerWith() and onAttachedToEngine() can call. Either registerWith() or
onAttachedToEngine() will be called, not both."
- https://flutter.dev/docs/development/packages-and-plugins/plugin-api-migration
*/
private void onAttachedToEngine(Context applicationContext, BinaryMessenger messenger) {
methodChannel = new MethodChannel(messenger, "flutter_midi");
methodChannel.setMethodCallHandler(new FlutterMidiPlugin());
}
@Override
public void onDetachedFromEngine(FlutterPluginBinding binding) {
applicationContext = null;
methodChannel.setMethodCallHandler(null);
methodChannel = null;
}
@Override
public void onMethodCall(MethodCall call, Result result) {
if (call.method.equals("prepare_midi")) {
try {
String _path = call.argument("path");
File _file = new File(_path);
SF2Soundbank sf = new SF2Soundbank(_file);
synth = new SoftSynthesizer();
synth.open();
synth.loadAllInstruments(sf);
synth.getChannels()[0].programChange(0);
synth.getChannels()[1].programChange(1);
recv = synth.getReceiver();
} catch (IOException e) {
e.printStackTrace();
} catch (MidiUnavailableException e) {
e.printStackTrace();
}
} else if (call.method.equals("change_sound")) {
try {
String _path = call.argument("path");
File _file = new File(_path);
SF2Soundbank sf = new SF2Soundbank(_file);
synth = new SoftSynthesizer();
synth.open();
synth.loadAllInstruments(sf);
synth.getChannels()[0].programChange(0);
synth.getChannels()[1].programChange(1);
recv = synth.getReceiver();
} catch (IOException e) {
e.printStackTrace();
} catch (MidiUnavailableException e) {
e.printStackTrace();
}
} else if (call.method.equals("play_midi_note")) {
int _note = call.argument("note");
int _velocity = call.argument("velocity");
try {
ShortMessage msg = new ShortMessage();
msg.setMessage(ShortMessage.NOTE_ON, 0, _note, _velocity);
recv.send(msg, -1);
} catch (InvalidMidiDataException e) {
e.printStackTrace();
}
} else if (call.method.equals("stop_midi_note")) {
int _note = call.argument("note");
int _velocity = call.argument("velocity");
try {
ShortMessage msg = new ShortMessage();
msg.setMessage(ShortMessage.NOTE_OFF, 0, _note, _velocity);
recv.send(msg, -1);
} catch (InvalidMidiDataException e) {
e.printStackTrace();
}
} else {
}
}
}
@@ -0,0 +1,46 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/
# Web related
lib/generated_plugin_registrant.dart
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Android Studio will place build artifacts here
/android/app/debug
/android/app/profile
/android/app/release
+10
View File
@@ -0,0 +1,10 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: 77512a3c46ec447cc64bac959e3043c2f0bdd446
channel: master
project_type: app
+16
View File
@@ -0,0 +1,16 @@
# flutter_midi_example
Demonstrates how to use the flutter_midi plugin.
## Getting Started
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://flutter.io/docs/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://flutter.io/docs/cookbook)
For help getting started with Flutter, view our
[online documentation](https://flutter.io/docs), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
+7
View File
@@ -0,0 +1,7 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
@@ -0,0 +1,67 @@
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 28
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
lintOptions {
disable 'InvalidPackage'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.example.example"
minSdkVersion 16
targetSdkVersion 28
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
}
flutter {
source '../..'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}
@@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.example">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
@@ -0,0 +1,30 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.example">
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<application
android:name="io.flutter.app.FlutterApplication"
android:label="example"
android:icon="@mipmap/ic_launcher">
<activity
android:name="io.flutter.embedding.android.FlutterActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>
Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
</resources>
@@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.example">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
+31
View File
@@ -0,0 +1,31 @@
buildscript {
ext.kotlin_version = '1.3.50'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
jcenter()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}
@@ -0,0 +1,4 @@
org.gradle.jvmargs=-Xmx1536M
android.enableR8=true
android.useAndroidX=true
android.enableJetifier=true
@@ -0,0 +1,6 @@
#Fri Jun 23 08:50:38 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
+15
View File
@@ -0,0 +1,15 @@
include ':app'
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
}
plugins.each { name, path ->
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
include ":$name"
project(":$name").projectDir = pluginDirectory
}
+33
View File
@@ -0,0 +1,33 @@
*.mode1v3
*.mode2v3
*.moved-aside
*.pbxuser
*.perspectivev3
**/*sync/
.sconsign.dblite
.tags*
**/.vagrant/
**/DerivedData/
Icon?
**/Pods/
**/.symlinks/
profile
xcuserdata
**/.generated/
Flutter/App.framework
Flutter/Flutter.framework
Flutter/Flutter.podspec
Flutter/Generated.xcconfig
Flutter/ephemeral/
Flutter/app.flx
Flutter/app.zip
Flutter/flutter_assets/
Flutter/flutter_export_environment.sh
ServiceDefinitions.json
Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules.
!default.mode1v3
!default.mode2v3
!default.pbxuser
!default.perspectivev3
@@ -0,0 +1,26 @@
<?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>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>8.0</string>
</dict>
</plist>
@@ -0,0 +1,2 @@
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"
@@ -0,0 +1,2 @@
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"
+41
View File
@@ -0,0 +1,41 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '9.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_ios_podfile_setup
target 'Runner' do
use_frameworks!
use_modular_headers!
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
end
end
+28
View File
@@ -0,0 +1,28 @@
PODS:
- Flutter (1.0.0)
- flutter_midi (0.0.1):
- Flutter
- path_provider (0.0.1):
- Flutter
DEPENDENCIES:
- Flutter (from `Flutter`)
- flutter_midi (from `.symlinks/plugins/flutter_midi/ios`)
- path_provider (from `.symlinks/plugins/path_provider/ios`)
EXTERNAL SOURCES:
Flutter:
:path: Flutter
flutter_midi:
:path: ".symlinks/plugins/flutter_midi/ios"
path_provider:
:path: ".symlinks/plugins/path_provider/ios"
SPEC CHECKSUMS:
Flutter: 434fef37c0980e73bb6479ef766c45957d4b510c
flutter_midi: 4fe7280cf156c668fe92445f384b1bc440473cdb
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
COCOAPODS: 1.10.1
@@ -0,0 +1,574 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
8A223C5FBD986B4897047BE9 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C4129DF1B02405D977FDC10 /* Pods_Runner.framework */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
1EF6E390822A969C1BAF1720 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
2CF6BF108CE97D3FF0E4074B /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
3C4129DF1B02405D977FDC10 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
BB1303FE7A4C9273741A7E58 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
8A223C5FBD986B4897047BE9 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
3D90B1142E53436247B8920F /* Frameworks */ = {
isa = PBXGroup;
children = (
3C4129DF1B02405D977FDC10 /* Pods_Runner.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
6FCF25D4796CC565F56692C5 /* Pods */ = {
isa = PBXGroup;
children = (
BB1303FE7A4C9273741A7E58 /* Pods-Runner.debug.xcconfig */,
1EF6E390822A969C1BAF1720 /* Pods-Runner.release.xcconfig */,
2CF6BF108CE97D3FF0E4074B /* Pods-Runner.profile.xcconfig */,
);
name = Pods;
path = Pods;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
);
name = Flutter;
sourceTree = "<group>";
};
97C146E51CF9000F007C117D = {
isa = PBXGroup;
children = (
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
6FCF25D4796CC565F56692C5 /* Pods */,
3D90B1142E53436247B8920F /* Frameworks */,
);
sourceTree = "<group>";
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
);
name = Products;
sourceTree = "<group>";
};
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
97C147021CF9000F007C117D /* Info.plist */,
97C146F11CF9000F007C117D /* Supporting Files */,
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
);
path = Runner;
sourceTree = "<group>";
};
97C146F11CF9000F007C117D /* Supporting Files */ = {
isa = PBXGroup;
children = (
);
name = "Supporting Files";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
97C146ED1CF9000F007C117D /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
5B0119F1E58B7269472310B0 /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
889DE4B16C1F671D4DDCC694 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = Runner;
productName = Runner;
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1020;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
LastSwiftMigration = 1100;
};
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 97C146E51CF9000F007C117D;
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
97C146ED1CF9000F007C117D /* Runner */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
97C146EC1CF9000F007C117D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Thin Binary";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
};
5B0119F1E58B7269472310B0 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
889DE4B16C1F671D4DDCC694 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/flutter_midi/flutter_midi.framework",
"${BUILT_PRODUCTS_DIR}/path_provider/path_provider.framework",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_midi.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/path_provider.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
97C146EA1CF9000F007C117D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C146FB1CF9000F007C117D /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C147001CF9000F007C117D /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
249021D3217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Profile;
};
249021D4217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Profile;
};
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
97C147061CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
};
97C147071CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.example;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147031CF9000F007C117D /* Debug */,
97C147041CF9000F007C117D /* Release */,
249021D3217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147061CF9000F007C117D /* Debug */,
97C147071CF9000F007C117D /* Release */,
249021D4217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>
@@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1020"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>
@@ -0,0 +1,8 @@
<?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>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
@@ -0,0 +1,13 @@
import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
@@ -0,0 +1,122 @@
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@3x.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "Icon-App-1024x1024@1x.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 564 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

@@ -0,0 +1,23 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "LaunchImage.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

@@ -0,0 +1,5 @@
# Launch Screen Assets
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<image name="LaunchImage" width="168" height="185"/>
</resources>
</document>
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--Flutter View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>
+45
View File
@@ -0,0 +1,45 @@
<?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>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>example</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>
</plist>
@@ -0,0 +1 @@
#import "GeneratedPluginRegistrant.h"
@@ -0,0 +1,88 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_midi/flutter_midi.dart';
import 'package:flutter/foundation.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final _flutterMidi = FlutterMidi();
@override
void initState() {
if (!kIsWeb) {
load(_value);
} else {
_flutterMidi.prepare(sf2: null);
}
super.initState();
}
void load(String asset) async {
print('Loading File...');
_flutterMidi.unmute();
ByteData _byte = await rootBundle.load(asset);
//assets/sf2/SmallTimGM6mb.sf2
//assets/sf2/Piano.SF2
_flutterMidi.prepare(sf2: _byte, name: _value.replaceAll('assets/', ''));
}
String _value = 'assets/Piano.sf2';
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
// DropdownButton<String>(
// value: _value,
// items: [
// DropdownMenuItem(
// child: Text("Soft Piano"),
// value: "assets/sf2/SmallTimGM6mb.sf2",
// ),
// DropdownMenuItem(
// child: Text("Loud Piano"),
// value: "assets/sf2/Piano.SF2",
// ),
// ],
// onChanged: (String value) {
// setState(() {
// _value = value;
// });
// load(_value);
// },
// ),
ElevatedButton(
child: Text('Play C'),
onPressed: () {
_play(60);
},
),
],
)),
),
);
}
void _play(int midi) {
if (kIsWeb) {
// WebMidi.play(midi);
} else {
_flutterMidi.playMidiNote(midi: midi);
}
}
}
@@ -0,0 +1,22 @@
name: flutter_midi_example
description: Demonstrates how to use the flutter_midi plugin.
publish_to: 'none'
environment:
sdk: ">=2.12.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
dev_dependencies:
flutter_test:
sdk: flutter
flutter_midi:
path: ..
flutter:
uses-material-design: true
assets:
- assets/
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

+43
View File
@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta content="IE=Edge" http-equiv="X-UA-Compatible" />
<meta name="description" content="A new Flutter project." />
<!-- iOS meta tags & icons -->
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-status-bar-style" content="black" />
<meta name="apple-mobile-web-app-title" content="example" />
<link rel="apple-touch-icon" href="/icons/Icon-192.png" />
<title>example</title>
<link rel="manifest" href="/manifest.json" />
</head>
<body>
<button id="temp">Play</button>
<script src="main.dart.js" type="application/javascript"></script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/tone/14.7.39/Tone.js"
type="application/javascript"
></script>
<script>
const synth = new Tone.PolySynth().toDestination();
document.body.addEventListener("click", () => {
// const note = "C4";
// playNote(note);
// setTimeout(() => stopNote(note), 1000);
Tone.context.resume();
});
function playNote(note, duration) {
Tone.context.resume();
synth.triggerAttack(note, duration ?? Tone.context.currentTime);
}
function stopNote(note) {
Tone.context.resume();
synth.triggerRelease(note, Tone.context.currentTime);
}
</script>
</body>
</html>
+23
View File
@@ -0,0 +1,23 @@
{
"name": "example",
"short_name": "example",
"start_url": ".",
"display": "minimal-ui",
"background_color": "#0175C2",
"theme_color": "#0175C2",
"description": "A new Flutter project.",
"orientation": "portrait-primary",
"prefer_related_applications": false,
"icons": [
{
"src": "icons/Icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "icons/Icon-512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
+36
View File
@@ -0,0 +1,36 @@
.idea/
.vagrant/
.sconsign.dblite
.svn/
.DS_Store
*.swp
profile
DerivedData/
build/
GeneratedPluginRegistrant.h
GeneratedPluginRegistrant.m
.generated/
*.pbxuser
*.mode1v3
*.mode2v3
*.perspectivev3
!default.pbxuser
!default.mode1v3
!default.mode2v3
!default.perspectivev3
xcuserdata
*.moved-aside
*.pyc
*sync/
Icon?
.tags*
/Flutter/Generated.xcconfig
View File
@@ -0,0 +1,471 @@
//
// AudioUnitMIDISynth.swift
// MIDISynth
//
// Created by Gene De Lisa on 2/6/16.
// Copyright © 2016 Gene De Lisa. All rights reserved.
//
import Foundation
import AudioToolbox
import CoreAudio
// swiftlint:disable function_body_length
// swiftlint:disable type_body_length
// swiftlint:disable file_length
// swiftlint:disable line_length
/// # A Core Audio MIDISynth `AudioUnit` example.
/// This will add a polyphonic `kAudioUnitSubType_MIDISynth` audio unit to the `AUGraph`.
///
/// - author: Gene De Lisa
/// - copyright: 2016 Gene De Lisa
/// - date: February 2016
class AudioUnitMIDISynth: NSObject {
var processingGraph: AUGraph?
var midisynthNode = AUNode()
var ioNode = AUNode()
var midisynthUnit: AudioUnit?
var ioUnit: AudioUnit?
var musicSequence: MusicSequence!
var musicPlayer: MusicPlayer!
let patch1 = UInt32(46)
let patch2 = UInt32(0)
var pitch = UInt32(60)
var bankUrl: URL!
init(soundfont: URL) {
super.init()
prepare(soundfont:soundfont)
}
func prepare(soundfont: URL) {
bankUrl = soundfont;
augraphSetup()
loadMIDISynthSoundFont()
initializeGraph()
self.musicSequence = createMusicSequence()
musicPlayer = createPlayer(musicSequence)
loadPatches()
startGraph()
}
/// Create the `AUGraph`, the nodes and units, then wire them together.
func augraphSetup() {
var status = OSStatus(noErr)
status = NewAUGraph(&processingGraph)
AudioUtils.CheckError(status)
createIONode()
createSynthNode()
// now do the wiring. The graph needs to be open before you call AUGraphNodeInfo
status = AUGraphOpen(self.processingGraph!)
AudioUtils.CheckError(status)
status = AUGraphNodeInfo(self.processingGraph!, self.midisynthNode, nil, &midisynthUnit)
AudioUtils.CheckError(status)
status = AUGraphNodeInfo(self.processingGraph!, self.ioNode, nil, &ioUnit)
AudioUtils.CheckError(status)
let synthOutputElement: AudioUnitElement = 0
let ioUnitInputElement: AudioUnitElement = 0
status = AUGraphConnectNodeInput(self.processingGraph!,
self.midisynthNode, synthOutputElement, // srcnode, SourceOutputNumber
self.ioNode, ioUnitInputElement) // destnode, DestInputNumber
AudioUtils.CheckError(status)
}
/// Create the Output Node and add it to the `AUGraph`.
func createIONode() {
var cd = AudioComponentDescription(
componentType: OSType(kAudioUnitType_Output),
componentSubType: OSType(kAudioUnitSubType_RemoteIO),
componentManufacturer: OSType(kAudioUnitManufacturer_Apple),
componentFlags: 0, componentFlagsMask: 0)
let status = AUGraphAddNode(self.processingGraph!, &cd, &ioNode)
AudioUtils.CheckError(status)
}
/// Create the Synth Node and add it to the `AUGraph`.
func createSynthNode() {
var cd = AudioComponentDescription(
componentType: OSType(kAudioUnitType_MusicDevice),
componentSubType: OSType(kAudioUnitSubType_MIDISynth),
componentManufacturer: OSType(kAudioUnitManufacturer_Apple),
componentFlags: 0, componentFlagsMask: 0)
let status = AUGraphAddNode(self.processingGraph!, &cd, &midisynthNode)
AudioUtils.CheckError(status)
}
/// This will load the default sound font and set the synth unit's property.
/// - postcondition: `self.midisynthUnit` will have it's sound font url set.
func loadMIDISynthSoundFont() {
if var bankURL = bankUrl {
let status = AudioUnitSetProperty(
self.midisynthUnit!,
AudioUnitPropertyID(kMusicDeviceProperty_SoundBankURL),
AudioUnitScope(kAudioUnitScope_Global),
0,
&bankURL,
UInt32(MemoryLayout<URL>.size))
AudioUtils.CheckError(status)
print("loaded sound font")
} else {
print("Could not load sound font")
}
}
/// Pre-load the patches you will use.
///
/// Turn on `kAUMIDISynthProperty_EnablePreload` so the midisynth will load the patch data from the file into memory.
/// You load the patches first before playing a sequence or sending messages.
/// Then you turn `kAUMIDISynthProperty_EnablePreload` off. It is now in a state where it will respond to MIDI program
/// change messages and switch to the already cached instrument data.
///
/// - precondition: the graph must be initialized
///
/// [Doug's post](http://prod.lists.apple.com/archives/coreaudio-api/2016/Jan/msg00018.html)
func loadPatches() {
if !isGraphInitialized() {
fatalError("initialize graph first")
}
let channel = UInt32(0)
var enabled = UInt32(1)
var status = AudioUnitSetProperty(
self.midisynthUnit!,
AudioUnitPropertyID(kAUMIDISynthProperty_EnablePreload),
AudioUnitScope(kAudioUnitScope_Global),
0,
&enabled,
UInt32(MemoryLayout<UInt32>.size))
AudioUtils.CheckError(status)
// let bankSelectCommand = UInt32(0xB0 | 0)
// status = MusicDeviceMIDIEvent(self.midisynthUnit, bankSelectCommand, 0, 0, 0)
let pcCommand = UInt32(0xC0 | channel)
status = MusicDeviceMIDIEvent(self.midisynthUnit!, pcCommand, patch1, 0, 0)
AudioUtils.CheckError(status)
status = MusicDeviceMIDIEvent(self.midisynthUnit!, pcCommand, patch2, 0, 0)
AudioUtils.CheckError(status)
enabled = UInt32(0)
status = AudioUnitSetProperty(
self.midisynthUnit!,
AudioUnitPropertyID(kAUMIDISynthProperty_EnablePreload),
AudioUnitScope(kAudioUnitScope_Global),
0,
&enabled,
UInt32(MemoryLayout<UInt32>.size))
AudioUtils.CheckError(status)
// at this point the patches are loaded. You still have to send a program change at "play time" for the synth
// to switch to that patch
}
/// Check to see if the `AUGraph` is Initialized.
///
/// - returns: `true` if it's running, `false` if not
/// - seealso: [AUGraphIsInitialized](/https://developer.apple.com/library/prerelease/ios/documentation/AudioToolbox/Reference/AUGraphServicesReference/index.html#//apple_ref/c/func/AUGraphIsInitialized)
func isGraphInitialized() -> Bool {
var outIsInitialized = DarwinBoolean(false)
let status = AUGraphIsInitialized(self.processingGraph!, &outIsInitialized)
AudioUtils.CheckError(status)
return outIsInitialized.boolValue
}
/// Initializes the `AUGraph.
func initializeGraph() {
let status = AUGraphInitialize(self.processingGraph!)
AudioUtils.CheckError(status)
}
/// Starts the `AUGraph`
func startGraph() {
let status = AUGraphStart(self.processingGraph!)
AudioUtils.CheckError(status)
}
/// Check to see if the `AUGraph` is running.
///
/// - returns: `true` if it's running, `false` if not
func isGraphRunning() -> Bool {
var isRunning = DarwinBoolean(false)
let status = AUGraphIsRunning(self.processingGraph!, &isRunning)
AudioUtils.CheckError(status)
return isRunning.boolValue
}
/// Generate a random pitch between 36 (C below middle C) and 100.
///
/// - postcondition: self.pitch is modified
func generateRandomPitch() {
pitch = arc4random_uniform(64) + 36 // 36 - 100
}
// /// Send a note on message using patch1 on channel 0
// func playPatch1On() {
//
// let channel = UInt32(0)
// let noteCommand = UInt32(0x90 | channel)
// let pcCommand = UInt32(0xC0 | channel)
// var status = OSStatus(noErr)
//
// generateRandomPitch()
// print(pitch)
// status = MusicDeviceMIDIEvent(self.midisynthUnit!, pcCommand, patch1, 0, 0)
// AudioUtils.CheckError(status)
// status = MusicDeviceMIDIEvent(self.midisynthUnit!, noteCommand, pitch, 64, 0)
// AudioUtils.CheckError(status)
// }
//
// /// Send a note off message using patch1 on channel 0
// func playPatch1Off() {
// let channel = UInt32(0)
// let noteCommand = UInt32(0x80 | channel)
// var status = OSStatus(noErr)
// status = MusicDeviceMIDIEvent(self.midisynthUnit!, noteCommand, pitch, 0, 0)
// AudioUtils.CheckError(status)
// }
//
// /// Send a note on message using patch2 on channel 0
// func playPatch2On(midi: Int) {
//
// let channel = UInt32(0)
// let noteCommand = UInt32(0x90 | channel)
// let pcCommand = UInt32(0xC0 | channel)
// var status = OSStatus(noErr)
// pitch = UInt32(midi)
// //generateRandomPitch()
// print(pitch)
// status = MusicDeviceMIDIEvent(self.midisynthUnit!, pcCommand, patch2, 0, 0)
// AudioUtils.CheckError(status)
// status = MusicDeviceMIDIEvent(self.midisynthUnit!, noteCommand, pitch, 64, 0)
// AudioUtils.CheckError(status)
// }
//
// /// Send a note off message using patch2 on channel 0
// func playPatch2Off() {
// let channel = UInt32(0)
// let noteCommand = UInt32(0x80 | channel)
// var status = OSStatus(noErr)
// status = MusicDeviceMIDIEvent(self.midisynthUnit!, noteCommand, pitch, 0, 0)
// AudioUtils.CheckError(status)
// }
//
/// Send a note on message using patch2 on channel 0
func playPitch(midi: Int, velocity: Int) {
let channel = UInt32(0)
let noteCommand = UInt32(0x90 | channel)
let pcCommand = UInt32(0xC0 | channel)
var status = OSStatus(noErr)
status = MusicDeviceMIDIEvent(self.midisynthUnit!, pcCommand, patch2, 0, 0)
AudioUtils.CheckError(status)
status = MusicDeviceMIDIEvent(self.midisynthUnit!, noteCommand, UInt32(midi), UInt32(velocity), 0)
AudioUtils.CheckError(status)
}
/// Send a note off message using patch2 on channel 0
func stopPitch(midi: Int, velocity: Int) {
let channel = UInt32(0)
let noteCommand = UInt32(0x80 | channel)
var status = OSStatus(noErr)
status = MusicDeviceMIDIEvent(self.midisynthUnit!, noteCommand, UInt32(midi), UInt32(velocity), 0)
AudioUtils.CheckError(status)
}
/// Create a test `MusicSequence`.
///
/// - throws: Nothing, but it should
/// - todo: create an `ErrorType` ennum
/// - returns: a `MusicSequence`
func createMusicSequence() -> MusicSequence {
var musicSequence: MusicSequence?
var status = NewMusicSequence(&musicSequence)
if status != noErr {
print("\(#line) bad status \(status) creating sequence")
}
// add a track
var track: MusicTrack?
status = MusicSequenceNewTrack(musicSequence!, &track)
if status != noErr {
print("error creating track \(status)")
}
var channel = UInt8(0)
// bank select msb
var chanmess = MIDIChannelMessage(status: 0xB0 | channel, data1: 0, data2: 0, reserved: 0)
status = MusicTrackNewMIDIChannelEvent(track!, 0, &chanmess)
if status != noErr {
print("creating bank select event \(status)")
}
// bank select lsb
chanmess = MIDIChannelMessage(status: 0xB0 | channel, data1: 32, data2: 0, reserved: 0)
status = MusicTrackNewMIDIChannelEvent(track!, 0, &chanmess)
if status != noErr {
print("creating bank select event \(status)")
}
// program change. first data byte is the patch, the second data byte is unused for program change messages.
chanmess = MIDIChannelMessage(status: 0xC0 | channel, data1: UInt8(patch1), data2: 0, reserved: 0)
status = MusicTrackNewMIDIChannelEvent(track!, 0, &chanmess)
if status != noErr {
print("creating program change event \(status)")
}
// now make some notes and put them on the track
var beat = MusicTimeStamp(0.0)
for i: UInt8 in 60...72 {
var mess = MIDINoteMessage(channel: channel,
note: i,
velocity: 64,
releaseVelocity: 0,
duration: 1.0 )
status = MusicTrackNewMIDINoteEvent(track!, beat, &mess)
if status != noErr {
print("creating new midi note event \(status)")
}
beat += 1
}
// another track
channel = UInt8(1)
track = nil
status = MusicSequenceNewTrack(musicSequence!, &track)
if status != noErr {
print("error creating track \(status)")
}
chanmess = MIDIChannelMessage(status: 0xB0 | channel, data1: 0, data2: 0, reserved: 0)
status = MusicTrackNewMIDIChannelEvent(track!, 0, &chanmess)
if status != noErr {
print("creating bank select msb event \(status)")
}
chanmess = MIDIChannelMessage(status: 0xB0 | channel, data1: 32, data2: 0, reserved: 0)
status = MusicTrackNewMIDIChannelEvent(track!, 0, &chanmess)
if status != noErr {
print("creating bank select lsb event \(status)")
}
chanmess = MIDIChannelMessage(status: 0xC0 | channel, data1: UInt8(patch2), data2: 0, reserved: 0)
status = MusicTrackNewMIDIChannelEvent(track!, 0, &chanmess)
if status != noErr {
print("creating program change event \(status)")
}
beat = MusicTimeStamp(3.0)
for i: UInt8 in 60...72 {
var mess = MIDINoteMessage(channel: channel,
note: i,
velocity: 36,
releaseVelocity: 0,
duration: 1.0 )
status = MusicTrackNewMIDINoteEvent(track!, beat, &mess)
if status != OSStatus(noErr) {
print("creating new midi note event \(status)")
}
beat += 1
}
// associate the AUGraph with the sequence.
status = MusicSequenceSetAUGraph(musicSequence!, self.processingGraph)
// Let's see it
CAShow(UnsafeMutablePointer<MusicSequence>(musicSequence!))
return musicSequence!
}
/// Create a `MusicPlayer` with the specified sequence.
///
/// - parameters:
/// - musicSequence: a valid `MusicSequence` instance
/// - throws: Nothing, but it should
/// - todo: create an `ErrorType` ennum
/// - returns: a `MusicPlayer`
func createPlayer(_ musicSequence: MusicSequence) -> MusicPlayer {
var musicPlayer: MusicPlayer?
var status = NewMusicPlayer(&musicPlayer)
if status != OSStatus(noErr) {
print("bad status \(status) creating player")
AudioUtils.CheckError(status)
}
status = MusicPlayerSetSequence(musicPlayer!, musicSequence)
if status != OSStatus(noErr) {
print("setting sequence \(status)")
AudioUtils.CheckError(status)
}
status = MusicPlayerPreroll(musicPlayer!)
if status != OSStatus(noErr) {
print("prerolling player \(status)")
AudioUtils.CheckError(status)
}
return musicPlayer!
}
/// Make the `MusicPlayer` play its sequence
/// - throws: Nothing, but it should
/// - todo: create an `ErrorType` ennum
func musicPlayerPlay() {
var status = noErr
var playing: DarwinBoolean = false
status = MusicPlayerIsPlaying(musicPlayer, &playing)
if playing != false {
status = MusicPlayerStop(musicPlayer)
if status != noErr {
print("Error stopping \(status)")
AudioUtils.CheckError(status)
return
}
}
status = MusicPlayerSetTime(musicPlayer, 0)
if status != noErr {
print("setting time \(status)")
AudioUtils.CheckError(status)
return
}
status = MusicPlayerStart(musicPlayer)
if status != noErr {
print("Error starting \(status)")
AudioUtils.CheckError(status)
return
}
}
}
+449
View File
@@ -0,0 +1,449 @@
//
// AudioUtils.swift
// SwiftMusic
//
// Created by Gene De Lisa on 2/28/15.
// Copyright (c) 2015 Gene De Lisa. All rights reserved.
//
import Foundation
import AudioToolbox
import CoreAudio
// swiftlint:disable function_body_length
// swiftlint:disable type_body_length
// swiftlint:disable file_length
#if os(OSX)
// for UTCreateStringForOSType
import CoreServices
#endif
#if os(tvOS)
#elseif os(iOS)
import CoreMIDI
#endif
import AVFoundation
/// # A few utilities for using Core Audio.
///
/// I started with [Adamson's](http://amzn.to/1KG0yWe) Objective-C CheckError method. The translation
/// into Swift was a bit of a pain.
///
/// - author: Gene De Lisa
/// - copyright: 2016 Gene De Lisa
/// - date: February 2016
open class AudioUtils {
fileprivate init() {
}
/// Create a String from an encoded 4char.
///
/// - parameter n: The encoded 4char
///
/// - returns: The String representation.
class func stringFrom4(_ n: Int) -> String {
var scalar = UnicodeScalar((n >> 24) & 255)
if !scalar!.isASCII {
return ""
}
var s = String(describing: scalar)
scalar = UnicodeScalar((n >> 16) & 255)
if !scalar!.isASCII {
return ""
}
s.append(String(describing: scalar))
scalar = UnicodeScalar((n >> 8) & 255)
if !scalar!.isASCII {
return ""
}
s.append(String(describing: scalar))
scalar = UnicodeScalar(n & 255)
if !scalar!.isASCII {
return ""
}
s.append(String(describing: scalar))
return s
}
/// Create a String from an encoded 4char.
///
/// - parameter status: an `OSStatus` containing the encoded 4char.
///
/// - returns: The String representation.
class func stringFrom4(_ status: OSStatus) -> String {
let n = Int(status)
return stringFrom4(n)
}
/// Create an encoded 4char from a String.
///
/// - parameter s: The String.
///
/// - returns: the encoded Int
class func valueFromString4(_ s: String) -> Int {
var n = 0
var r = ""
if s.count > 4 {
let startIndex = s.index(s.startIndex, offsetBy: 4)
// r = s.substring(from: startIndex)
r = String(s[startIndex...])
} else {
r = s + " "
let startIndex = s.index(s.startIndex, offsetBy: 4)
// r = r.substring(to: startIndex)
r = String(r[...startIndex])
}
for UniCodeChar in r.unicodeScalars {
n = (n << 8) + (Int(UniCodeChar.value) & 255)
}
return n
}
// osx only
//let s = UTCreateStringForOSType(error)
//
// let e = UInt32(error)
//// let swapped = CFSwapInt32HostToBig(e)
// let swapped = e
//
// let b1 = Character(UnicodeScalar(swapped & 0b00001))
// let b2 = Character(UnicodeScalar(swapped & 0b00010))
// let b3 = Character(UnicodeScalar(swapped & 0b00100))
// let b4 = Character(UnicodeScalar(swapped & 0b01000))
// print("check error string: \(b1) \(b2) \(b3) \(b4)")
// func OSTypeFrom(string : String) -> UInt {
// var result : UInt = 0
// if let data = string.dataUsingEncoding(NSMacOSRomanStringEncoding) {
// let bytes = UnsafePointer<UInt8>(data.bytes)
// for i in 0..<data.length {
// result = result << 8 + UInt(bytes[i])
// }
// }
// return result
// }
// func stringValue(unicodeValue: Int) -> String {
// var stringValue = ""
// var value = unicodeValue
// for _ in 0..<4 {
// stringValue = String(UnicodeScalar(value & 255)) + stringValue
// value = value / 256
// }
// return stringValue
// }
#if os(tvOS)
/// Check the status code
///
/// - parameter error: The status to check.
/// - todo: Finish this for tvOS
class func CheckError(status: OSStatus) {
if status == noErr {
print("no error")
return
}
print("error \(status)")
}
#elseif os(iOS)
/// Print a description of the status code to stdout if it's an error.
///
/// - parameter status: the status to check.
class func CheckError(_ status: OSStatus) {
if status == noErr {
return
}
let s = stringFrom4(status)
print("error chars '\(s)'")
switch status {
// AudioToolbox
case kAUGraphErr_NodeNotFound:
print("kAUGraphErr_NodeNotFound")
case kAUGraphErr_OutputNodeErr:
print("kAUGraphErr_OutputNodeErr")
case kAUGraphErr_InvalidConnection:
print("kAUGraphErr_InvalidConnection")
case kAUGraphErr_CannotDoInCurrentContext:
print("kAUGraphErr_CannotDoInCurrentContext")
case kAUGraphErr_InvalidAudioUnit:
print("kAUGraphErr_InvalidAudioUnit")
case kMIDIInvalidClient :
print("kMIDIInvalidClient ")
case kMIDIInvalidPort :
print("kMIDIInvalidPort ")
case kMIDIWrongEndpointType :
print("kMIDIWrongEndpointType")
case kMIDINoConnection :
print("kMIDINoConnection ")
case kMIDIUnknownEndpoint :
print("kMIDIUnknownEndpoint ")
case kMIDIUnknownProperty :
print("kMIDIUnknownProperty ")
case kMIDIWrongPropertyType :
print("kMIDIWrongPropertyType ")
case kMIDINoCurrentSetup :
print("kMIDINoCurrentSetup ")
case kMIDIMessageSendErr :
print("kMIDIMessageSendErr ")
case kMIDIServerStartErr :
print("kMIDIServerStartErr ")
case kMIDISetupFormatErr :
print("kMIDISetupFormatErr ")
case kMIDIWrongThread :
print("kMIDIWrongThread ")
case kMIDIObjectNotFound :
print("kMIDIObjectNotFound ")
case kMIDIIDNotUnique :
print("kMIDIIDNotUnique ")
case kAudioToolboxErr_InvalidSequenceType :
print("kAudioToolboxErr_InvalidSequenceType ")
case kAudioToolboxErr_TrackIndexError :
print("kAudioToolboxErr_TrackIndexError ")
case kAudioToolboxErr_TrackNotFound :
print("kAudioToolboxErr_TrackNotFound ")
case kAudioToolboxErr_EndOfTrack :
print("kAudioToolboxErr_EndOfTrack ")
case kAudioToolboxErr_StartOfTrack :
print("kAudioToolboxErr_StartOfTrack ")
case kAudioToolboxErr_IllegalTrackDestination:
print("kAudioToolboxErr_IllegalTrackDestination")
case kAudioToolboxErr_NoSequence :
print("kAudioToolboxErr_NoSequence ")
case kAudioToolboxErr_InvalidEventType :
print("kAudioToolboxErr_InvalidEventType")
case kAudioToolboxErr_InvalidPlayerState:
print("kAudioToolboxErr_InvalidPlayerState")
case kAudioUnitErr_InvalidProperty :
print("kAudioUnitErr_InvalidProperty")
case kAudioUnitErr_InvalidParameter :
print("kAudioUnitErr_InvalidParameter")
case kAudioUnitErr_InvalidElement :
print("kAudioUnitErr_InvalidElement")
case kAudioUnitErr_NoConnection :
print("kAudioUnitErr_NoConnection")
case kAudioUnitErr_FailedInitialization :
print("kAudioUnitErr_FailedInitialization")
case kAudioUnitErr_TooManyFramesToProcess:
print("kAudioUnitErr_TooManyFramesToProcess")
case kAudioUnitErr_InvalidFile:
print("kAudioUnitErr_InvalidFile")
case kAudioUnitErr_FormatNotSupported :
print("kAudioUnitErr_FormatNotSupported")
case kAudioUnitErr_Uninitialized:
print("kAudioUnitErr_Uninitialized")
case kAudioUnitErr_InvalidScope :
print("kAudioUnitErr_InvalidScope")
case kAudioUnitErr_PropertyNotWritable :
print("kAudioUnitErr_PropertyNotWritable")
case kAudioUnitErr_InvalidPropertyValue :
print("kAudioUnitErr_InvalidPropertyValue")
case kAudioUnitErr_PropertyNotInUse :
print("kAudioUnitErr_PropertyNotInUse")
case kAudioUnitErr_Initialized :
print("kAudioUnitErr_Initialized")
case kAudioUnitErr_InvalidOfflineRender :
print("kAudioUnitErr_InvalidOfflineRender")
case kAudioUnitErr_Unauthorized :
print("kAudioUnitErr_Unauthorized")
case kAudioUnitErr_CannotDoInCurrentContext:
print("kAudioUnitErr_CannotDoInCurrentContext")
case kAudioUnitErr_FailedInitialization:
print("kAudioUnitErr_FailedInitialization")
case kAudioUnitErr_FileNotSpecified:
print("kAudioUnitErr_FileNotSpecified")
case kAudioUnitErr_FormatNotSupported:
print("kAudioUnitErr_FormatNotSupported")
case kAudioUnitErr_IllegalInstrument:
print("kAudioUnitErr_IllegalInstrument")
case kAudioUnitErr_Initialized:
print("kAudioUnitErr_Initialized")
case kAudioUnitErr_InstrumentTypeNotFound:
print("kAudioUnitErr_InstrumentTypeNotFound")
case kAudioUnitErr_InvalidElement:
print("kAudioUnitErr_InvalidElement")
case kAudioUnitErr_InvalidFile:
print("kAudioUnitErr_InvalidFile")
case kAudioUnitErr_InvalidOfflineRender:
print("kAudioUnitErr_InvalidOfflineRender")
case kAudioUnitErr_InvalidParameter:
print("kAudioUnitErr_InvalidParameter")
case kAudioUnitErr_InvalidProperty:
print("kAudioUnitErr_InvalidProperty")
case kAudioUnitErr_InvalidPropertyValue:
print("kAudioUnitErr_InvalidPropertyValue")
case kAudioUnitErr_InvalidScope:
print("kAudioUnitErr_InvalidScope")
case kAudioUnitErr_NoConnection:
print("kAudioUnitErr_NoConnection")
case kAudioUnitErr_PropertyNotInUse:
print("kAudioUnitErr_PropertyNotInUse")
case kAudioUnitErr_PropertyNotWritable:
print("kAudioUnitErr_PropertyNotWritable")
case kAudioUnitErr_TooManyFramesToProcess:
print("kAudioUnitErr_TooManyFramesToProcess")
case kAudioUnitErr_Unauthorized:
print("kAudioUnitErr_Unauthorized")
case kAudioUnitErr_Uninitialized:
print("kAudioUnitErr_Uninitialized")
case kAudioUnitErr_UnknownFileType:
print("kAudioUnitErr_UnknownFileType")
case kAudioComponentErr_InstanceInvalidated:
print("kAudioComponentErr_InstanceInvalidated ")
case kAudioComponentErr_DuplicateDescription:
print("kAudioComponentErr_DuplicateDescription ")
case kAudioComponentErr_UnsupportedType:
print("kAudioComponentErr_UnsupportedType ")
case kAudioComponentErr_TooManyInstances:
print("kAudioComponentErr_TooManyInstances ")
case kAudioComponentErr_NotPermitted:
print("kAudioComponentErr_NotPermitted ")
case kAudioComponentErr_InitializationTimedOut:
print("kAudioComponentErr_InitializationTimedOut ")
case kAudioComponentErr_InvalidFormat:
print("kAudioComponentErr_InvalidFormat ")
// in CoreAudioTypes
case kAudio_UnimplementedError :
print("kAudio_UnimplementedError")
case kAudio_FileNotFoundError :
print("kAudio_FileNotFoundError")
case kAudio_FilePermissionError :
print("kAudio_FilePermissionError")
case kAudio_TooManyFilesOpenError :
print("kAudio_TooManyFilesOpenError")
case kAudio_BadFilePathError :
print("kAudio_BadFilePathError")
case kAudio_ParamError :
print("kAudio_ParamError") // the infamous -50
case kAudio_MemFullError :
print("kAudio_MemFullError")
default:
print("huh?")
print("bad status \(status)")
//print("\(__LINE__) bad status \(error)")
}
}
#endif
}
@@ -0,0 +1,4 @@
#import <Flutter/Flutter.h>
@interface FlutterMidiPlugin : NSObject<FlutterPlugin>
@end
@@ -0,0 +1,8 @@
#import "FlutterMidiPlugin.h"
#import <flutter_midi/flutter_midi-Swift.h>
@implementation FlutterMidiPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
[SwiftFlutterMidiPlugin registerWithRegistrar:registrar];
}
@end
@@ -0,0 +1,61 @@
import Flutter
import UIKit
import AVFoundation
public class SwiftFlutterMidiPlugin: NSObject, FlutterPlugin {
var message = "Please Send Message"
var _arguments = [String: Any]()
var au: AudioUnitMIDISynth!
public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(name: "flutter_midi", binaryMessenger: registrar.messenger())
let instance = SwiftFlutterMidiPlugin()
registrar.addMethodCallDelegate(instance, channel: channel)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
case "prepare_midi":
let map = call.arguments as? Dictionary<String, String>
let data = map?["path"]
let url = URL(fileURLWithPath: data!)
au = AudioUnitMIDISynth(soundfont: url)
print("Valid URL: \(url)")
let message = "Prepared Sound Font"
result(message)
case "change_sound":
let map = call.arguments as? Dictionary<String, String>
let data = map?["path"]
let url = URL(fileURLWithPath: data!)
au.prepare(soundfont: url)
print("Valid URL: \(url)")
let message = "Prepared Sound Font"
result(message)
case "unmute":
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback)
} catch {
print(error)
}
let message = "unmuted Device"
result(message)
case "play_midi_note":
_arguments = call.arguments as! [String : Any];
let midi = _arguments["note"] as? Int
let velocity = _arguments["velocity"] as? Int
au.playPitch(midi: midi ?? 60, velocity: velocity ?? 64)
let message = "Playing: \(String(describing: midi!))"
result(message)
case "stop_midi_note":
_arguments = call.arguments as! [String : Any];
let midi = _arguments["note"] as? Int
let velocity = _arguments["velocity"] as? Int
au.stopPitch(midi: midi ?? 60, velocity: velocity ?? 64)
let message = "Stopped: \(String(describing: midi!))"
result(message)
default:
result(FlutterMethodNotImplemented)
break
}
}
}
+21
View File
@@ -0,0 +1,21 @@
#
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
#
Pod::Spec.new do |s|
s.name = 'flutter_midi'
s.version = '0.0.1'
s.summary = 'A FLutter Plugin to Play midi on iOS and Android.'
s.description = <<-DESC
A FLutter Plugin to Play midi on iOS and Android.
DESC
s.homepage = 'http://example.com'
s.license = { :file => '../LICENSE' }
s.author = { 'Your Company' => 'email@example.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.public_header_files = 'Classes/**/*.h'
s.dependency 'Flutter'
s.ios.deployment_target = '8.0'
end
@@ -0,0 +1,83 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'src/cache.dart';
import 'src/platform_interface.dart';
class FlutterMidi extends FlutterMidiPlatform {
static const MethodChannel _channel = MethodChannel('flutter_midi');
/// Needed so that the sound font is loaded
/// On iOS make sure to include the sound_font.SF2 in the Runner folder.
/// This does not work in the simulator.
@override
Future<String?> prepare({
required ByteData? sf2,
String name = 'instrument.sf2',
}) async {
if (sf2 == null) return Future.value(null);
if (kIsWeb) return _channel.invokeMethod('prepare_midi');
File? _file = await writeToFile(sf2, name: name);
if (_file == null) return null;
return _channel.invokeMethod('prepare_midi', {'path': _file.path});
}
/// Needed so that the sound font is loaded
/// On iOS make sure to include the sound_font.SF2 in the Runner folder.
/// This does not work in the simulator.
@override
Future<String?> changeSound({
required ByteData? sf2,
String name = 'instrument.sf2',
}) async {
if (sf2 == null) return Future.value(null);
File? _file = await writeToFile(sf2, name: name);
if (_file == null) return null;
final Map<dynamic, dynamic> mapData = <dynamic, dynamic>{};
mapData['path'] = _file.path;
debugPrint('Path => ${_file.path}');
final String result = await _channel.invokeMethod('change_sound', mapData);
debugPrint('Result: $result');
return result;
}
/// Unmute the device temporarily even if the mute switch is on or toggled in settings.
@override
Future<String> unmute() async {
final String result = await _channel.invokeMethod('unmute');
return result;
}
/// Use this when stopping the sound onTouchUp or to cancel a long file.
/// Not needed if playing midi onTap.
/// Stop with velocity in the range between 0-127
@override
Future<String?> stopMidiNote({
required int midi,
int velocity = 64,
}) async {
return _channel.invokeMethod('stop_midi_note', {
'note': midi,
'velocity': velocity,
});
}
/// Play a midi note from the sound_font.SF2 library bundled with the application.
/// Play a midi note in the range between 0-127
/// Play with velocity in the range between 0-127
/// Multiple notes can be played at once as separate calls.
@override
Future<String?> playMidiNote({
required int midi,
int velocity = 64,
}) async {
return _channel.invokeMethod('play_midi_note', {
'note': midi,
'velocity': velocity,
});
}
}
@@ -0,0 +1,41 @@
import 'dart:async';
import 'dart:js' as js;
import 'package:flutter/widgets.dart';
import 'package:tonic/tonic.dart' as tonic;
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
import 'package:flutter/services.dart';
import 'src/platform_interface.dart';
class FlutterMidiPlugin extends FlutterMidiPlatform {
static void registerWith(Registrar registrar) {
WidgetsFlutterBinding.ensureInitialized();
final instance = FlutterMidiPlugin();
final MethodChannel channel = MethodChannel(
'flutter_midi',
const StandardMethodCodec(),
registrar.messenger,
);
channel.setMethodCallHandler(instance.handleMethodCall);
}
Future<dynamic> handleMethodCall(MethodCall call) async {
switch (call.method) {
case 'play_midi_note':
final int midi = call.arguments['note'];
String _note = tonic.Pitch.fromMidiNumber(midi).toString();
_note = _note.replaceAll('', 'b').replaceAll('', '#');
js.context.callMethod('playNote', [_note]);
return 'Result: $_note';
case 'stop_midi_note':
final int midi = call.arguments['note'];
String _note = tonic.Pitch.fromMidiNumber(midi).toString();
_note = _note.replaceAll('', 'b').replaceAll('', '#');
// print('Midi -> $midi/$_note');
js.context.callMethod('stopNote');
return 'Result: $_note';
default:
}
}
}
@@ -0,0 +1,16 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
Future<File?> writeToFile(ByteData data,
{String name = "instrument.sf2"}) async {
if (kIsWeb) return null;
final buffer = data.buffer;
final directory = await getApplicationDocumentsDirectory();
final path = "${directory.path}/$name";
return File(path)
.writeAsBytes(buffer.asUint8List(data.offsetInBytes, data.lengthInBytes));
}
@@ -0,0 +1,70 @@
import 'package:flutter/services.dart';
import 'platform_interface.dart';
const MethodChannel _channel = MethodChannel('flutter_midi');
class MethodChannelUrlLauncher extends FlutterMidiPlatform {
/// Needed so that the sound font is loaded
/// On iOS make sure to include the sound_font.SF2 in the Runner folder.
/// This does not work in the simulator.
@override
Future<String?> prepare({
required ByteData? sf2,
String name = 'instrument.sf2',
}) async {
return _channel.invokeMethod<String>('prepare_midi', {
'name': name,
'data': sf2,
});
}
/// Needed so that the sound font is loaded
/// On iOS make sure to include the sound_font.SF2 in the Runner folder.
/// This does not work in the simulator.
@override
Future<String?> changeSound({
required ByteData? sf2,
String name = 'instrument.sf2',
}) async {
return _channel.invokeMethod<String>('change_sound', {
'name': name,
'data': sf2,
});
}
/// Unmute the device temporarily even if the mute switch is on or toggled in settings.
@override
Future<String?> unmute() {
return _channel.invokeMethod<String>('unmute');
}
/// Use this when stopping the sound onTouchUp or to cancel a long file.
/// Not needed if playing midi onTap.
/// Stop with velocity in the range between 0-127
@override
Future<String?> stopMidiNote({
required int midi,
int velocity = 64,
}) {
return _channel.invokeMethod<String>('stop_midi_note', {
'note': midi,
'velocity': velocity,
});
}
/// Play a midi note from the sound_font.SF2 library bundled with the application.
/// Play a midi note in the range between 0-127
/// Play with velocity in the range between 0-127
/// Multiple notes can be played at once as separate calls.
@override
Future<String?> playMidiNote({
required int midi,
int velocity = 64,
}) {
return _channel.invokeMethod<String>('play_midi_note', {
'note': midi,
'velocity': velocity,
});
}
}
@@ -0,0 +1,63 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
import 'method_channel.dart';
class FlutterMidiPlatform extends PlatformInterface {
FlutterMidiPlatform() : super(token: _token);
static final Object _token = Object();
static FlutterMidiPlatform _instance = MethodChannelUrlLauncher();
static FlutterMidiPlatform get instance => _instance;
static set instance(FlutterMidiPlatform instance) {
PlatformInterface.verifyToken(instance, _token);
_instance = instance;
}
/// Needed so that the sound font is loaded
/// On iOS make sure to include the sound_font.SF2 in the Runner folder.
/// This does not work in the simulator.
Future<String?> prepare({
required ByteData? sf2,
String name = 'instrument.sf2',
}) async {
debugPrint('Setup Midi..');
throw UnimplementedError('prepare() has not been implemented.');
}
/// Needed so that the sound font is loaded
/// On iOS make sure to include the sound_font.SF2 in the Runner folder.
/// This does not work in the simulator.
Future<String?> changeSound({
required ByteData? sf2,
String name = 'instrument.sf2',
}) async {
throw UnimplementedError('changeSound() has not been implemented.');
}
/// Unmute the device temporarily even if the mute switch is on or toggled in settings.
Future<String?> unmute() async {
throw UnimplementedError('canLaunch() has not been implemented.');
}
/// Use this when stopping the sound onTouchUp or to cancel a long file.
/// Not needed if playing midi onTap.
/// Stop with velocity in the range between 0-127
Future<String?> stopMidiNote({
required int midi,
int velocity = 64,
}) async {
throw UnimplementedError('stopMidiNote() has not been implemented.');
}
/// Play a midi note from the sound_font.SF2 library bundled with the application.
/// Play a midi note in the range between 0-127
/// Play with velocity in the range between 0-127
/// Multiple notes can be played at once as separate calls.
Future<String?> playMidiNote({
required int midi,
int velocity = 64,
}) async {
throw UnimplementedError('playMidiNote() has not been implemented.');
}
}
+8
View File
@@ -0,0 +1,8 @@
## This file must *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
#
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
#Sun Jan 27 20:59:01 EST 2019
sdk.dir=/Users/developer/Library/Android/sdk
@@ -0,0 +1,471 @@
//
// AudioUnitMIDISynth.swift
// MIDISynth
//
// Created by Gene De Lisa on 2/6/16.
// Copyright © 2016 Gene De Lisa. All rights reserved.
//
import Foundation
import AudioToolbox
import CoreAudio
// swiftlint:disable function_body_length
// swiftlint:disable type_body_length
// swiftlint:disable file_length
// swiftlint:disable line_length
/// # A Core Audio MIDISynth `AudioUnit` example.
/// This will add a polyphonic `kAudioUnitSubType_MIDISynth` audio unit to the `AUGraph`.
///
/// - author: Gene De Lisa
/// - copyright: 2016 Gene De Lisa
/// - date: February 2016
class AudioUnitMIDISynth: NSObject {
var processingGraph: AUGraph?
var midisynthNode = AUNode()
var ioNode = AUNode()
var midisynthUnit: AudioUnit?
var ioUnit: AudioUnit?
var musicSequence: MusicSequence!
var musicPlayer: MusicPlayer!
let patch1 = UInt32(46)
let patch2 = UInt32(0)
var pitch = UInt32(60)
var bankUrl: URL!
init(soundfont: URL) {
super.init()
prepare(soundfont:soundfont)
}
func prepare(soundfont: URL) {
bankUrl = soundfont;
augraphSetup()
loadMIDISynthSoundFont()
initializeGraph()
self.musicSequence = createMusicSequence()
musicPlayer = createPlayer(musicSequence)
loadPatches()
startGraph()
}
/// Create the `AUGraph`, the nodes and units, then wire them together.
func augraphSetup() {
var status = OSStatus(noErr)
status = NewAUGraph(&processingGraph)
// // AudioUtils.CheckError(status)
createIONode()
createSynthNode()
// now do the wiring. The graph needs to be open before you call AUGraphNodeInfo
status = AUGraphOpen(self.processingGraph!)
// // AudioUtils.CheckError(status)
status = AUGraphNodeInfo(self.processingGraph!, self.midisynthNode, nil, &midisynthUnit)
// AudioUtils.CheckError(status)
status = AUGraphNodeInfo(self.processingGraph!, self.ioNode, nil, &ioUnit)
// AudioUtils.CheckError(status)
let synthOutputElement: AudioUnitElement = 0
let ioUnitInputElement: AudioUnitElement = 0
status = AUGraphConnectNodeInput(self.processingGraph!,
self.midisynthNode, synthOutputElement, // srcnode, SourceOutputNumber
self.ioNode, ioUnitInputElement) // destnode, DestInputNumber
// AudioUtils.CheckError(status)
}
/// Create the Output Node and add it to the `AUGraph`.
func createIONode() {
var cd = AudioComponentDescription(
componentType: OSType(kAudioUnitType_Output),
componentSubType: OSType(kAudioUnitSubType_MIDISynth),
componentManufacturer: OSType(kAudioUnitManufacturer_Apple),
componentFlags: 0, componentFlagsMask: 0)
let status = AUGraphAddNode(self.processingGraph!, &cd, &ioNode)
// AudioUtils.CheckError(status)
}
/// Create the Synth Node and add it to the `AUGraph`.
func createSynthNode() {
var cd = AudioComponentDescription(
componentType: OSType(kAudioUnitType_MusicDevice),
componentSubType: OSType(kAudioUnitSubType_MIDISynth),
componentManufacturer: OSType(kAudioUnitManufacturer_Apple),
componentFlags: 0, componentFlagsMask: 0)
// let status = AUGraphAddNode(self.processingGraph!, &cd, &midisynthNode)
// AudioUtils.CheckError(status)
}
/// This will load the default sound font and set the synth unit's property.
/// - postcondition: `self.midisynthUnit` will have it's sound font url set.
func loadMIDISynthSoundFont() {
if var bankURL = bankUrl {
let status = AudioUnitSetProperty(
self.midisynthUnit!,
AudioUnitPropertyID(kMusicDeviceProperty_SoundBankURL),
AudioUnitScope(kAudioUnitScope_Global),
0,
&bankURL,
UInt32(MemoryLayout<URL>.size))
// AudioUtils.CheckError(status)
print("loaded sound font")
} else {
print("Could not load sound font")
}
}
/// Pre-load the patches you will use.
///
/// Turn on `kAUMIDISynthProperty_EnablePreload` so the midisynth will load the patch data from the file into memory.
/// You load the patches first before playing a sequence or sending messages.
/// Then you turn `kAUMIDISynthProperty_EnablePreload` off. It is now in a state where it will respond to MIDI program
/// change messages and switch to the already cached instrument data.
///
/// - precondition: the graph must be initialized
///
/// [Doug's post](http://prod.lists.apple.com/archives/coreaudio-api/2016/Jan/msg00018.html)
func loadPatches() {
if !isGraphInitialized() {
fatalError("initialize graph first")
}
let channel = UInt32(0)
var enabled = UInt32(1)
var status = AudioUnitSetProperty(
self.midisynthUnit!,
AudioUnitPropertyID(kAUMIDISynthProperty_EnablePreload),
AudioUnitScope(kAudioUnitScope_Global),
0,
&enabled,
UInt32(MemoryLayout<UInt32>.size))
// AudioUtils.CheckError(status)
// let bankSelectCommand = UInt32(0xB0 | 0)
// status = MusicDeviceMIDIEvent(self.midisynthUnit, bankSelectCommand, 0, 0, 0)
let pcCommand = UInt32(0xC0 | channel)
status = MusicDeviceMIDIEvent(self.midisynthUnit!, pcCommand, patch1, 0, 0)
// AudioUtils.CheckError(status)
status = MusicDeviceMIDIEvent(self.midisynthUnit!, pcCommand, patch2, 0, 0)
// AudioUtils.CheckError(status)
enabled = UInt32(0)
status = AudioUnitSetProperty(
self.midisynthUnit!,
AudioUnitPropertyID(kAUMIDISynthProperty_EnablePreload),
AudioUnitScope(kAudioUnitScope_Global),
0,
&enabled,
UInt32(MemoryLayout<UInt32>.size))
// AudioUtils.CheckError(status)
// at this point the patches are loaded. You still have to send a program change at "play time" for the synth
// to switch to that patch
}
/// Check to see if the `AUGraph` is Initialized.
///
/// - returns: `true` if it's running, `false` if not
/// - seealso: [AUGraphIsInitialized](/https://developer.apple.com/library/prerelease/ios/documentation/AudioToolbox/Reference/AUGraphServicesReference/index.html#//apple_ref/c/func/AUGraphIsInitialized)
func isGraphInitialized() -> Bool {
var outIsInitialized = DarwinBoolean(false)
let status = AUGraphIsInitialized(self.processingGraph!, &outIsInitialized)
// AudioUtils.CheckError(status)
return outIsInitialized.boolValue
}
/// Initializes the `AUGraph.
func initializeGraph() {
let status = AUGraphInitialize(self.processingGraph!)
// AudioUtils.CheckError(status)
}
/// Starts the `AUGraph`
func startGraph() {
let status = AUGraphStart(self.processingGraph!)
// AudioUtils.CheckError(status)
}
/// Check to see if the `AUGraph` is running.
///
/// - returns: `true` if it's running, `false` if not
func isGraphRunning() -> Bool {
var isRunning = DarwinBoolean(false)
let status = AUGraphIsRunning(self.processingGraph!, &isRunning)
// AudioUtils.CheckError(status)
return isRunning.boolValue
}
/// Generate a random pitch between 36 (C below middle C) and 100.
///
/// - postcondition: self.pitch is modified
func generateRandomPitch() {
pitch = arc4random_uniform(64) + 36 // 36 - 100
}
// /// Send a note on message using patch1 on channel 0
// func playPatch1On() {
//
// let channel = UInt32(0)
// let noteCommand = UInt32(0x90 | channel)
// let pcCommand = UInt32(0xC0 | channel)
// var status = OSStatus(noErr)
//
// generateRandomPitch()
// print(pitch)
// status = MusicDeviceMIDIEvent(self.midisynthUnit!, pcCommand, patch1, 0, 0)
// // AudioUtils.CheckError(status)
// status = MusicDeviceMIDIEvent(self.midisynthUnit!, noteCommand, pitch, 64, 0)
// // AudioUtils.CheckError(status)
// }
//
// /// Send a note off message using patch1 on channel 0
// func playPatch1Off() {
// let channel = UInt32(0)
// let noteCommand = UInt32(0x80 | channel)
// var status = OSStatus(noErr)
// status = MusicDeviceMIDIEvent(self.midisynthUnit!, noteCommand, pitch, 0, 0)
// // AudioUtils.CheckError(status)
// }
//
// /// Send a note on message using patch2 on channel 0
// func playPatch2On(midi: Int) {
//
// let channel = UInt32(0)
// let noteCommand = UInt32(0x90 | channel)
// let pcCommand = UInt32(0xC0 | channel)
// var status = OSStatus(noErr)
// pitch = UInt32(midi)
// //generateRandomPitch()
// print(pitch)
// status = MusicDeviceMIDIEvent(self.midisynthUnit!, pcCommand, patch2, 0, 0)
// // AudioUtils.CheckError(status)
// status = MusicDeviceMIDIEvent(self.midisynthUnit!, noteCommand, pitch, 64, 0)
// // AudioUtils.CheckError(status)
// }
//
// /// Send a note off message using patch2 on channel 0
// func playPatch2Off() {
// let channel = UInt32(0)
// let noteCommand = UInt32(0x80 | channel)
// var status = OSStatus(noErr)
// status = MusicDeviceMIDIEvent(self.midisynthUnit!, noteCommand, pitch, 0, 0)
// // AudioUtils.CheckError(status)
// }
//
/// Send a note on message using patch2 on channel 0
func playPitch(midi: Int, velocity: Int) {
let channel = UInt32(0)
let noteCommand = UInt32(0x90 | channel)
let pcCommand = UInt32(0xC0 | channel)
var status = OSStatus(noErr)
status = MusicDeviceMIDIEvent(self.midisynthUnit!, pcCommand, patch2, 0, 0)
// AudioUtils.CheckError(status)
status = MusicDeviceMIDIEvent(self.midisynthUnit!, noteCommand, UInt32(midi), UInt32(velocity), 0)
// AudioUtils.CheckError(status)
}
/// Send a note off message using patch2 on channel 0
func stopPitch(midi: Int, velocity: Int) {
let channel = UInt32(0)
let noteCommand = UInt32(0x80 | channel)
var status = OSStatus(noErr)
status = MusicDeviceMIDIEvent(self.midisynthUnit!, noteCommand, UInt32(midi), UInt32(velocity), 0)
// AudioUtils.CheckError(status)
}
/// Create a test `MusicSequence`.
///
/// - throws: Nothing, but it should
/// - todo: create an `ErrorType` ennum
/// - returns: a `MusicSequence`
func createMusicSequence() -> MusicSequence {
var musicSequence: MusicSequence?
var status = NewMusicSequence(&musicSequence)
if status != noErr {
print("\(#line) bad status \(status) creating sequence")
}
// add a track
var track: MusicTrack?
status = MusicSequenceNewTrack(musicSequence!, &track)
if status != noErr {
print("error creating track \(status)")
}
var channel = UInt8(0)
// bank select msb
var chanmess = MIDIChannelMessage(status: 0xB0 | channel, data1: 0, data2: 0, reserved: 0)
status = MusicTrackNewMIDIChannelEvent(track!, 0, &chanmess)
if status != noErr {
print("creating bank select event \(status)")
}
// bank select lsb
chanmess = MIDIChannelMessage(status: 0xB0 | channel, data1: 32, data2: 0, reserved: 0)
status = MusicTrackNewMIDIChannelEvent(track!, 0, &chanmess)
if status != noErr {
print("creating bank select event \(status)")
}
// program change. first data byte is the patch, the second data byte is unused for program change messages.
chanmess = MIDIChannelMessage(status: 0xC0 | channel, data1: UInt8(patch1), data2: 0, reserved: 0)
status = MusicTrackNewMIDIChannelEvent(track!, 0, &chanmess)
if status != noErr {
print("creating program change event \(status)")
}
// now make some notes and put them on the track
var beat = MusicTimeStamp(0.0)
for i: UInt8 in 60...72 {
var mess = MIDINoteMessage(channel: channel,
note: i,
velocity: 64,
releaseVelocity: 0,
duration: 1.0 )
status = MusicTrackNewMIDINoteEvent(track!, beat, &mess)
if status != noErr {
print("creating new midi note event \(status)")
}
beat += 1
}
// another track
channel = UInt8(1)
track = nil
status = MusicSequenceNewTrack(musicSequence!, &track)
if status != noErr {
print("error creating track \(status)")
}
chanmess = MIDIChannelMessage(status: 0xB0 | channel, data1: 0, data2: 0, reserved: 0)
status = MusicTrackNewMIDIChannelEvent(track!, 0, &chanmess)
if status != noErr {
print("creating bank select msb event \(status)")
}
chanmess = MIDIChannelMessage(status: 0xB0 | channel, data1: 32, data2: 0, reserved: 0)
status = MusicTrackNewMIDIChannelEvent(track!, 0, &chanmess)
if status != noErr {
print("creating bank select lsb event \(status)")
}
chanmess = MIDIChannelMessage(status: 0xC0 | channel, data1: UInt8(patch2), data2: 0, reserved: 0)
status = MusicTrackNewMIDIChannelEvent(track!, 0, &chanmess)
if status != noErr {
print("creating program change event \(status)")
}
beat = MusicTimeStamp(3.0)
for i: UInt8 in 60...72 {
var mess = MIDINoteMessage(channel: channel,
note: i,
velocity: 36,
releaseVelocity: 0,
duration: 1.0 )
status = MusicTrackNewMIDINoteEvent(track!, beat, &mess)
if status != OSStatus(noErr) {
print("creating new midi note event \(status)")
}
beat += 1
}
// associate the AUGraph with the sequence.
status = MusicSequenceSetAUGraph(musicSequence!, self.processingGraph)
// Let's see it
CAShow(UnsafeMutablePointer<MusicSequence>(musicSequence!))
return musicSequence!
}
/// Create a `MusicPlayer` with the specified sequence.
///
/// - parameters:
/// - musicSequence: a valid `MusicSequence` instance
/// - throws: Nothing, but it should
/// - todo: create an `ErrorType` ennum
/// - returns: a `MusicPlayer`
func createPlayer(_ musicSequence: MusicSequence) -> MusicPlayer {
var musicPlayer: MusicPlayer?
var status = NewMusicPlayer(&musicPlayer)
if status != OSStatus(noErr) {
print("bad status \(status) creating player")
// AudioUtils.CheckError(status)
}
status = MusicPlayerSetSequence(musicPlayer!, musicSequence)
if status != OSStatus(noErr) {
print("setting sequence \(status)")
// AudioUtils.CheckError(status)
}
status = MusicPlayerPreroll(musicPlayer!)
if status != OSStatus(noErr) {
print("prerolling player \(status)")
// AudioUtils.CheckError(status)
}
return musicPlayer!
}
/// Make the `MusicPlayer` play its sequence
/// - throws: Nothing, but it should
/// - todo: create an `ErrorType` ennum
func musicPlayerPlay() {
var status = noErr
var playing: DarwinBoolean = false
status = MusicPlayerIsPlaying(musicPlayer, &playing)
if playing != false {
status = MusicPlayerStop(musicPlayer)
if status != noErr {
print("Error stopping \(status)")
// AudioUtils.CheckError(status)
return
}
}
status = MusicPlayerSetTime(musicPlayer, 0)
if status != noErr {
print("setting time \(status)")
// AudioUtils.CheckError(status)
return
}
status = MusicPlayerStart(musicPlayer)
if status != noErr {
print("Error starting \(status)")
// AudioUtils.CheckError(status)
return
}
}
}
+440
View File
@@ -0,0 +1,440 @@
//
// AudioUtils.swift
// SwiftMusic
//
// Created by Gene De Lisa on 2/28/15.
// Copyright (c) 2015 Gene De Lisa. All rights reserved.
//
import Foundation
import AudioToolbox
import CoreAudio
// swiftlint:disable function_body_length
// swiftlint:disable type_body_length
// swiftlint:disable file_length
import CoreServices
import AVFoundation
/// # A few utilities for using Core Audio.
///
/// I started with [Adamson's](http://amzn.to/1KG0yWe) Objective-C CheckError method. The translation
/// into Swift was a bit of a pain.
///
/// - author: Gene De Lisa
/// - copyright: 2016 Gene De Lisa
/// - date: February 2016
open class AudioUtils {
fileprivate init() {
}
/// Create a String from an encoded 4char.
///
/// - parameter n: The encoded 4char
///
/// - returns: The String representation.
class func stringFrom4(_ n: Int) -> String {
var scalar = UnicodeScalar((n >> 24) & 255)
if !scalar!.isASCII {
return ""
}
var s = String(describing: scalar)
scalar = UnicodeScalar((n >> 16) & 255)
if !scalar!.isASCII {
return ""
}
s.append(String(describing: scalar))
scalar = UnicodeScalar((n >> 8) & 255)
if !scalar!.isASCII {
return ""
}
s.append(String(describing: scalar))
scalar = UnicodeScalar(n & 255)
if !scalar!.isASCII {
return ""
}
s.append(String(describing: scalar))
return s
}
/// Create a String from an encoded 4char.
///
/// - parameter status: an `OSStatus` containing the encoded 4char.
///
/// - returns: The String representation.
class func stringFrom4(_ status: OSStatus) -> String {
let n = Int(status)
return stringFrom4(n)
}
/// Create an encoded 4char from a String.
///
/// - parameter s: The String.
///
/// - returns: the encoded Int
class func valueFromString4(_ s: String) -> Int {
var n = 0
var r = ""
if s.count > 4 {
let startIndex = s.index(s.startIndex, offsetBy: 4)
// r = s.substring(from: startIndex)
r = String(s[startIndex...])
} else {
r = s + " "
let startIndex = s.index(s.startIndex, offsetBy: 4)
// r = r.substring(to: startIndex)
r = String(r[...startIndex])
}
for UniCodeChar in r.unicodeScalars {
n = (n << 8) + (Int(UniCodeChar.value) & 255)
}
return n
}
// // osx only
// let s = UTCreateStringForOSType(error)
//
// let e = UInt32(error)
// // let swapped = CFSwapInt32HostToBig(e)
// let swapped = e
//
// let b1 = Character(UnicodeScalar(swapped & 0b00001))
// let b2 = Character(UnicodeScalar(swapped & 0b00010))
// let b3 = Character(UnicodeScalar(swapped & 0b00100))
// let b4 = Character(UnicodeScalar(swapped & 0b01000))
// print("check error string: \(b1) \(b2) \(b3) \(b4)")
// func OSTypeFrom(string : String) -> UInt {
// var result : UInt = 0
// if let data = string.dataUsingEncoding(NSMacOSRomanStringEncoding) {
// let bytes = UnsafePointer<UInt8>(data.bytes)
// for i in 0..<data.length {
// result = result << 8 + UInt(bytes[i])
// }
// }
// return result
// }
//
//
// func stringValue(unicodeValue: Int) -> String {
// var stringValue = ""
// var value = unicodeValue
// for _ in 0..<4 {
// stringValue = String(UnicodeScalar(value & 255)) + stringValue
// value = value / 256
// }
// return stringValue
// }
#if os(tvOS)
/// Check the status code
///
/// - parameter error: The status to check.
/// - todo: Finish this for tvOS
class func CheckError(status: OSStatus) {
if status == noErr {
print("no error")
return
}
print("error \(status)")
}
#elseif os(iOS)
/// Print a description of the status code to stdout if it's an error.
///
/// - parameter status: the status to check.
class func CheckError(_ status: OSStatus) {
if status == noErr {
return
}
let s = stringFrom4(status)
print("error chars '\(s)'")
switch status {
// AudioToolbox
case kAUGraphErr_NodeNotFound:
print("kAUGraphErr_NodeNotFound")
case kAUGraphErr_OutputNodeErr:
print("kAUGraphErr_OutputNodeErr")
case kAUGraphErr_InvalidConnection:
print("kAUGraphErr_InvalidConnection")
case kAUGraphErr_CannotDoInCurrentContext:
print("kAUGraphErr_CannotDoInCurrentContext")
case kAUGraphErr_InvalidAudioUnit:
print("kAUGraphErr_InvalidAudioUnit")
case kMIDIInvalidClient :
print("kMIDIInvalidClient ")
case kMIDIInvalidPort :
print("kMIDIInvalidPort ")
case kMIDIWrongEndpointType :
print("kMIDIWrongEndpointType")
case kMIDINoConnection :
print("kMIDINoConnection ")
case kMIDIUnknownEndpoint :
print("kMIDIUnknownEndpoint ")
case kMIDIUnknownProperty :
print("kMIDIUnknownProperty ")
case kMIDIWrongPropertyType :
print("kMIDIWrongPropertyType ")
case kMIDINoCurrentSetup :
print("kMIDINoCurrentSetup ")
case kMIDIMessageSendErr :
print("kMIDIMessageSendErr ")
case kMIDIServerStartErr :
print("kMIDIServerStartErr ")
case kMIDISetupFormatErr :
print("kMIDISetupFormatErr ")
case kMIDIWrongThread :
print("kMIDIWrongThread ")
case kMIDIObjectNotFound :
print("kMIDIObjectNotFound ")
case kMIDIIDNotUnique :
print("kMIDIIDNotUnique ")
case kAudioToolboxErr_InvalidSequenceType :
print("kAudioToolboxErr_InvalidSequenceType ")
case kAudioToolboxErr_TrackIndexError :
print("kAudioToolboxErr_TrackIndexError ")
case kAudioToolboxErr_TrackNotFound :
print("kAudioToolboxErr_TrackNotFound ")
case kAudioToolboxErr_EndOfTrack :
print("kAudioToolboxErr_EndOfTrack ")
case kAudioToolboxErr_StartOfTrack :
print("kAudioToolboxErr_StartOfTrack ")
case kAudioToolboxErr_IllegalTrackDestination:
print("kAudioToolboxErr_IllegalTrackDestination")
case kAudioToolboxErr_NoSequence :
print("kAudioToolboxErr_NoSequence ")
case kAudioToolboxErr_InvalidEventType :
print("kAudioToolboxErr_InvalidEventType")
case kAudioToolboxErr_InvalidPlayerState:
print("kAudioToolboxErr_InvalidPlayerState")
case kAudioUnitErr_InvalidProperty :
print("kAudioUnitErr_InvalidProperty")
case kAudioUnitErr_InvalidParameter :
print("kAudioUnitErr_InvalidParameter")
case kAudioUnitErr_InvalidElement :
print("kAudioUnitErr_InvalidElement")
case kAudioUnitErr_NoConnection :
print("kAudioUnitErr_NoConnection")
case kAudioUnitErr_FailedInitialization :
print("kAudioUnitErr_FailedInitialization")
case kAudioUnitErr_TooManyFramesToProcess:
print("kAudioUnitErr_TooManyFramesToProcess")
case kAudioUnitErr_InvalidFile:
print("kAudioUnitErr_InvalidFile")
case kAudioUnitErr_FormatNotSupported :
print("kAudioUnitErr_FormatNotSupported")
case kAudioUnitErr_Uninitialized:
print("kAudioUnitErr_Uninitialized")
case kAudioUnitErr_InvalidScope :
print("kAudioUnitErr_InvalidScope")
case kAudioUnitErr_PropertyNotWritable :
print("kAudioUnitErr_PropertyNotWritable")
case kAudioUnitErr_InvalidPropertyValue :
print("kAudioUnitErr_InvalidPropertyValue")
case kAudioUnitErr_PropertyNotInUse :
print("kAudioUnitErr_PropertyNotInUse")
case kAudioUnitErr_Initialized :
print("kAudioUnitErr_Initialized")
case kAudioUnitErr_InvalidOfflineRender :
print("kAudioUnitErr_InvalidOfflineRender")
case kAudioUnitErr_Unauthorized :
print("kAudioUnitErr_Unauthorized")
case kAudioUnitErr_CannotDoInCurrentContext:
print("kAudioUnitErr_CannotDoInCurrentContext")
case kAudioUnitErr_FailedInitialization:
print("kAudioUnitErr_FailedInitialization")
case kAudioUnitErr_FileNotSpecified:
print("kAudioUnitErr_FileNotSpecified")
case kAudioUnitErr_FormatNotSupported:
print("kAudioUnitErr_FormatNotSupported")
case kAudioUnitErr_IllegalInstrument:
print("kAudioUnitErr_IllegalInstrument")
case kAudioUnitErr_Initialized:
print("kAudioUnitErr_Initialized")
case kAudioUnitErr_InstrumentTypeNotFound:
print("kAudioUnitErr_InstrumentTypeNotFound")
case kAudioUnitErr_InvalidElement:
print("kAudioUnitErr_InvalidElement")
case kAudioUnitErr_InvalidFile:
print("kAudioUnitErr_InvalidFile")
case kAudioUnitErr_InvalidOfflineRender:
print("kAudioUnitErr_InvalidOfflineRender")
case kAudioUnitErr_InvalidParameter:
print("kAudioUnitErr_InvalidParameter")
case kAudioUnitErr_InvalidProperty:
print("kAudioUnitErr_InvalidProperty")
case kAudioUnitErr_InvalidPropertyValue:
print("kAudioUnitErr_InvalidPropertyValue")
case kAudioUnitErr_InvalidScope:
print("kAudioUnitErr_InvalidScope")
case kAudioUnitErr_NoConnection:
print("kAudioUnitErr_NoConnection")
case kAudioUnitErr_PropertyNotInUse:
print("kAudioUnitErr_PropertyNotInUse")
case kAudioUnitErr_PropertyNotWritable:
print("kAudioUnitErr_PropertyNotWritable")
case kAudioUnitErr_TooManyFramesToProcess:
print("kAudioUnitErr_TooManyFramesToProcess")
case kAudioUnitErr_Unauthorized:
print("kAudioUnitErr_Unauthorized")
case kAudioUnitErr_Uninitialized:
print("kAudioUnitErr_Uninitialized")
case kAudioUnitErr_UnknownFileType:
print("kAudioUnitErr_UnknownFileType")
case kAudioComponentErr_InstanceInvalidated:
print("kAudioComponentErr_InstanceInvalidated ")
case kAudioComponentErr_DuplicateDescription:
print("kAudioComponentErr_DuplicateDescription ")
case kAudioComponentErr_UnsupportedType:
print("kAudioComponentErr_UnsupportedType ")
case kAudioComponentErr_TooManyInstances:
print("kAudioComponentErr_TooManyInstances ")
case kAudioComponentErr_NotPermitted:
print("kAudioComponentErr_NotPermitted ")
case kAudioComponentErr_InitializationTimedOut:
print("kAudioComponentErr_InitializationTimedOut ")
case kAudioComponentErr_InvalidFormat:
print("kAudioComponentErr_InvalidFormat ")
// in CoreAudioTypes
case kAudio_UnimplementedError :
print("kAudio_UnimplementedError")
case kAudio_FileNotFoundError :
print("kAudio_FileNotFoundError")
case kAudio_FilePermissionError :
print("kAudio_FilePermissionError")
case kAudio_TooManyFilesOpenError :
print("kAudio_TooManyFilesOpenError")
case kAudio_BadFilePathError :
print("kAudio_BadFilePathError")
case kAudio_ParamError :
print("kAudio_ParamError") // the infamous -50
case kAudio_MemFullError :
print("kAudio_MemFullError")
default:
print("huh?")
print("bad status \(status)")
//print("\(__LINE__) bad status \(error)")
}
}
#endif
}
@@ -0,0 +1,61 @@
import Cocoa
import FlutterMacOS
import AVFoundation
public class FlutterMidiPlugin: NSObject, FlutterPlugin {
var message = "Please Send Message"
var _arguments = [String: Any]()
var au: AudioUnitMIDISynth!
public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(name: "flutter_midi", binaryMessenger: registrar.messenger)
let instance = FlutterMidiPlugin()
registrar.addMethodCallDelegate(instance, channel: channel)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
case "prepare_midi":
let map = call.arguments as? Dictionary<String, String>
let data = map?["path"]
let url = URL(fileURLWithPath: data!)
au = AudioUnitMIDISynth(soundfont: url)
print("Valid URL: \(url)")
let message = "Prepared Sound Font"
result(message)
case "change_sound":
let map = call.arguments as? Dictionary<String, String>
let data = map?["path"]
let url = URL(fileURLWithPath: data!)
au.prepare(soundfont: url)
print("Valid URL: \(url)")
let message = "Prepared Sound Font"
result(message)
case "unmute":
do {
// try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
} catch {
print(error)
}
let message = "unmuted Device"
result(message)
case "play_midi_note":
_arguments = call.arguments as! [String : Any];
let midi = _arguments["note"] as? Int
let velocity = _arguments["velocity"] as? Int
au.playPitch(midi: midi ?? 60, velocity: velocity ?? 64)
let message = "Playing: \(String(describing: midi!))"
result(message)
case "stop_midi_note":
_arguments = call.arguments as! [String : Any];
let midi = _arguments["note"] as? Int
let velocity = _arguments["velocity"] as? Int
au.stopPitch(midi: midi ?? 60, velocity: velocity ?? 64)
let message = "Stopped: \(String(describing: midi!))"
result(message)
default:
result(FlutterMethodNotImplemented)
break
}
}
}
@@ -0,0 +1,12 @@
//
// Generated file. Do not edit.
//
import FlutterMacOS
import Foundation
import path_provider_macos
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
}
+22
View File
@@ -0,0 +1,22 @@
#
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
# Run `pod lib lint flutter_midi.podspec' to validate before publishing.
#
Pod::Spec.new do |s|
s.name = 'flutter_midi'
s.version = '0.0.1'
s.summary = 'A new flutter plugin project.'
s.description = <<-DESC
A new flutter plugin project.
DESC
s.homepage = 'http://example.com'
s.license = { :file => '../LICENSE' }
s.author = { 'Your Company' => 'email@example.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.dependency 'FlutterMacOS'
s.platform = :osx, '10.11'
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }
s.swift_version = '5.0'
end
+35
View File
@@ -0,0 +1,35 @@
name: flutter_midi
description: A FLutter Plugin to Play midi on iOS and Android.
version: 1.1.1
author: Rody Davis <rody.davis.jr@gmail.com>
homepage: https://github.com/rodydavis/flutter_midi
environment:
sdk: ">=2.12.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
flutter_web_plugins:
sdk: flutter
js: ^0.6.3
path_provider: ^2.0.5
plugin_platform_interface: ^2.0.1
tonic: ^0.2.4
flutter:
plugin:
platforms:
ios:
pluginClass: FlutterMidiPlugin
android:
package: com.appleeducate.fluttermidi
pluginClass: FlutterMidiPlugin
# web:
# pluginClass: FlutterMidiPlugin
# fileName: flutter_midi_web.dart
# macos:
# pluginClass: FlutterMidiPlugin
dev_dependencies:
flutter_test:
sdk: flutter