├── AblLinkSample ├── app │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── noisepages │ │ │ └── nettoyeur │ │ │ └── abllinksample │ │ │ └── MainActivity.java │ │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── raw │ │ └── metronome.pd │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── CHANGES.txt ├── LICENSE ├── README.md ├── android ├── CMakeLists.txt └── README.md └── external ├── Makefile ├── Makefile.pdlibbuilder ├── abl_link_instance.cpp ├── abl_link_instance.hpp ├── abl_link~-help.pd ├── abl_link~.cpp ├── abl_link~.hpp ├── android-ifaddrs ├── foo.h ├── ifaddrs.cpp └── ifaddrs.h └── metronome.pd /AblLinkSample/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion rootProject.ext.compileSdkVersion 5 | buildToolsVersion rootProject.ext.buildToolsVersion 6 | defaultConfig { 7 | applicationId "com.noisepages.nettoyeur.abllinksample" 8 | minSdkVersion rootProject.minSdkVersion 9 | targetSdkVersion 30 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | externalNativeBuild { 20 | cmake { 21 | path '../../android/CMakeLists.txt' 22 | } 23 | } 24 | } 25 | 26 | dependencies { 27 | implementation project(':PdCore') 28 | implementation 'com.google.android.material:material:1.6.0' 29 | implementation 'androidx.activity:activity:1.4.0' 30 | } 31 | -------------------------------------------------------------------------------- /AblLinkSample/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/tal/Development/tools/android-sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /AblLinkSample/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /AblLinkSample/app/src/main/java/com/noisepages/nettoyeur/abllinksample/MainActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * For information on usage and redistribution, and for a DISCLAIMER OF ALL 3 | * WARRANTIES, see the file, LICENSE, in the root of this repository. 4 | * 5 | */ 6 | 7 | package com.noisepages.nettoyeur.abllinksample; 8 | 9 | import org.puredata.android.io.AudioParameters; 10 | import org.puredata.android.service.PdPreferences; 11 | import org.puredata.android.service.PdService; 12 | import org.puredata.core.PdBase; 13 | import org.puredata.core.PdListener; 14 | import org.puredata.core.utils.IoUtils; 15 | import org.puredata.core.utils.PdDispatcher; 16 | 17 | import android.content.ComponentName; 18 | import android.content.Intent; 19 | import android.content.ServiceConnection; 20 | import android.content.res.Resources; 21 | import android.os.Bundle; 22 | import android.os.IBinder; 23 | import android.util.Log; 24 | import android.view.View; 25 | import android.widget.CheckBox; 26 | import android.widget.SeekBar; 27 | import android.widget.TextView; 28 | import android.widget.Toast; 29 | 30 | import androidx.appcompat.app.AppCompatActivity; 31 | 32 | import java.io.File; 33 | import java.io.IOException; 34 | import java.io.InputStream; 35 | import java.util.Locale; 36 | 37 | public class MainActivity extends AppCompatActivity { 38 | 39 | private static final String TAG = "AblLinkSample"; 40 | static final int PD_LATENCY_MS = 7; // Latency values shouldn't go below this 41 | 42 | private TextView tempoLabel = null; 43 | private SeekBar tempoBar = null; 44 | private TextView phase = null; 45 | private TextView beatTime = null; 46 | private PdService pdService = null; 47 | private Toast toast = null; 48 | 49 | private void toast(final String msg) { 50 | runOnUiThread(new Runnable() { 51 | @Override 52 | public void run() { 53 | toast.setText(TAG + ": " + msg); 54 | toast.show(); 55 | } 56 | }); 57 | } 58 | 59 | private PdDispatcher dispatcher = new PdDispatcher() { 60 | @Override 61 | public void print(String s) { 62 | toast(s); 63 | } 64 | }; 65 | 66 | private final ServiceConnection pdConnection = new ServiceConnection() { 67 | @Override 68 | public void onServiceConnected(ComponentName name, IBinder service) { 69 | pdService = ((PdService.PdBinder) service).getService(); 70 | initPd(); 71 | } 72 | 73 | @Override 74 | public void onServiceDisconnected(ComponentName name) { 75 | // this method will never be called 76 | } 77 | }; 78 | 79 | @Override 80 | protected void onCreate(Bundle savedInstanceState) { 81 | super.onCreate(savedInstanceState); 82 | toast = Toast.makeText(getApplicationContext(), "", Toast.LENGTH_SHORT); 83 | AudioParameters.init(this); 84 | PdPreferences.initPreferences(getApplicationContext()); 85 | initGui(); 86 | bindService(new Intent(this, PdService.class), pdConnection, BIND_AUTO_CREATE); 87 | } 88 | 89 | @Override 90 | protected void onDestroy() { 91 | super.onDestroy(); 92 | cleanup(); 93 | } 94 | 95 | private void initGui() { 96 | setContentView(R.layout.activity_main); 97 | final CheckBox connectBox = (CheckBox) findViewById(R.id.connectBox); 98 | connectBox.setOnClickListener(new View.OnClickListener() { 99 | @Override 100 | public void onClick(View view) { 101 | PdBase.sendFloat("connect", connectBox.isChecked() ? 1 : 0); 102 | } 103 | }); 104 | tempoLabel = (TextView) findViewById(R.id.tempoLabel); 105 | tempoBar = (SeekBar) findViewById(R.id.tempoBar); 106 | tempoBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 107 | @Override 108 | public void onProgressChanged(SeekBar seekBar, int value, boolean fromUser) { 109 | if (fromUser) { 110 | PdBase.sendFloat("tempo", (float) progressToTempo(value)); 111 | } 112 | } 113 | @Override public void onStartTrackingTouch(SeekBar seekBar) {} 114 | @Override public void onStopTrackingTouch(SeekBar seekBar) {} 115 | }); 116 | final TextView quantumLabel = (TextView) findViewById(R.id.quantumLabel); 117 | final SeekBar quantumBar = (SeekBar) findViewById(R.id.quantumBar); 118 | quantumBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 119 | @Override 120 | public void onProgressChanged(SeekBar seekBar, int value, boolean fromUser) { 121 | int q = value + 1; 122 | PdBase.sendFloat("quantum", q); 123 | quantumLabel.setText("Quantum: " + q); 124 | } 125 | @Override public void onStartTrackingTouch(SeekBar seekBar) {} 126 | @Override public void onStopTrackingTouch(SeekBar seekBar) {} 127 | }); 128 | final TextView latencyLabel = (TextView) findViewById(R.id.offsetLabel); 129 | final SeekBar latencyBar = (SeekBar) findViewById(R.id.offsetBar); 130 | latencyBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 131 | @Override 132 | public void onProgressChanged(SeekBar seekBar, int value, boolean fromUser) { 133 | if (fromUser) { 134 | int toSet = PD_LATENCY_MS + value; 135 | PdBase.sendFloat("offset", (float) toSet); 136 | latencyLabel.setText("Offset: " + toSet + "ms"); 137 | } 138 | } 139 | @Override public void onStartTrackingTouch(SeekBar seekBar) {} 140 | @Override public void onStopTrackingTouch(SeekBar seekBar) {} 141 | }); 142 | latencyBar.setProgress(23 - PD_LATENCY_MS); 143 | phase = (TextView) findViewById(R.id.phase); 144 | beatTime = (TextView) findViewById(R.id.beatTime); 145 | } 146 | 147 | private void initPd() { 148 | Resources res = getResources(); 149 | File patchFile = null; 150 | try { 151 | PdBase.setReceiver(dispatcher); 152 | PdBase.subscribe("android"); 153 | InputStream in = res.openRawResource(R.raw.metronome); 154 | patchFile = IoUtils.extractResource(in, "metronome.pd", getCacheDir()); 155 | PdBase.openPatch(patchFile); 156 | dispatcher.addListener("tempoOut", new PdListener.Adapter() { 157 | @Override public void receiveFloat(final String source, final float x) { 158 | runOnUiThread(new Runnable() { 159 | @Override 160 | public void run() { 161 | tempoLabel.setText("Tempo: " + (int) (x + 0.5) + "bpm"); 162 | tempoBar.setProgress(tempoToProgress(x)); 163 | } 164 | }); 165 | } 166 | }); 167 | dispatcher.addListener("phase", new PdListener.Adapter() { 168 | @Override public void receiveFloat(final String source, final float x) { 169 | runOnUiThread(new Runnable() { 170 | @Override 171 | public void run() { 172 | phase.setText(String.format(Locale.US, "%,.1f", x)); 173 | } 174 | }); 175 | } 176 | }); 177 | dispatcher.addListener("beatTime", new PdListener.Adapter() { 178 | @Override public void receiveFloat(final String source, final float x) { 179 | runOnUiThread(new Runnable() { 180 | @Override 181 | public void run() { 182 | beatTime.setText(String.format(Locale.US, "%,.1f", x)); 183 | } 184 | }); 185 | } 186 | }); 187 | startAudio(); 188 | } catch (IOException e) { 189 | Log.e(TAG, e.toString()); 190 | finish(); 191 | } finally { 192 | if (patchFile != null) patchFile.delete(); 193 | } 194 | } 195 | 196 | private void startAudio() { 197 | String name = getResources().getString(R.string.app_name); 198 | try { 199 | pdService.initAudio(-1, 0, 2, -1); // negative values will be replaced with defaults/preferences 200 | pdService.startAudio(new Intent(this, MainActivity.class), R.drawable.icon, name, "Return to " + name + "."); 201 | } catch (IOException e) { 202 | toast(e.toString()); 203 | } 204 | } 205 | 206 | private void stopAudio() { 207 | pdService.stopAudio(); 208 | } 209 | 210 | private void cleanup() { 211 | try { 212 | stopAudio(); 213 | unbindService(pdConnection); 214 | } catch (IllegalArgumentException e) { 215 | // already unbound 216 | pdService = null; 217 | } 218 | } 219 | 220 | private static final double ctemp = Math.sqrt(20.0 * 999.0); 221 | private static final double qtemp = ctemp / 20.0; 222 | 223 | private double progressToTempo(int progress) { 224 | return ctemp * Math.pow(qtemp, (progress - 50.0) / 50.0); 225 | } 226 | 227 | private int tempoToProgress(float bpm) { 228 | return (int) (50.0 + 50 * Math.log(bpm / ctemp) / Math.log(qtemp)); 229 | } 230 | } -------------------------------------------------------------------------------- /AblLinkSample/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 22 | 23 | 30 | 31 | 36 | 37 | 44 | 45 | 53 | 54 | 61 | 62 | 68 | 69 | 74 | 75 | 79 | 80 | 86 | 87 | 91 | 92 | 98 | 99 | 100 | 101 | 105 | 106 | 112 | 113 | 117 | 118 | 124 | 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /AblLinkSample/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libpd/abl_link/25642d0c80edd234b2f2eecd98065f9f0232058f/AblLinkSample/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /AblLinkSample/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libpd/abl_link/25642d0c80edd234b2f2eecd98065f9f0232058f/AblLinkSample/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /AblLinkSample/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libpd/abl_link/25642d0c80edd234b2f2eecd98065f9f0232058f/AblLinkSample/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /AblLinkSample/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libpd/abl_link/25642d0c80edd234b2f2eecd98065f9f0232058f/AblLinkSample/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /AblLinkSample/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libpd/abl_link/25642d0c80edd234b2f2eecd98065f9f0232058f/AblLinkSample/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /AblLinkSample/app/src/main/res/raw/metronome.pd: -------------------------------------------------------------------------------- 1 | #N canvas 586 72 413 406 10; 2 | #X obj 154 278 osc~ 440; 3 | #X obj 110 308 *~; 4 | #X obj 110 352 dac~; 5 | #X obj 80 279 vline~; 6 | #X msg 80 258 1 \, 0 250; 7 | #X obj 110 330 *~ 0.25; 8 | #X msg 93 64 tempo \$1; 9 | #X msg 156 64 resolution \$1; 10 | #X msg 253 64 reset 0 \$1; 11 | #X obj 199 255 f 440; 12 | #X obj 119 113 abl_link~ 1 0 4 140; 13 | #X obj 154 255 f 880; 14 | #X obj 154 211 select 0; 15 | #X obj 154 234 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 16 | -1 -1; 17 | #X obj 199 233 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 18 | -1 -1; 19 | #X msg 18 65 connect \$1; 20 | #X obj 259 250 print num_peers; 21 | #X obj 259 228 r #abl_link_num_peers; 22 | #X obj 120 190 t b f; 23 | #X obj 93 41 r tempo; 24 | #X obj 156 41 r resolution; 25 | #X obj 253 41 r quantum; 26 | #X obj 18 40 r connect; 27 | #X obj 291 144 s tempoOut; 28 | #X msg 327 62 offset \$1; 29 | #X obj 327 41 r offset; 30 | #X obj 80 141 s step; 31 | #X obj 136 163 s phase; 32 | #X obj 204 163 s beatTime; 33 | #N canvas 520 184 114 148 filter 0; 34 | #X obj 6 5 inlet; 35 | #X obj 6 25 expr $f1 * 10; 36 | #X obj 6 65 expr $f1 / 10; 37 | #X obj 6 45 int; 38 | #X obj 6 85 change; 39 | #X obj 6 107 outlet; 40 | #X connect 0 0 1 0; 41 | #X connect 1 0 3 0; 42 | #X connect 2 0 4 0; 43 | #X connect 3 0 2 0; 44 | #X connect 4 0 5 0; 45 | #X restore 136 142 pd filter; 46 | #N canvas 501 198 114 148 filter 0; 47 | #X obj 6 5 inlet; 48 | #X obj 6 25 expr $f1 * 10; 49 | #X obj 6 65 expr $f1 / 10; 50 | #X obj 6 45 int; 51 | #X obj 6 85 change; 52 | #X obj 6 107 outlet; 53 | #X connect 0 0 1 0; 54 | #X connect 1 0 3 0; 55 | #X connect 2 0 4 0; 56 | #X connect 3 0 2 0; 57 | #X connect 4 0 5 0; 58 | #X restore 204 142 pd filter; 59 | #X connect 0 0 1 1; 60 | #X connect 1 0 5 0; 61 | #X connect 3 0 1 0; 62 | #X connect 4 0 3 0; 63 | #X connect 4 0 3 0; 64 | #X connect 5 0 2 0; 65 | #X connect 5 0 2 1; 66 | #X connect 6 0 10 0; 67 | #X connect 7 0 10 0; 68 | #X connect 8 0 10 0; 69 | #X connect 9 0 0 0; 70 | #X connect 10 0 18 0; 71 | #X connect 10 0 26 0; 72 | #X connect 10 1 29 0; 73 | #X connect 10 2 30 0; 74 | #X connect 10 3 23 0; 75 | #X connect 11 0 0 0; 76 | #X connect 12 0 13 0; 77 | #X connect 12 1 14 0; 78 | #X connect 13 0 11 0; 79 | #X connect 14 0 9 0; 80 | #X connect 15 0 10 0; 81 | #X connect 17 0 16 0; 82 | #X connect 18 0 4 0; 83 | #X connect 18 1 12 0; 84 | #X connect 19 0 6 0; 85 | #X connect 20 0 7 0; 86 | #X connect 21 0 8 0; 87 | #X connect 22 0 15 0; 88 | #X connect 24 0 10 0; 89 | #X connect 25 0 24 0; 90 | #X connect 29 0 27 0; 91 | #X connect 30 0 28 0; 92 | -------------------------------------------------------------------------------- /AblLinkSample/app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /AblLinkSample/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /AblLinkSample/app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /AblLinkSample/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | AblLinkSample 3 | 4 | -------------------------------------------------------------------------------- /AblLinkSample/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /AblLinkSample/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | google() 6 | mavenCentral() 7 | } 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:7.2.0' 10 | } 11 | } 12 | 13 | allprojects { 14 | repositories { 15 | google() 16 | mavenCentral() 17 | jcenter() // FIXME: com.noisepages.nettoyeur:midi 18 | } 19 | } 20 | 21 | task clean(type: Delete) { 22 | delete rootProject.buildDir 23 | } 24 | 25 | ext { 26 | minSdkVersion = 17 27 | compileSdkVersion = 32 28 | buildToolsVersion = '32.0.0' 29 | androidxLegacySupportVersion = '1.0.0' 30 | ndkVersion = '21.4.7075529' // https://developer.android.com/ndk/downloads#lts-downloads 31 | } 32 | -------------------------------------------------------------------------------- /AblLinkSample/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | android.useAndroidX=true 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | -------------------------------------------------------------------------------- /AblLinkSample/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/libpd/abl_link/25642d0c80edd234b2f2eecd98065f9f0232058f/AblLinkSample/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /AblLinkSample/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /AblLinkSample/gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | # 21 | # Gradle start up script for POSIX generated by Gradle. 22 | # 23 | # Important for running: 24 | # 25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 26 | # noncompliant, but you have some other compliant shell such as ksh or 27 | # bash, then to run this script, type that shell name before the whole 28 | # command line, like: 29 | # 30 | # ksh Gradle 31 | # 32 | # Busybox and similar reduced shells will NOT work, because this script 33 | # requires all of these POSIX shell features: 34 | # * functions; 35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 37 | # * compound commands having a testable exit status, especially «case»; 38 | # * various built-in commands including «command», «set», and «ulimit». 39 | # 40 | # Important for patching: 41 | # 42 | # (2) This script targets any POSIX shell, so it avoids extensions provided 43 | # by Bash, Ksh, etc; in particular arrays are avoided. 44 | # 45 | # The "traditional" practice of packing multiple parameters into a 46 | # space-separated string is a well documented source of bugs and security 47 | # problems, so this is (mostly) avoided, by progressively accumulating 48 | # options in "$@", and eventually passing that to Java. 49 | # 50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 52 | # see the in-line comments for details. 53 | # 54 | # There are tweaks for specific operating systems such as AIX, CygWin, 55 | # Darwin, MinGW, and NonStop. 56 | # 57 | # (3) This script is generated from the Groovy template 58 | # https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 59 | # within the Gradle project. 60 | # 61 | # You can find Gradle at https://github.com/gradle/gradle/. 62 | # 63 | ############################################################################## 64 | 65 | # Attempt to set APP_HOME 66 | 67 | # Resolve links: $0 may be a link 68 | app_path=$0 69 | 70 | # Need this for daisy-chained symlinks. 71 | while 72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 73 | [ -h "$app_path" ] 74 | do 75 | ls=$( ls -ld "$app_path" ) 76 | link=${ls#*' -> '} 77 | case $link in #( 78 | /*) app_path=$link ;; #( 79 | *) app_path=$APP_HOME$link ;; 80 | esac 81 | done 82 | 83 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit 84 | 85 | APP_NAME="Gradle" 86 | APP_BASE_NAME=${0##*/} 87 | 88 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 89 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 90 | 91 | # Use the maximum available, or set MAX_FD != -1 to use that value. 92 | MAX_FD=maximum 93 | 94 | warn () { 95 | echo "$*" 96 | } >&2 97 | 98 | die () { 99 | echo 100 | echo "$*" 101 | echo 102 | exit 1 103 | } >&2 104 | 105 | # OS specific support (must be 'true' or 'false'). 106 | cygwin=false 107 | msys=false 108 | darwin=false 109 | nonstop=false 110 | case "$( uname )" in #( 111 | CYGWIN* ) cygwin=true ;; #( 112 | Darwin* ) darwin=true ;; #( 113 | MSYS* | MINGW* ) msys=true ;; #( 114 | NONSTOP* ) nonstop=true ;; 115 | esac 116 | 117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 118 | 119 | 120 | # Determine the Java command to use to start the JVM. 121 | if [ -n "$JAVA_HOME" ] ; then 122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 123 | # IBM's JDK on AIX uses strange locations for the executables 124 | JAVACMD=$JAVA_HOME/jre/sh/java 125 | else 126 | JAVACMD=$JAVA_HOME/bin/java 127 | fi 128 | if [ ! -x "$JAVACMD" ] ; then 129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 130 | 131 | Please set the JAVA_HOME variable in your environment to match the 132 | location of your Java installation." 133 | fi 134 | else 135 | JAVACMD=java 136 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 137 | 138 | Please set the JAVA_HOME variable in your environment to match the 139 | location of your Java installation." 140 | fi 141 | 142 | # Increase the maximum file descriptors if we can. 143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 144 | case $MAX_FD in #( 145 | max*) 146 | MAX_FD=$( ulimit -H -n ) || 147 | warn "Could not query maximum file descriptor limit" 148 | esac 149 | case $MAX_FD in #( 150 | '' | soft) :;; #( 151 | *) 152 | ulimit -n "$MAX_FD" || 153 | warn "Could not set maximum file descriptor limit to $MAX_FD" 154 | esac 155 | fi 156 | 157 | # Collect all arguments for the java command, stacking in reverse order: 158 | # * args from the command line 159 | # * the main class name 160 | # * -classpath 161 | # * -D...appname settings 162 | # * --module-path (only if needed) 163 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 164 | 165 | # For Cygwin or MSYS, switch paths to Windows format before running java 166 | if "$cygwin" || "$msys" ; then 167 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 168 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 169 | 170 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 171 | 172 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 173 | for arg do 174 | if 175 | case $arg in #( 176 | -*) false ;; # don't mess with options #( 177 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 178 | [ -e "$t" ] ;; #( 179 | *) false ;; 180 | esac 181 | then 182 | arg=$( cygpath --path --ignore --mixed "$arg" ) 183 | fi 184 | # Roll the args list around exactly as many times as the number of 185 | # args, so each arg winds up back in the position where it started, but 186 | # possibly modified. 187 | # 188 | # NB: a `for` loop captures its iteration list before it begins, so 189 | # changing the positional parameters here affects neither the number of 190 | # iterations, nor the values presented in `arg`. 191 | shift # remove old arg 192 | set -- "$@" "$arg" # push replacement arg 193 | done 194 | fi 195 | 196 | # Collect all arguments for the java command; 197 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of 198 | # shell script including quotes and variable substitutions, so put them in 199 | # double quotes to make sure that they get re-expanded; and 200 | # * put everything else in single quotes, so that it's not re-expanded. 201 | 202 | set -- \ 203 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 204 | -classpath "$CLASSPATH" \ 205 | org.gradle.wrapper.GradleWrapperMain \ 206 | "$@" 207 | 208 | # Use "xargs" to parse quoted args. 209 | # 210 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 211 | # 212 | # In Bash we could simply go: 213 | # 214 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 215 | # set -- "${ARGS[@]}" "$@" 216 | # 217 | # but POSIX shell has neither arrays nor command substitution, so instead we 218 | # post-process each arg (as a line of input to sed) to backslash-escape any 219 | # character that might be a shell metacharacter, then use eval to reverse 220 | # that process (while maintaining the separation between arguments), and wrap 221 | # the whole thing up as a single "set" statement. 222 | # 223 | # This will of course break if any of these variables contains a newline or 224 | # an unmatched quote. 225 | # 226 | 227 | eval "set -- $( 228 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 229 | xargs -n1 | 230 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 231 | tr '\n' ' ' 232 | )" '"$@"' 233 | 234 | exec "$JAVACMD" "$@" 235 | -------------------------------------------------------------------------------- /AblLinkSample/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /AblLinkSample/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':PdCore' 2 | project(':PdCore').projectDir = new File(settingsDir, '../../pd-for-android/PdCore') -------------------------------------------------------------------------------- /CHANGES.txt: -------------------------------------------------------------------------------- 1 | v0.6: 2021 May 25 2 | 3 | * updated to Link 3.0.3 4 | * updated to pd-lib-builder 0.6.0 5 | * fixed Windows build (Lucas Cordiviola) 6 | 7 | v0.5: 2020 Feb 18 8 | 9 | abl_link~ accepts an [offset( message that allows users to improve 10 | synchronization on platforms that don't report their latency. This message has 11 | been around for a long time, but it was undocumented because the Link 12 | specification frowns upon exposed configuration settings. In practice, however, 13 | this feature is hard to avoid, and so we make it official by documenting it. 14 | 15 | v0.4: 2018 Mar 05 16 | 17 | This release updates the code of abl_link~ so that it builds with Link 3.0, and 18 | it adds support for setting and receiving the play state of the Link session; 19 | see help patch for details. 20 | 21 | v0.3: 2016 Nov 16 22 | 23 | Moved to GitHub and integrated dependencies as submodules. Various build 24 | improvements. Added latency handling & internal offset message. Improved help 25 | files. Now using 3-clause BSD license. 26 | 27 | v0.2: 2016 Oct 28 | 29 | pre-git beta 30 | 31 | v0.1: 2016 Oct 32 | 33 | pre-git alpha 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This software is copyrighted by Google Inc, Tal Kirshboim, and others. The 2 | following terms (the "Standard Improved BSD License") apply to all files 3 | associated with the software unless explicitly disclaimed in individual files: 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | 1. Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 2. Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following 13 | disclaimer in the documentation and/or other materials provided 14 | with the distribution. 15 | 3. The name of the author may not be used to endorse or promote 16 | products derived from this software without specific prior 17 | written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY 20 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 22 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 23 | BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 25 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 27 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 29 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30 | THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # abl_link~ 2 | 3 | Ableton Link 3.0 integration for Pd. 4 | 5 | ## Desktop version 6 | 7 | Users: 8 | 9 | * Simply install `abl_link~` from deken and check out the help patch. 10 | 11 | Developers: 12 | * Clone this repository recursively so you'll have all submodules: `git clone --recursive https://github.com/libpd/abl_link.git` 13 | * Build the external by saying `make` in the `external` directory and install it like any other external. 14 | * Run the metronome patch in `external` to check the timing of the external against the LinkHut sample app. 15 | 16 | ## Android version 17 | 18 | In order to build and run the sample app, you need to be set up for native 19 | Android development. If you'd like to add Link to your own app, check out the 20 | README in the `android` directory. 21 | 22 | * Set up your build environment following these instructions: https://developer.android.com/studio/projects/add-native-code.html 23 | * Clone Pd for Android : https://github.com/libpd/pd-for-android 24 | * Clone this repository into the same parent directory as Pd for Android. (You can put it somewhere else, but then you'll have to adjust `android/CMakeLists.txt` and `AblLinkSample/settings.gradle` accordingly.) 25 | * Now you should be able to build and run the sample app. 26 | 27 | ## iOS version 28 | 29 | The iOS version is here: https://github.com/libpd/pd-for-ios 30 | -------------------------------------------------------------------------------- /android/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.6) 2 | 3 | set(PD_CORE ${CMAKE_CURRENT_LIST_DIR}/../../pd-for-android/PdCore/src/main) 4 | 5 | add_library(pd SHARED IMPORTED) 6 | set_target_properties(pd PROPERTIES IMPORTED_LOCATION 7 | ${PD_CORE}/libs/${ANDROID_ABI}/libpd.so) 8 | 9 | include_directories(${PD_CORE}/jni/libpd/pure-data/src) 10 | include_directories(../external/android-ifaddrs) 11 | include_directories(../external/link/include) 12 | include_directories(../external/link/modules/asio-standalone/asio/include) 13 | 14 | add_library(abl_link_tilde SHARED 15 | ../external/android-ifaddrs/ifaddrs.cpp ../external/abl_link_instance.cpp 16 | ../external/abl_link~.cpp) 17 | target_compile_definitions(abl_link_tilde PRIVATE 18 | ANDROID=1 LINK_PLATFORM_LINUX=1 PD=1 ABL_LINK_OFFSET_MS=23) 19 | set(CMAKE_CXX_FLAGS "-std=c++11 -Wno-multichar -fexceptions -Werror") 20 | 21 | target_link_libraries(abl_link_tilde pd) 22 | -------------------------------------------------------------------------------- /android/README.md: -------------------------------------------------------------------------------- 1 | # abl_link~ for Android 2 | 3 | While this solution is about using the abl_link~ external with Pd for Android, it should contain enough information to allow developers to integrate Link into Android apps that don't use Pd. 4 | 5 | ## How to build abl_link~ for Android 6 | 7 | * Build and run the AblLinkSample app, just to make sure that your development setup is sound. 8 | * Add `` to your manifest. Without it, there won't be any obvious failures, but abl_link~ will not connect to other Link instances. 9 | * Link gradle to `CMakeLists.txt` in this directory following these instructions: https://developer.android.com/studio/projects/add-native-code.html#link-gradle 10 | * Add `ndk { abiFilters 'x86', 'armeabi', 'armeabi-v7a' }` to the `defaultConfig` section of the `build.gradle` file of your module. 11 | * Now the abl_link~ external should build within your project. You can use it like any other locally built external. If you use libpd by way of PdService, then the external will already be on Pd's search path, and so patches can use it without further ado. 12 | 13 | ## What's going on here? 14 | 15 | * Link uses ifaddrs, which is not part of the stable Android APIs. So, I looked around and decided to borrow the implementation of ifaddrs that comes with the Android version of Chromium, which is BSD-licensed and IPv6 aware. It's included here, in `external/android-ifaddrs`. 16 | * Other than that, it just took a few straightforward compiler flags to make this work. They're in `CMakeLists.txt`. 17 | * For purposes other than libpd, the build file should be straightforward to adjust. Good luck! 18 | 19 | -------------------------------------------------------------------------------- /external/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile to build Ableton Link external for Pure Data. 2 | # 3 | # Needs Makefile.pdlibbuilder as helper makefile for platform-dependent build 4 | # settings and rules. 5 | # 6 | # use : make pdincludepath=/path/to/pure-data/src/ 7 | # 8 | # The following command will build the external and install the distributable 9 | # files into a subdirectory called build/abl_link (useful to package later with deken) : 10 | # 11 | # make install pdincludepath=../pure-data/src/ objectsdir=./build 12 | 13 | lib.name = abl_link~ 14 | 15 | abl_link~.class.sources = abl_link~.cpp abl_link_instance.cpp 16 | 17 | # all extra files to be included in binary distribution of the library 18 | datafiles = abl_link~-help.pd ../LICENSE metronome.pd 19 | 20 | LINK_INCLUDES ?= ./link/include 21 | ASIO_INCLUDES ?= ./link/modules/asio-standalone/asio/include 22 | 23 | cflags = -std=c++11 -I$(LINK_INCLUDES) \ 24 | -I$(ASIO_INCLUDES) -Wno-multichar 25 | 26 | suppress-wunused = yes 27 | 28 | define forLinux 29 | cflags += -DLINK_PLATFORM_LINUX=1 30 | endef 31 | 32 | define forDarwin 33 | cflags += -DLINK_PLATFORM_MACOSX=1 -mmacosx-version-min=10.9 34 | endef 35 | 36 | 37 | define forWindows 38 | cflags += -DLINK_PLATFORM_WINDOWS=1 39 | ldlibs += -lws2_32 -liphlpapi -static -lpthread 40 | endef 41 | 42 | PDLIBBUILDER_DIR ?= . 43 | include $(PDLIBBUILDER_DIR)/Makefile.pdlibbuilder 44 | 45 | VERSION = $(shell git describe) 46 | 47 | update-pdlibbuilder: 48 | curl https://raw.githubusercontent.com/pure-data/pd-lib-builder/master/Makefile.pdlibbuilder > ./Makefile.pdlibbuilder 49 | 50 | deken-source: 51 | @rm -rf build_src 52 | @mkdir -p build_src/abl_link~ 53 | @cp $(abl_link~.class.sources) \ 54 | $(patsubst %.cpp, %.hpp, $(abl_link~.class.sources)) \ 55 | $(datafiles) Makefile.pdlibbuilder metronome.pd Makefile \ 56 | build_src/abl_link~ 57 | cd build_src/ ; deken upload -v $(VERSION) abl_link~ 58 | 59 | deken-binary: 60 | @rm -rf build 61 | @make install objectsdir=./build 62 | cd build/ ; deken upload -v $(VERSION) abl_link~ 63 | 64 | -------------------------------------------------------------------------------- /external/Makefile.pdlibbuilder: -------------------------------------------------------------------------------- 1 | # Makefile.pdlibbuilder dated 2019-12-21 2 | version = 0.6.0 3 | 4 | # Helper makefile for Pure Data external libraries. 5 | # Written by Katja Vetter March-June 2015 for the public domain. No warranties. 6 | # Inspired by Hans Christoph Steiner's Makefile Template and Stephan Beal's 7 | # ShakeNMake. 8 | # 9 | # Grab the newest version of Makefile.pdlibbuilder from 10 | # https://github.com/pure-data/pd-lib-builder/ 11 | # 12 | # GNU make version >= 3.81 required. 13 | # 14 | # 15 | #=== characteristics =========================================================== 16 | # 17 | # 18 | # - defines build settings based on autodetected OS and architecture 19 | # - defines rules to build Pd class- or lib executables from C or C++ sources 20 | # - defines rules for libdir installation 21 | # - defines convenience targets for developer and user 22 | # - evaluates implicit dependencies for non-clean builds 23 | # 24 | # 25 | #=== basic usage =============================================================== 26 | # 27 | # 28 | # In your Makefile, define your Pd lib name and class files, and include 29 | # Makefile.pdlibbuilder at the end of the Makefile. Like so: 30 | # 31 | # ________________________________________________________________________ 32 | # 33 | # # Makefile for mylib 34 | # 35 | # lib.name = mylib 36 | # 37 | # class.sources = myclass1.c myclass2.c 38 | # 39 | # datafiles = myclass1-help.pd myclass2-help.pd README.txt LICENSE.txt 40 | # 41 | # include Makefile.pdlibbuilder 42 | # ________________________________________________________________________ 43 | # 44 | # 45 | # For files in class.sources it is assumed that class basename == source file 46 | # basename. The default target builds all classes as individual executables 47 | # with Pd's default extension for the platform. For anything more than the 48 | # most basic usage, continue reading. 49 | # 50 | # 51 | #=== list of Makefile.pdlibbuilder API variables =============================== 52 | # 53 | # 54 | # Variables available for definition in your library Makefile: 55 | # 56 | # - lib.name 57 | # - lib.setup.sources 58 | # - class.sources 59 | # - common.sources 60 | # - shared.sources 61 | # - .class.sources 62 | # - .class.ldflags 63 | # - .class.ldlibs 64 | # - cflags 65 | # - ldflags 66 | # - ldlibs 67 | # - datafiles 68 | # - datadirs 69 | # - makefiles 70 | # - makefiledirs 71 | # - externalsdir 72 | # 73 | # Optional multiline defines evaluated per operating system: 74 | # 75 | # - forLinux 76 | # - forDarwin 77 | # - forWindows 78 | # 79 | # Variables available for your makefile or make command line: 80 | # 81 | # - make-lib-executable 82 | # - suppress-wunused 83 | # 84 | # Path variables for make command line or environment: 85 | # 86 | # - PDDIR 87 | # - PDINCLUDEDIR 88 | # - PDBINDIR 89 | # - PDLIBDIR 90 | # 91 | # Standard make variables for make command line or environment: 92 | # 93 | # - CPPFLAGS 94 | # - CFLAGS 95 | # - LDFLAGS 96 | # - CC 97 | # - CXX 98 | # - INSTALL 99 | # - STRIP 100 | # - DESTDIR 101 | # 102 | # Optional user variables for make command line or environment: 103 | # 104 | # - PLATFORM 105 | # 106 | # Deprecated path variables: 107 | # 108 | # - pdincludepath 109 | # - pdbinpath 110 | # - objectsdir 111 | # 112 | # 113 | #=== descriptions of Makefile.pdlibbuilder API variables ======================= 114 | # 115 | # 116 | # lib.name: 117 | # Name of the library directory as it will be installed / distributed. Also the 118 | # name of the lib executable in the case where all classes are linked into 119 | # a single binary. 120 | # 121 | # lib.setup.sources: 122 | # Source file(s) (C or C++) which must be compiled only when linking all classes 123 | # into a single lib binary. 124 | # 125 | # class.sources: 126 | # All sources files (C or C++) for which the condition holds that 127 | # class name == source file basename. 128 | # 129 | # .class.sources: 130 | # Source file(s) (C or C++) specific to class . Use this for 131 | # multiple-source classes or when class name != source file basename. 132 | # 133 | # common.sources: 134 | # Source file(s) which must be statically linked to each class in the library. 135 | # 136 | # shared.sources: 137 | # Source file(s) (C or C++) to build a shared dynamic link lib, to be linked 138 | # with all class executables. 139 | # 140 | # cflags, ldflags, ldlibs: 141 | # Define cflags (preprocessor&compiler), ldflags (linker) and ldlibs (dynamic 142 | # link libs) for the whole library. These flags are added to platform-specific 143 | # flags defined by Makefile.pdlibbuilder. 144 | # 145 | # .class.ldflags and .class.ldlibs: 146 | # Define ldflags resp. ldlibs specific to class . These flags are 147 | # added to platform-specific flags defined by Makefile.pdlibbuilder, and flags 148 | # defined in your Makefile for the whole library. Note: cflags can not be 149 | # defined per class in the current implementation. 150 | # 151 | # datafiles and datadirs: 152 | # All extra files you want to include in binary distributions of the 153 | # library: abstractions and help patches, example patches, meta patch, readme 154 | # and license texts, manuals, sound files, etcetera. Use 'datafiles' for all 155 | # files that should go into your lib rootdir and 'datadirs' for complete 156 | # directories you want to copy from source to distribution. 157 | # 158 | # forLinux, forDarwin, forWindows: 159 | # Shorthand for 'variable definitions for Linux only' etc. Use like: 160 | # define forLinux 161 | # cflags += -DLINUX 162 | # class.sources += linuxthing.c 163 | # endef 164 | # 165 | # makefiles and makefiledirs: 166 | # Extra makefiles or directories with makefiles that should be made in sub-make 167 | # processes. 168 | # 169 | # make-lib-executable: 170 | # When this variable is defined 'yes' in your makefile or as command argument, 171 | # Makefile.pdlibbuilder will try to build all classes into a single library 172 | # executable (but it will force exit if lib.setup.sources is undefined). 173 | # If your makefile defines 'make-lib-executable=yes' as the library default, 174 | # this can still be overridden with 'make-lib-executable=no' as command argument 175 | # to build individual class executables (the Makefile.pdlibbuilder default.) 176 | # 177 | # suppress-wunused: 178 | # When this variable is defined ('yes' or any other value), -Wunused-variable, 179 | # -Wunused-parameter, -Wunused-value and -Wunused-function are suppressed, 180 | # but the other warnings from -Wall are retained. 181 | # 182 | # PDDIR: 183 | # Root directory of 'portable' pd package. When defined, PDINCLUDEDIR and 184 | # PDBINDIR will be evaluated as $(PDDIR)/src and $(PDDIR)/bin. 185 | # 186 | # PDINCLUDEDIR: 187 | # Directory where Pd API m_pd.h should be found, and other Pd header files. 188 | # Overrides the default search path. 189 | # 190 | # PDBINDIR: 191 | # Directory where pd.dll should be found for linking (Windows only). Overrides 192 | # the default search path. 193 | # 194 | # PDLIBDIR: 195 | # Root directory for installation of Pd library directories. Overrides the 196 | # default install location. 197 | # 198 | # DESTDIR: 199 | # Prepended path component for staged install. 200 | # 201 | # PLATFORM: 202 | # Target platform for cross compilation in the form of GNU triplet: 203 | # cpu-vendor-os. Example: x86_64-w64-mingw32. This specifies the tool chain that 204 | # pdlibbuilder will use, if installed and locatable. System and architecture 205 | # will then be autodefined accordingly. In most cases no other variables need to 206 | # be overridden. 207 | # 208 | # CPPFLAGS: 209 | # Preprocessor flags which are not strictly required for building. 210 | # 211 | # CFLAGS: 212 | # Compiler flags which are not strictly required for building. Compiler flags 213 | # defined by Makefile.pdlibbuilder for warning, optimization and architecture 214 | # specification are overriden by CFLAGS. 215 | # 216 | # LDFLAGS: 217 | # Linker flags which are not strictly required for building. Linker flags 218 | # defined by Makefile.pdlibbuilder for architecture specification are overriden 219 | # by LDFLAGS. 220 | # 221 | # CC and CXX: 222 | # C and C++ compiler programs as defined in your build environment. 223 | # 224 | # INSTALL 225 | # Definition of install program. 226 | # 227 | # STRIP 228 | # Name of strip program. Default 'strip' can be overridden in cross compilation 229 | # environments. 230 | # 231 | # objectsdir: 232 | # Root directory for installation of Pd library directories, like PDLIBDIR but 233 | # not overridable by environment. Supported for compatibility with pd-extended 234 | # central makefile, but deprecated otherwise. 235 | # 236 | # pdincludepath, pdbinpath: 237 | # As PDINCLUDEDIR and PDBINDIR but not overridable by environment. Deprecated 238 | # as user variables. 239 | # 240 | # 241 | #=== paths ===================================================================== 242 | # 243 | # 244 | # Source files in directories other than current working directory must be 245 | # prefixed with their relative path. Do not rely on VPATH or vpath. 246 | # Object (.o) files are built in the directory of their source files. 247 | # Executables are built in current working directory. 248 | # 249 | # Default search path for m_pd.h and other API header files is platform 250 | # dependent, and overridable by PDINCLUDEDIR: 251 | # 252 | # Linux: /usr/include/pd 253 | # 254 | # OSX: /Applications/Pd*.app/Contents/Resources/src 255 | # 256 | # Windows: %PROGRAMFILES%/Pd/src 257 | # %PROGRAMFILES(X86)%/Pd/src (32 bit builds on 64 bit Windows) 258 | # 259 | # Default search path for binary pd.dll (Windows), overridable by PDBINDIR 260 | # 261 | # %PROGRAMFILES%/Pd/bin 262 | # %PROGRAMFILES(X86)%/Pd/bin (32 bit builds on 64 bit Windows) 263 | # 264 | # Default location to install pd libraries is platform dependent, and 265 | # overridable by PDLIBDIR: 266 | # 267 | # Linux: /usr/local/lib/pd-externals 268 | # OSX: ~/Library/Pd 269 | # Windows: %APPDATA%/Pd 270 | # 271 | # https://puredata.info/docs/faq/how-do-i-install-externals-and-help-files 272 | # The rationale for not installing to ~/pd-externals by default on Linux 273 | # is that some people share the home dir between 32 and 64 bit installations. 274 | # 275 | # 276 | #=== targets =================================================================== 277 | # 278 | # 279 | # all: build $(executables) plus optional post target 280 | # post: target to build after $(executables) 281 | # alldebug: build all with -g option turned on for debug symbols 282 | # : force clean build of an individual class 283 | # .pre: make preprocessor output file in current working directory 284 | # .lst: make asm/source output file in current working directory 285 | # 286 | # install: install executables and data files 287 | # clean: remove build products from source tree 288 | # 289 | # help: print help text 290 | # vars: print makefile variables 291 | # allvars: print all variables 292 | # depend: print generated prerequisites 293 | # dumpmachine: print compiler output of option '-dumpmachine' 294 | # coffee: dummy target 295 | # 296 | # Variable $(executables) expands to class executables plus optional shared lib, 297 | # or alternatively to single lib executable when make-lib-executable=true. 298 | # Targets pre and post can be defined by library makefile. Make sure to include 299 | # Makefile.pdlibbuilder first so default target all will not be redefined. 300 | # 301 | # 302 | #=== Pd-extended libdir concept ================================================ 303 | # 304 | # 305 | # For libdir layout as conceived by Hans-Christoph Steiner, see: 306 | # 307 | # https://puredata.info/docs/developer/Libdir 308 | # 309 | # Files README.txt, LICENSE.txt and -meta.pd are part of the libdir 310 | # convention. Help patches for each class and abstraction are supposed to be 311 | # available. Makefile.pdlibbuilder does not force the presence of these files 312 | # however. It does not automatically include such files in libdir installations. 313 | # Data files you want to include in distributions must be defined explicitly in 314 | # your Makefile. 315 | # 316 | # 317 | #=== Makefile.pdlibbuilder syntax conventions ================================== 318 | # 319 | # 320 | # Makefile.pdlibbuilder variable names are lower case. Default make variables, 321 | # environment variables, and standard user variables (CC, CXX, CFLAGS, DESTDIR) 322 | # are upper case. Use target 'allvars' to print all variables and their values. 323 | # 324 | # 'Fields' in data variables are separated by dots, like in 'foo.class.sources'. 325 | # Words in variables expressing a function or command are separated by dashes, 326 | # like in 'make-lib-executable'. 327 | # 328 | # 329 | #=== useful make options ======================================================= 330 | # 331 | # 332 | # Use 'make -d ' to print debug details of the make process. 333 | # Use 'make -p ' to print make's database. 334 | # 335 | # 336 | #=== TODO ====================================================================== 337 | # 338 | # 339 | # - decide whether to use -static-libgcc or shared dll in MinGW 340 | # - cygwin support 341 | # - android support 342 | # - figure out how to handle '$' in filenames 343 | # - add makefile template targets dpkg-source dist libdir distclean tags? 344 | # 345 | # 346 | #=== end of documentation sections ============================================= 347 | # 348 | # 349 | ################################################################################ 350 | ################################################################################ 351 | ################################################################################ 352 | 353 | 354 | # GNU make version 3.81 (2006) or higher is required because of the following: 355 | # - function 'info' 356 | # - variable '.DEFAULT_GOAL' 357 | 358 | # force exit when make version is < 3.81 359 | ifneq ($(firstword $(sort 3.81 $(MAKE_VERSION))), 3.81) 360 | $(error GNU make version 3.81 or higher is required) 361 | endif 362 | 363 | # Relative path to externals root dir in multi-lib source tree like 364 | # pd-extended SVN. Default is parent of current working directory. May be 365 | # defined differently in including makefile. 366 | externalsdir ?= .. 367 | 368 | # variable you can use to check if Makefile.pdlibbuilder is already included 369 | Makefile.pdlibbuilder = true 370 | 371 | 372 | ################################################################################ 373 | ### target platform detection ################################################## 374 | ################################################################################ 375 | 376 | 377 | #=== target platform =========================================================== 378 | 379 | 380 | # PLATFORM: optional user variable to define target platform for cross 381 | # compilation. Redefine build tools accordingly. PLATFORM should match 382 | # the exact target prefix of tools present in $PATH, like x86_64-w64-mingw32, 383 | # x86_64-apple-darwin12 etc. Tool definitions are exported to ensure submakes 384 | # will get the same. 385 | 386 | ifneq ($(PLATFORM),) 387 | ifneq ($(findstring darwin, $(PLATFORM)),) 388 | export CC = $(PLATFORM)-cc 389 | export CXX = $(PLATFORM)-c++ 390 | export CPP = $(PLATFORM)-cc 391 | else 392 | export CC = $(PLATFORM)-gcc 393 | export CXX = $(PLATFORM)-g++ 394 | export CPP = $(PLATFORM)-cpp 395 | endif 396 | STRIP = $(PLATFORM)-strip 397 | endif 398 | 399 | # Let (native or cross-) compiler report target triplet and isolate individual 400 | # words therein to facilitate later processing. 401 | target.triplet := $(subst -, ,$(shell $(CC) -dumpmachine)) 402 | 403 | 404 | #=== operating system ========================================================== 405 | 406 | 407 | # The following systems are defined: Linux, Darwin, Windows. GNU and 408 | # GNU/kFreeBSD are treated as Linux to get the same options. 409 | 410 | ifneq ($(filter linux gnu% kfreebsd, $(target.triplet)),) 411 | system = Linux 412 | endif 413 | 414 | ifneq ($(filter darwin%, $(target.triplet)),) 415 | system = Darwin 416 | endif 417 | 418 | ifneq ($(filter mingw% cygwin%, $(target.triplet)),) 419 | system = Windows 420 | endif 421 | 422 | # evaluate possible system-specific multiline defines from library makefile 423 | $(eval $(for$(system))) 424 | 425 | 426 | # TODO: Cygwin, Android 427 | 428 | 429 | #=== architecture ============================================================== 430 | 431 | 432 | # The following CPU names can be processed by pdlibbuilder: 433 | # i*86 Intel 32 bit 434 | # x86_64 Intel 64 bit 435 | # arm ARM 32 bit 436 | # aarch64 ARM 64 bit 437 | 438 | target.arch := $(firstword $(target.triplet)) 439 | 440 | 441 | ################################################################################ 442 | ### variables per platform ##################################################### 443 | ################################################################################ 444 | 445 | 446 | #=== flags per architecture ==================================================== 447 | 448 | 449 | # Set architecture-dependent cflags, mainly for Linux. For Mac and Windows, 450 | # arch.c.flags are overriden below. To see gcc's default architecture flags: 451 | # $ gcc -Q --help=target 452 | 453 | # ARMv6: Raspberry Pi 1st gen, not detectable from target.arch 454 | ifeq ($(shell uname), armv6l) 455 | arch.c.flags = -march=armv6 -mfpu=vfp -mfloat-abi=hard 456 | 457 | # ARMv7: Beagle, Udoo, RPi2 etc. 458 | else ifeq ($(target.arch), arm) 459 | arch.c.flags = -march=armv7-a -mfpu=vfpv3 -mfloat-abi=hard 460 | 461 | # ARMv8 64 bit, not tested yet 462 | else ifeq ($(target.arch), aarch64) 463 | arch.c.flags = -mcpu=cortex-a53 464 | 465 | # Intel 32 bit, build with SSE and SSE2 instructions 466 | else ifneq ($(filter i%86, $(target.arch)),) 467 | arch.c.flags = -march=pentium4 -mfpmath=sse -msse -msse2 468 | 469 | # Intel/AMD 64 bit, build with SSE, SSE2 and SSE3 instructions 470 | else ifeq ($(target.arch), x86_64) 471 | arch.c.flags = -march=core2 -mfpmath=sse -msse -msse2 -msse3 472 | 473 | # if none of the above architectures detected 474 | else 475 | arch.c.flags = 476 | endif 477 | 478 | 479 | #=== flags and paths for Linux ================================================= 480 | 481 | 482 | ifeq ($(system), Linux) 483 | prefix = /usr/local 484 | libdir := $(prefix)/lib 485 | pkglibdir = $(libdir)/pd-externals 486 | pdincludepath := $(wildcard /usr/include/pd) 487 | extension = pd_linux 488 | cpp.flags := -DUNIX 489 | c.flags := -fPIC 490 | c.ldflags := -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags 491 | c.ldlibs := -lc -lm 492 | cxx.flags := -fPIC -fcheck-new 493 | cxx.ldflags := -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags 494 | cxx.ldlibs := -lc -lm -lstdc++ 495 | shared.extension = so 496 | shared.ldflags = -rdynamic -fPIC -shared -Wl,-soname,$(shared.lib) 497 | endif 498 | 499 | 500 | #=== flags and paths for Darwin ================================================ 501 | 502 | 503 | # LLVM-clang doesn't support -fcheck-new, therefore this flag is only used when 504 | # compiling with g++. 505 | 506 | ifeq ($(system), Darwin) 507 | pkglibdir = $(HOME)/Library/Pd 508 | pdincludepath := $(firstword $(wildcard \ 509 | /Applications/Pd*.app/Contents/Resources/src)) 510 | extension = pd_darwin 511 | cpp.flags := -DUNIX -DMACOSX -I /sw/include 512 | c.flags := 513 | c.ldflags := -undefined suppress -flat_namespace -bundle 514 | c.ldlibs := -lc 515 | cxx.ldflags := -undefined suppress -flat_namespace -bundle 516 | cxx.ldlibs := -lc 517 | shared.extension = dylib 518 | shared.ldflags = -dynamiclib -undefined dynamic_lookup \ 519 | -install_name @loader_path/$(shared.lib) \ 520 | -compatibility_version 1 -current_version 1.0 521 | ifneq ($(filter %g++, $(CXX)),) 522 | cxx.flags := -fcheck-new 523 | endif 524 | ifeq ($(extension), d_fat) 525 | arch := i386 x86_64 526 | else 527 | arch := $(target.arch) 528 | endif 529 | ifneq ($(filter -mmacosx-version-min=%, $(cflags)),) 530 | version.flag := $(filter -mmacosx-version-min=%, $(cflags)) 531 | else 532 | version.flag = -mmacosx-version-min=10.6 533 | endif 534 | arch.c.flags := $(addprefix -arch , $(arch)) $(version.flag) 535 | arch.ld.flags := $(arch.c.flags) 536 | endif 537 | 538 | 539 | #=== flags and paths for Windows =============================================== 540 | 541 | 542 | # Standard paths on Windows contain spaces, and GNU make functions treat such 543 | # paths as lists, with unintended effects. Therefore we must use shell function 544 | # ls instead of make's wildcard when probing for a path, and use double quotes 545 | # when specifying a path in a command argument. 546 | 547 | # Default paths in Mingw / Mingw-w64 environments. 'PROGRAMFILES' is standard 548 | # location for builds with native architecture, 'ProgramFiles(x86)' for i686 549 | # builds on x86_64 Windows (detection method by Lucas Cordiviola). Curly braces 550 | # required because of parentheses in variable name. 551 | ifeq ($(system), Windows) 552 | pkglibdir := $(APPDATA)/Pd 553 | ifeq ($(target.arch), i686) 554 | programfiles := ${ProgramFiles(x86)} 555 | else 556 | programfiles := $(PROGRAMFILES) 557 | endif 558 | pdbinpath := $(programfiles)/Pd/bin 559 | pdincludepath := $(programfiles)/Pd/src 560 | endif 561 | 562 | # Store default path to pd.dll in PDBINDIR if the latter is not user-defined. 563 | # For include path this is done in the platform-independent paths section below, 564 | # but for PDBINDIR it is done here so ld flags can be evaluated as immediate 565 | # variables. 566 | ifeq ($(system), Windows) 567 | ifdef PDDIR 568 | PDBINDIR := $(PDDIR)/bin 569 | endif 570 | PDBINDIR ?= $(pdbinpath) 571 | endif 572 | 573 | # TODO: decide whether -mms-bitfields should be specified. 574 | ifeq ($(system), Windows) 575 | cpp.flags := -DMSW -DNT 576 | ifeq ($(target.arch), i686) 577 | arch.c.flags := -march=pentium4 -msse -msse2 -mfpmath=sse 578 | else ifeq ($(target.arch), x86_64) 579 | cpp.flags := -DMSW -DNT -DPD_LONGINTTYPE=__int64 580 | arch.c.flags := -march=core2 -msse -msse2 -msse3 -mfpmath=sse 581 | else 582 | arch.c.flags = 583 | endif 584 | extension = dll 585 | c.flags := 586 | c.ldflags := -static-libgcc -shared \ 587 | -Wl,--enable-auto-import "$(PDBINDIR)/pd.dll" 588 | c.ldlibs := 589 | cxx.flags := -fcheck-new 590 | cxx.ldflags := -static-libgcc -static-libstdc++ -shared \ 591 | -Wl,--enable-auto-import "$(PDBINDIR)/pd.dll" 592 | cxx.ldlibs := 593 | shared.extension = dll 594 | shared.ldflags := -static-libgcc -shared "$(PDBINDIR)/pd.dll" 595 | stripflags = --strip-all 596 | endif 597 | 598 | 599 | #=== paths ===================================================================== 600 | 601 | 602 | # Platform-dependent default paths are specified above, but overridable. 603 | # Path variables in upper case can be defined as make command argument or in the 604 | # environment. Variable 'objectsdir' is supported for compatibility with 605 | # the build system that pd-l2ork has inherited from pd-extended. 606 | 607 | PDINCLUDEDIR ?= $(pdincludepath) 608 | PDLIBDIR ?= $(firstword $(objectsdir) $(pkglibdir)) 609 | 610 | ifdef PDDIR 611 | PDINCLUDEDIR := $(wildcard $(PDDIR)/src) 612 | endif 613 | 614 | # base path where all components of the lib will be installed by default 615 | installpath := $(DESTDIR)$(PDLIBDIR)/$(lib.name) 616 | 617 | # check if include path contains spaces (as is often the case on Windows) 618 | # if so, store the path so we can later do checks with it 619 | pdincludepathwithspaces := $(if $(word 2, $(PDINCLUDEDIR)), $(PDINCLUDEDIR)) 620 | 621 | 622 | #=== accumulated build flags =================================================== 623 | 624 | 625 | # From GNU make docs: 'Users expect to be able to specify CFLAGS freely 626 | # themselves.' So we use CFLAGS to define options which are not strictly 627 | # required for compilation: optimizations, architecture specifications, and 628 | # warnings. CFLAGS can be safely overriden using a make command argument. 629 | # Variables cflags, ldflags and ldlibs may be defined in including makefile. 630 | 631 | optimization.flags = -O3 -ffast-math -funroll-loops -fomit-frame-pointer 632 | warn.flags = -Wall -Wextra -Wshadow -Winline -Wstrict-aliasing 633 | 634 | # suppress -Wunused-variable & Co if you don't want to clutter a build log 635 | ifdef suppress-wunused 636 | warn.flags += $(addprefix -Wno-unused-, function parameter value variable) 637 | endif 638 | 639 | CFLAGS = $(warn.flags) $(optimization.flags) $(arch.c.flags) 640 | 641 | # preprocessor flags 642 | cpp.flags := -DPD -I "$(PDINCLUDEDIR)" $(cpp.flags) $(CPPFLAGS) 643 | 644 | # flags for dependency checking (cflags from makefile may define -I options) 645 | depcheck.flags := $(cpp.flags) $(cflags) 646 | 647 | # architecture specifications for linker are overridable by LDFLAGS 648 | LDFLAGS := $(arch.ld.flags) 649 | 650 | # now add the same ld flags to shared dynamic lib 651 | shared.ldflags += $(LDFLAGS) 652 | 653 | # accumulated flags for C compiler / linker 654 | c.flags := $(cpp.flags) $(c.flags) $(cflags) $(CFLAGS) 655 | c.ldflags := $(c.ldflags) $(ldflags) $(LDFLAGS) 656 | c.ldlibs := $(c.ldlibs) $(ldlibs) 657 | 658 | # accumulated flags for C++ compiler / linker 659 | cxx.flags := $(cpp.flags) $(cxx.flags) $(cflags) $(CFLAGS) 660 | cxx.ldflags := $(cxx.ldflags) $(ldflags) $(LDFLAGS) 661 | cxx.ldlibs := $(cxx.ldlibs) $(ldlibs) 662 | 663 | 664 | ################################################################################ 665 | ### variables: library name and version ######################################## 666 | ################################################################################ 667 | 668 | 669 | # strip possibles spaces from lib.name, they mess up calculated file names 670 | lib.name := $(strip $(lib.name)) 671 | 672 | # if meta file exists, check library version 673 | metafile := $(wildcard $(lib.name)-meta.pd) 674 | 675 | ifdef metafile 676 | lib.version := $(shell sed -n \ 677 | 's|^\#X text [0-9][0-9]* [0-9][0-9]* VERSION \(.*\);|\1|p' \ 678 | $(metafile)) 679 | endif 680 | 681 | 682 | ################################################################################ 683 | ### variables: files ########################################################### 684 | ################################################################################ 685 | 686 | 687 | #=== sources =================================================================== 688 | 689 | 690 | # (re)define .class.sources using file names in class.sources 691 | 692 | define add-class-source 693 | $(notdir $(basename $v)).class.sources += $v 694 | endef 695 | 696 | $(foreach v, $(class.sources), $(eval $(add-class-source))) 697 | 698 | # derive class names from .class.sources variables 699 | sourcevariables := $(filter %.class.sources, $(.VARIABLES)) 700 | classes := $(basename $(basename $(sourcevariables))) 701 | 702 | # accumulate all source files specified in makefile 703 | classes.sources := $(sort $(foreach v, $(sourcevariables), $($v))) 704 | all.sources := $(classes.sources) $(lib.setup.sources) \ 705 | $(shared.sources) $(common.sources) 706 | 707 | 708 | #=== object files ============================================================== 709 | 710 | 711 | # construct object filenames from all C and C++ source file names 712 | classes.objects := $(addsuffix .o, $(basename $(classes.sources))) 713 | common.objects := $(addsuffix .o, $(basename $(common.sources))) 714 | shared.objects := $(addsuffix .o, $(basename $(shared.sources))) 715 | lib.setup.objects := $(addsuffix .o, $(basename $(lib.setup.sources))) 716 | all.objects = $(classes.objects) $(common.objects) $(shared.objects) \ 717 | $(lib.setup.objects) 718 | 719 | 720 | #=== executables =============================================================== 721 | 722 | 723 | # construct class executable names from class names 724 | classes.executables := $(addsuffix .$(extension), $(classes)) 725 | 726 | # Construct shared lib executable name if shared sources are defined. If 727 | # extension and shared extension are not identical, use both to facilitate co- 728 | # installation for different platforms, like .m_i386.dll and .m_amd64.dll. 729 | ifdef shared.sources 730 | ifeq ($(extension), $(shared.extension)) 731 | shared.lib = lib$(lib.name).$(shared.extension) 732 | else 733 | shared.lib = lib$(lib.name).$(extension).$(shared.extension) 734 | endif 735 | else 736 | shared.lib := 737 | endif 738 | 739 | 740 | ################################################################################ 741 | ### variables: tools ########################################################### 742 | ################################################################################ 743 | 744 | 745 | # aliases so we can later define 'compile-$1' and set 'c' or 'cxx' as argument 746 | compile-c := $(CC) 747 | compile-cxx := $(CXX) 748 | 749 | 750 | ################################################################################ 751 | ### checks ##################################################################### 752 | ################################################################################ 753 | 754 | 755 | # At this point most variables are defined. Now do some checks and info's 756 | # before rules begin. 757 | 758 | # print Makefile.pdlibbuilder version before possible termination 759 | $(info ++++ info: using Makefile.pdlibbuilder version $(version)) 760 | 761 | # Terminate if target triplet remained empty, to avoid all sorts of confusing 762 | # scenarios and spurious bugs. 763 | ifeq ($(target.triplet),) 764 | $(error Command "$(CC) -dumpmachine" did not return a target triplet, \ 765 | needed for a build. \ 766 | Is compiler "$(CC)" installed in your PATH? ($(PATH)). \ 767 | Does compiler "$(CC)" support option "-dumpmachine"?) 768 | endif 769 | 770 | # 'forward declaration' of default target, needed to do checks 771 | all: 772 | 773 | # To avoid unpredictable results, make sure the default target is not redefined 774 | # by including makefile. 775 | ifneq ($(.DEFAULT_GOAL), all) 776 | $(error Default target must be 'all'.) 777 | endif 778 | 779 | # find out which target(s) will be made 780 | ifdef MAKECMDGOALS 781 | goals := $(MAKECMDGOALS) 782 | else 783 | goals := all 784 | endif 785 | 786 | # store path to Pd API m_pd.h if it is found 787 | ifdef PDINCLUDEDIR 788 | mpdh := $(shell ls "$(PDINCLUDEDIR)/m_pd.h") 789 | endif 790 | 791 | # store path to pd.dll; if not found, ls will give a useful error 792 | ifeq ($(system), Windows) 793 | pddll := $(shell ls "$(PDBINDIR)/pd.dll") 794 | endif 795 | 796 | # when making target all, check if m_pd.h is found and print info about it 797 | ifeq ($(goals), all) 798 | $(if $(mpdh), \ 799 | $(info ++++ info: using Pd API $(mpdh)), \ 800 | $(warning Where is Pd API m_pd.h? Do 'make help' for info.)) 801 | endif 802 | 803 | # print target info 804 | $(info ++++ info: making target $(goals) $(if $(lib.name),in lib $(lib.name))) 805 | 806 | # when installing, print installpath info 807 | $(if $(filter install install-lib, $(goals)), $(info ++++ info: \ 808 | installpath is '$(installpath)')) 809 | 810 | 811 | #=== define executables ======================================================== 812 | 813 | 814 | # By default we build class executables, and optionally a shared dynamic link 815 | # lib. When make-lib-executable=yes we build all classes into a single lib 816 | # executable, on the condition that variable lib.setup.sources is defined. 817 | 818 | ifeq ($(make-lib-executable),yes) 819 | $(if $(lib.setup.sources), ,\ 820 | $(error Can not build library blob because lib.setup.sources is undefined)) 821 | executables := $(lib.name).$(extension) 822 | else 823 | executables := $(classes.executables) $(shared.lib) 824 | endif 825 | 826 | 827 | ################################################################################ 828 | ### rules: special targets ##################################################### 829 | ################################################################################ 830 | 831 | 832 | # Disable built-in rules. If some target can't be built with the specified 833 | # rules, it should not be built at all. 834 | MAKEFLAGS += --no-builtin-rules 835 | 836 | .PRECIOUS: 837 | .SUFFIXES: 838 | .PHONY: all post build-lib \ 839 | $(classes) $(makefiledirs) $(makefiles) \ 840 | install install-executables install-datafiles install-datadirs \ 841 | force clean vars allvars depend help 842 | 843 | 844 | ################################################################################ 845 | ### rules: build targets ####################################################### 846 | ################################################################################ 847 | 848 | 849 | # Target all forces the build of targets [$(executables) post] in 850 | # deterministic order. Target $(executables) builds class executables plus 851 | # optional shared lib or alternatively a single lib executable when 852 | # make-lib-executable=true. Target post is optionally defined by 853 | # library makefile. 854 | 855 | all: post 856 | post: $(executables) 857 | 858 | all: 859 | $(info ++++info: target all in lib $(lib.name) completed) 860 | 861 | # build all with -g option turned on for debug symbols 862 | alldebug: c.flags += -g 863 | alldebug: cxx.flags += -g 864 | alldebug: all 865 | 866 | 867 | #=== class executable ========================================================== 868 | 869 | 870 | # recipe for linking objects in class executable 871 | # argument $1 = compiler type (c or cxx) 872 | # argument $2 = class basename 873 | define link-class 874 | $(compile-$1) \ 875 | $($1.ldflags) $($2.class.ldflags) \ 876 | -o $2.$(extension) \ 877 | $(addsuffix .o, $(basename $($2.class.sources))) \ 878 | $(addsuffix .o, $(basename $(common.sources))) \ 879 | $($1.ldlibs) $($2.class.ldlibs) $(shared.lib) 880 | endef 881 | 882 | # general rule for linking object files in class executable 883 | %.$(extension): $(shared.lib) 884 | $(info ++++ info: linking objects in $@ for lib $(lib.name)) 885 | $(if $(filter %.cc %.cpp, $($*.class.sources)), \ 886 | $(call link-class,cxx,$*), \ 887 | $(call link-class,c,$*)) 888 | 889 | 890 | #=== library blob ============================================================== 891 | 892 | 893 | # build all classes into single executable 894 | build-lib: $(lib.name).$(extension) 895 | $(info ++++ info: library blob $(lib.name).$(extension) completed) 896 | 897 | # recipe for linking objects in lib executable 898 | # argument $1 = compiler type (c or cxx) 899 | define link-lib 900 | $(compile-$1) \ 901 | $($1.ldflags) $(lib.ldflags) \ 902 | -o $(lib.name).$(extension) $(all.objects) \ 903 | $($1.ldlibs) $(lib.ldlibs) 904 | endef 905 | 906 | # rule for linking objects in lib executable 907 | # declared conditionally to avoid name clashes 908 | ifeq ($(make-lib-executable),yes) 909 | $(lib.name).$(extension): $(all.objects) 910 | $(if $(filter %.cc %.cpp, $(all.sources)), \ 911 | $(call link-lib,cxx), \ 912 | $(call link-lib,c)) 913 | endif 914 | 915 | 916 | #=== shared dynamic lib ======================================================== 917 | 918 | 919 | # recipe for linking objects in shared executable 920 | # argument $1 = compiler type (c or cxx) 921 | define link-shared 922 | $(compile-$1) \ 923 | $(shared.ldflags) \ 924 | -o $(shared.lib) $(shared.objects) \ 925 | $($1.ldlibs) $(shared.ldlibs) 926 | endef 927 | 928 | # rule for linking objects in shared executable 929 | # build recipe is in macro 'link-shared' 930 | $(shared.lib): $(shared.objects) 931 | $(info ++++ info: linking objects in shared lib $@) 932 | $(if $(filter %.cc %.cpp, $(shared.sources)), \ 933 | $(call link-shared,cxx), \ 934 | $(call link-shared,c)) 935 | 936 | 937 | #=== object files ============================================================== 938 | 939 | 940 | # recipe to make .o file from source 941 | # argument $1 is compiler type (c or cxx) 942 | define make-object-file 943 | $(info ++++ info: making $@ in lib $(lib.name)) 944 | $(compile-$1) \ 945 | $($1.flags) \ 946 | -o $@ -c $< 947 | endef 948 | 949 | # Three rules to create .o files. These are double colon 'terminal' rules, 950 | # meaning they are the last in a rules chain. 951 | 952 | %.o:: %.c 953 | $(call make-object-file,c) 954 | 955 | %.o:: %.cc 956 | $(call make-object-file,cxx) 957 | 958 | %.o:: %.cpp 959 | $(call make-object-file,cxx) 960 | 961 | 962 | #=== explicit prerequisites for class executables ============================== 963 | 964 | 965 | # For class executables, prerequisite rules are declared in run time. Target 966 | # 'depend' prints these rules for debugging purposes. 967 | 968 | # declare explicit prerequisites rule like 'class: class.extension' 969 | # argument $v is class basename 970 | define declare-class-target 971 | $v: $v.$(extension) 972 | endef 973 | 974 | # declare explicit prerequisites rule like 'class.extension: object1.o object2.o' 975 | # argument $v is class basename 976 | define declare-class-executable-target 977 | $v.$(extension): $(addsuffix .o, $(basename $($v.class.sources))) \ 978 | $(addsuffix .o, $(basename $(common.sources))) 979 | endef 980 | 981 | # evaluate explicit prerequisite rules for all classes 982 | $(foreach v, $(classes), $(eval $(declare-class-target))) 983 | $(foreach v, $(classes), $(eval $(declare-class-executable-target))) 984 | 985 | 986 | #=== implicit prerequisites for class executables ============================== 987 | 988 | 989 | # Evaluating implicit prerequisites (header files) with help from the 990 | # preprocessor is 'expensive' so this is done conditionally and selectively. 991 | # Note that it is also possible to trigger a build via install targets, in 992 | # which case implicit prerequisites are not checked. 993 | 994 | # When the Pd include path contains spaces it will mess up the implicit 995 | # prerequisites rules. 996 | disable-dependency-tracking := $(strip $(pdincludepathwithspaces)) 997 | 998 | ifndef disable-dependency-tracking 999 | must-build-everything := $(filter all, $(goals)) 1000 | must-build-class := $(filter $(classes), $(goals)) 1001 | must-build-sources := $(foreach v, $(must-build-class), $($v.class.sources)) 1002 | endif 1003 | 1004 | # declare implicit prerequisites rule like 'object.o: header1.h header2.h ...' 1005 | # argument $1 is input source file(s) 1006 | # dir is explicitly added because option -MM strips it by default 1007 | define declare-object-target 1008 | $(dir $1)$(filter %.o: %.h, $(shell $(CPP) $(depcheck.flags) -MM $1)) $(MAKEFILE_LIST) 1009 | endef 1010 | 1011 | # evaluate implicit prerequisite rules when rebuilding everything 1012 | ifdef must-build-everything 1013 | $(if $(wildcard $(all.objects)), \ 1014 | $(info ++++ info: evaluating implicit prerequisites in lib $(lib.name).....) \ 1015 | $(foreach v, $(all.sources), $(eval $(call declare-object-target, $v)))) 1016 | endif 1017 | 1018 | # evaluate implicit prerequisite rules when selectively building classes 1019 | ifdef must-build-class 1020 | $(foreach v, $(must-build-sources), \ 1021 | $(eval $(call declare-object-target, $v))) 1022 | $(foreach v, $(shared.sources), \ 1023 | $(eval $(call declare-object-target, $v))) 1024 | endif 1025 | 1026 | 1027 | ################################################################################ 1028 | ### rules: preprocessor and assembly files ##################################### 1029 | ################################################################################ 1030 | 1031 | 1032 | # Preprocessor and assembly output files for bug tracing etc. They are not part 1033 | # of the build processes for executables. By default these files are created in 1034 | # the current working directory. Dependency tracking is not performed, the build 1035 | # is forced instead to make sure it's up to date. 1036 | 1037 | force: 1038 | 1039 | 1040 | #=== preprocessor file ========================================================= 1041 | 1042 | 1043 | # make preprocessor output file with extension .pre 1044 | # argument $1 = compiler type (c or cxx) 1045 | define make-preprocessor-file 1046 | $(info ++++ info: making preprocessor output file $(notdir $*.pre) \ 1047 | in current working directory) 1048 | $(compile-$1) -E $< $(c.flags) $($1.flags) -o $(notdir $*.pre) 1049 | endef 1050 | 1051 | %.pre:: %.c force 1052 | $(call make-preprocessor-file,c) 1053 | 1054 | %.pre:: %.cc force 1055 | $(call make-preprocessor-file,cxx) 1056 | 1057 | %.pre:: %.cpp force 1058 | $(call make-preprocessor-file,cxx) 1059 | 1060 | 1061 | #=== assembly file ============================================================= 1062 | 1063 | 1064 | # make C / assembly interleaved output file with extension .lst 1065 | # argument $1 = compiler type (c or cxx) 1066 | define make-assembly-file 1067 | $(info ++++ info: making assembly output file $(notdir $*.lst) \ 1068 | in current working directory) 1069 | $(compile-$1) \ 1070 | -c -Wa,-a,-ad -fverbose-asm \ 1071 | $($1.flags) \ 1072 | $< > $(notdir $*.lst) 1073 | endef 1074 | 1075 | %.lst:: %.c force 1076 | $(call make-assembly-file,c) 1077 | 1078 | %.lst:: %.cc force 1079 | $(call make-assembly-file,cxx) 1080 | 1081 | %.lst:: %.cpp force 1082 | $(call make-assembly-file,cxx) 1083 | 1084 | 1085 | ################################################################################ 1086 | ### rules: installation targets ################################################ 1087 | ################################################################################ 1088 | 1089 | 1090 | #=== strip ===================================================================== 1091 | 1092 | 1093 | # Stripping of installed binaries will only be done when variable 'stripflags' 1094 | # is defined non-empty. No default definition is provided except for Windows 1095 | # where the unstripped binaries are large, especially in the case of Mingw-w64. 1096 | 1097 | # Note: while stripping all symbols ('-s' or '--strip-all') is possible for 1098 | # Linux and Windows, in the case of OSX only non-global symbols can be stripped 1099 | # (option '-x' or '--discard-all'). 1100 | 1101 | # Make definition of strip command overridable so it can be defined in an 1102 | # environment for cross-compilation. 1103 | STRIP ?= strip 1104 | 1105 | # Commands in 'strip-executables' will be executed conditionally in the rule for 1106 | # target 'install-executables'. 1107 | strip-executables = cd "$(installpath)" && \ 1108 | $(foreach v, $(executables), $(STRIP) $(stripflags) '$v';) 1109 | 1110 | 1111 | #=== install =================================================================== 1112 | 1113 | 1114 | # Install targets depend on successful exit status of target all because nothing 1115 | # must be installed in case of a build error. 1116 | 1117 | # -p = preserve time stamps 1118 | # -m = set permission mode (as in chmod) 1119 | # -d = create all components of specified directories 1120 | INSTALL = install 1121 | INSTALL_PROGRAM := $(INSTALL) -p -m 644 1122 | INSTALL_DATA := $(INSTALL) -p -m 644 1123 | INSTALL_DIR := $(INSTALL) -m 755 -d 1124 | 1125 | # strip spaces from file names 1126 | executables := $(strip $(executables)) 1127 | datafiles := $(strip $(datafiles)) 1128 | datadirs := $(strip $(datadirs)) 1129 | 1130 | # Do not make any install sub-target with empty variable definition because the 1131 | # install program would exit with an error. 1132 | install: $(if $(executables), install-executables) 1133 | install: $(if $(datafiles), install-datafiles) 1134 | install: $(if $(datadirs), install-datadirs) 1135 | 1136 | install-executables: all 1137 | $(INSTALL_DIR) -v "$(installpath)" 1138 | $(foreach v, $(executables), \ 1139 | $(INSTALL_PROGRAM) '$v' "$(installpath)";) 1140 | $(info ++++ info: executables of lib $(lib.name) installed \ 1141 | from $(CURDIR) to $(installpath)) 1142 | $(if $(stripflags), $(strip-executables),) 1143 | 1144 | install-datafiles: all 1145 | $(INSTALL_DIR) -v "$(installpath)" 1146 | $(foreach v, $(datafiles), \ 1147 | $(INSTALL_DATA) '$(v)' "$(installpath)";) 1148 | $(info ++++ info: data files of lib $(lib.name) installed \ 1149 | from $(CURDIR) to $(installpath)) 1150 | 1151 | install-datadirs: all 1152 | $(foreach v, $(datadirs), $(INSTALL_DIR) "$(installpath)/$v";) 1153 | $(foreach v, $(datadirs), \ 1154 | $(INSTALL_DATA) $(wildcard $v/*) "$(installpath)/$v";) 1155 | $(info ++++ info: data directories of lib $(lib.name) installed \ 1156 | from $(CURDIR) to $(installpath)) 1157 | 1158 | 1159 | ################################################################################ 1160 | ### rules: distribution targets ################################################ 1161 | ################################################################################ 1162 | 1163 | 1164 | # TODO 1165 | # These targets are implemented in Makefile Template, but I have to figure out 1166 | # how to do it under the not-so-strict conditions of Makefile.pdlibbuilder. 1167 | 1168 | # make source package 1169 | dist: 1170 | @echo "target dist not yet implemented" 1171 | 1172 | # make Debian source package 1173 | dpkg-source: 1174 | @echo "target dpkg-source not yet implemented" 1175 | 1176 | $(ORIGDIR): 1177 | 1178 | $(DISTDIR): 1179 | 1180 | 1181 | ################################################################################ 1182 | ### rules: clean targets ####################################################### 1183 | ################################################################################ 1184 | 1185 | 1186 | # delete build products from build tree 1187 | clean: 1188 | rm -f $(all.objects) 1189 | rm -f $(classes.executables) $(lib.name).$(extension) $(shared.lib) 1190 | rm -f *.pre *.lst 1191 | 1192 | # remove distribution directories and tarballs from build tree 1193 | distclean: clean 1194 | @echo "target distclean not yet implemented" 1195 | 1196 | 1197 | ################################################################################ 1198 | ### rules: submake targets ##################################################### 1199 | ################################################################################ 1200 | 1201 | 1202 | # Iterate over sub-makefiles or makefiles in other directories. 1203 | 1204 | # When 'continue-make=yes' is set, sub-makes will report 'true' to the parent 1205 | # process regardless of their real exit status. This prevents the parent make 1206 | # from being aborted by a sub-make error. Useful when you want to quickly find 1207 | # out which sub-makes from a large set will succeed. 1208 | ifeq ($(continue-make),yes) 1209 | continue = || true 1210 | endif 1211 | 1212 | # These targets will trigger sub-make processes for entries in 'makefiledirs' 1213 | # and 'makefiles'. 1214 | all alldebug install clean distclean dist dkpg-source: \ 1215 | $(makefiledirs) $(makefiles) 1216 | 1217 | # this expands to identical rules for each entry in 'makefiledirs' 1218 | $(makefiledirs): 1219 | $(MAKE) --directory=$@ $(MAKECMDGOALS) $(continue) 1220 | 1221 | # this expands to identical rules for each entry in 'makefiles' 1222 | $(makefiles): 1223 | $(MAKE) --directory=$(dir $@) --makefile=$(notdir $@) $(MAKECMDGOALS) $(continue) 1224 | 1225 | 1226 | ################################################################################ 1227 | ### rules: convenience targets ################################################# 1228 | ################################################################################ 1229 | 1230 | 1231 | #=== show variables ============================================================ 1232 | 1233 | 1234 | # Several 'function' macro's cause errors when expanded within a rule or without 1235 | # proper arguments. Variables which are set with the define directive are only 1236 | # shown by name for that reason. 1237 | functions = \ 1238 | add-class-source \ 1239 | declare-class-target \ 1240 | declare-class-executable-target \ 1241 | declare-object-target \ 1242 | link-class \ 1243 | link-lib \ 1244 | link-shared \ 1245 | make-object-file \ 1246 | make-preprocessor-file \ 1247 | make-assembly-file 1248 | 1249 | 1250 | # show variables from makefiles 1251 | vars: 1252 | $(info ++++ info: showing makefile variables:) 1253 | $(foreach v,\ 1254 | $(sort $(filter-out $(functions) functions, $(.VARIABLES))),\ 1255 | $(if $(filter file, $(origin $v)),\ 1256 | $(info variable $v = $($v)))) 1257 | $(foreach v, $(functions), $(info 'function' name: $v)) 1258 | @echo 1259 | 1260 | # show all variables 1261 | allvars: 1262 | $(info ++++ info: showing default, automatic and makefile variables:) 1263 | $(foreach v, \ 1264 | $(sort $(filter-out $(functions) functions, $(.VARIABLES))), \ 1265 | $(info variable ($(origin $v)) $v = $($v))) 1266 | $(foreach v, $(functions), $(info 'function' name: $v)) 1267 | @echo 1268 | 1269 | 1270 | #=== show dependencies ========================================================= 1271 | 1272 | 1273 | # show generated prerequisites rules 1274 | depend: 1275 | $(info ++++ info: generated prerequisite rules) 1276 | $(foreach v, $(classes), $(info $(declare-class-target))) 1277 | $(foreach v, $(classes), $(info $(declare-class-executable-target))) 1278 | $(foreach v, $(all.sources), $(info $(call declare-object-target, $v))) 1279 | @echo 1280 | 1281 | 1282 | #=== show help text ============================================================ 1283 | 1284 | 1285 | # brief info about targets and paths 1286 | 1287 | ifdef mpdh 1288 | mpdhinfo := $(mpdh) 1289 | else 1290 | mpdhinfo := m_pd.h was not found. Is Pd installed? 1291 | endif 1292 | 1293 | help: 1294 | @echo 1295 | @echo " Main targets:" 1296 | @echo " all: build executables (default target)" 1297 | @echo " install: install all components of the library" 1298 | @echo " vars: print makefile variables for troubleshooting" 1299 | @echo " allvars: print all variables for troubleshooting" 1300 | @echo " help: print this help text" 1301 | @echo 1302 | @echo " Pd API m_pd.h:" 1303 | @echo " $(mpdhinfo)" 1304 | @echo " You may specify your preferred Pd include directory as argument" 1305 | @echo " to the make command, like 'PDINCLUDEDIR=path/to/pd/src'." 1306 | @echo 1307 | @echo " Path for installation of your libdir(s):" 1308 | @echo " $(PDLIBDIR)" 1309 | @echo " Alternatively you may specify your path for installation as argument" 1310 | @echo " to the make command, like 'PDLIBDIR=path/to/pd-externals'." 1311 | @echo 1312 | @echo " Default paths are listed in the doc sections in Makefile.pdlibbuilder." 1313 | @echo 1314 | 1315 | 1316 | #=== platform test ============================================================= 1317 | 1318 | 1319 | # This target can be used to test if the compiler for specified PLATFORM is 1320 | # correctly defined and available. 1321 | 1322 | dumpmachine: 1323 | @$(CC) -dumpmachine 1324 | 1325 | 1326 | #=== dummy target ============================================================== 1327 | 1328 | 1329 | coffee: 1330 | @echo "Makefile.pdlibbuilder: Can not make coffee. Sorry." 1331 | 1332 | 1333 | ################################################################################ 1334 | ### end of rules sections ###################################################### 1335 | ################################################################################ 1336 | 1337 | 1338 | # for syntax highlighting in vim and github 1339 | # vim: set filetype=make: 1340 | 1341 | -------------------------------------------------------------------------------- /external/abl_link_instance.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * For information on usage and redistribution, and for a DISCLAIMER OF ALL 3 | * WARRANTIES, see the file, LICENSE, in the root of this repository. 4 | * 5 | */ 6 | 7 | #include "abl_link_instance.hpp" 8 | 9 | #include "s_stuff.h" // Only for DEFDACBLKSIZE. 10 | 11 | namespace abl_link { 12 | 13 | // Eyeball estimate for latency compensation: Pd's reported delay (5ms) plus 14 | // the duration of one Pd buffer (1.4ms at 44.1kHz), rounded up to the next 15 | // integer. 16 | // TODO: Come up with a more scientific way of estimating the offset. 17 | #ifndef ABL_LINK_OFFSET_MS 18 | #define ABL_LINK_OFFSET_MS 7 19 | #endif 20 | 21 | std::weak_ptr AblLinkWrapper::shared_instance; 22 | 23 | AblLinkWrapper::AblLinkWrapper(double bpm) : 24 | link(bpm), 25 | session_state(ableton::link::ApiState(), false), 26 | time_filter( 27 | ableton::link::HostTimeFilter()), 28 | latency_offset(ABL_LINK_OFFSET_MS * 1000), 29 | num_peers_sym(gensym("#abl_link_num_peers")), 30 | num_peers(-1), 31 | sample_time(0.0), 32 | invocation_count(0) { 33 | link.enableStartStopSync(true); 34 | post("Created new Link instance with tempo %f.", bpm); 35 | } 36 | 37 | void AblLinkWrapper::enable(bool enabled) { link.enable(enabled); } 38 | 39 | void AblLinkWrapper::set_offset(double offset_ms) { 40 | latency_offset = std::chrono::microseconds((int)(offset_ms * 1000)); 41 | } 42 | 43 | ableton::Link::SessionState& AblLinkWrapper::acquireAudioSessionState( 44 | std::chrono::microseconds *current_time) { 45 | if (invocation_count++ == 0) { 46 | const int n = link.numPeers(); 47 | if (n != num_peers && num_peers_sym->s_thing) { 48 | pd_float(num_peers_sym->s_thing, n); 49 | num_peers = n; 50 | } 51 | session_state = link.captureAudioSessionState(); 52 | sample_time += DEFDACBLKSIZE; 53 | curr_time = time_filter.sampleTimeToHostTime(sample_time) + latency_offset; 54 | } 55 | *current_time = curr_time; 56 | return session_state; 57 | } 58 | 59 | void AblLinkWrapper::releaseAudioSessionState() { 60 | if (invocation_count >= shared_instance.use_count()) { 61 | link.commitAudioSessionState(session_state); 62 | invocation_count = 0; 63 | } 64 | } 65 | 66 | std::shared_ptr 67 | AblLinkWrapper::getSharedInstance(double bpm) { 68 | auto ptr = shared_instance.lock(); 69 | if (!ptr) { 70 | ptr.reset(new AblLinkWrapper(bpm)); 71 | shared_instance = ptr; 72 | } else { 73 | post("Using existing Link instance with ref count %d.", ptr.use_count()); 74 | } 75 | return ptr; 76 | } 77 | 78 | } // namespace abl_link 79 | -------------------------------------------------------------------------------- /external/abl_link_instance.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * For information on usage and redistribution, and for a DISCLAIMER OF ALL 3 | * WARRANTIES, see the file, LICENSE, in the root of this repository. 4 | * 5 | */ 6 | 7 | #ifndef __ABL_LINK_INSTANCE_H__ 8 | #define __ABL_LINK_INSTANCE_H__ 9 | 10 | #include 11 | 12 | #include "ableton/Link.hpp" 13 | #include "ableton/link/HostTimeFilter.hpp" 14 | #include "m_pd.h" 15 | 16 | namespace abl_link { 17 | 18 | class AblLinkWrapper { 19 | public: 20 | // Returns a shared pointer to the global Link instance, creating a new 21 | // instance with the given bpm if necessary. The bpm parameter will be 22 | // ignored if the global instance exists already. 23 | static std::shared_ptr getSharedInstance(double bpm); 24 | 25 | void enable(bool enabled); 26 | 27 | void set_offset(double offset_ms); 28 | 29 | ableton::Link::SessionState& 30 | acquireAudioSessionState(std::chrono::microseconds *current_time); 31 | 32 | void releaseAudioSessionState(); 33 | 34 | private: 35 | explicit AblLinkWrapper(double bpm); 36 | 37 | ableton::Link link; 38 | ableton::Link::SessionState session_state; 39 | ableton::link::HostTimeFilter time_filter; 40 | std::chrono::microseconds latency_offset; 41 | t_symbol *num_peers_sym; 42 | int num_peers; 43 | double sample_time; 44 | int invocation_count; 45 | std::chrono::microseconds curr_time; 46 | static std::weak_ptr shared_instance; 47 | }; 48 | 49 | } // namespace abl_link 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /external/abl_link~-help.pd: -------------------------------------------------------------------------------- 1 | #N canvas 100 86 912 528 10; 2 | #X msg 750 106 tempo \$1; 3 | #X msg 564 106 resolution \$1; 4 | #X msg 660 106 reset \$1 \$2; 5 | #X obj 660 85 pack f f; 6 | #X floatatom 594 232 5 0 0 1 beat_time - - 0; 7 | #X floatatom 566 253 5 0 0 1 phase - - 0; 8 | #X msg 435 206 \; pd dsp 1; 9 | #X floatatom 539 281 5 0 0 1 step - - 0; 10 | #X floatatom 622 210 5 0 0 1 tempo - - 0; 11 | #X obj 421 86 tgl 15 0 empty empty empty 17 7 0 10 #fcfcfc #000000 #000000 0 1; 12 | #X obj 539 169 abl_link~ 1 0 4 134; 13 | #X floatatom 750 87 5 0 0 2 tempo - - 0; 14 | #X floatatom 705 66 5 0 0 2 quantum - - 0; 15 | #X floatatom 660 66 5 0 0 2 beat - - 0; 16 | #X floatatom 564 86 5 0 0 2 resolution - - 0; 17 | #X text 25 344 Link's beat time can sometimes go backwards. When this happens \, the step outlet will fall silent until the beat time moves forward again. The phase and beat outlets will output raw values from Link so that patches can implement their own handling of time going backwards.; 18 | #X text 25 251 The creation arguments \, all optional \, specify the resolution (default 1) and the initial beat time (default 0) \, as well as the quantum (default 4) and tempo (default 120) \, which will be replaced by the session tempo if the Link instance is already connected. The Link external will perform a quantized launch on creation.; 19 | #X msg 421 107 connect \$1; 20 | #X text 25 424 The Link external emits events as soon as DSP is enabled in Pd. It will only connect with other Link instances \, however \, if you send it the message [connect 1(.; 21 | #X floatatom 647 300 5 0 0 0 - - - 0; 22 | #X obj 647 278 r #abl_link_num_peers; 23 | #X text 25 24 abl_link~: Ableton Link external; 24 | #X floatatom 650 191 5 0 0 1 is_playing - - 0; 25 | #X obj 504 86 tgl 15 0 empty empty empty 17 7 0 10 #fcfcfc #000000 #000000 0 1; 26 | #X msg 504 106 play \$1; 27 | #X text 25 52 abl_link~ is a Pd external that integrates Ableton Link into Pd. It has five outlets \, which emit the index of the current step (at the beginning of each step) \, the current phase and beat time on each DSP tick \, the tempo on tempo changes \, as well as the play state. Phase and beat time are Link concepts. The purpose of the step feature is to generate events in Pd at a given rate (measured in steps per beat).; 28 | #N canvas 213 167 446 262 offset_vs_audio_latency 0; 29 | #X text 37 29 Ableton defines its grid time as the moment when the sound should hit the speakers. This means connected apps must \, on their own \, account for audio driver latency and any other calculation latencies.; 30 | #X text 37 94 Pure Data does not currently make the audio driver latency available to objects. When you run abl_link~ against other apps \, then \, Pure Data may sound some milliseconds late.; 31 | #X text 37 149 abl_link~ responds to an [offset( message by shifting its timebase earlier by the given number of milliseconds. At worst \, then \, users may sync with non-Pd apps (or with Pd running under different audio settings) by manually setting the offset. It's easy to tune by hand/ear.; 32 | #X restore 119 483 pd offset_vs_audio_latency; 33 | #X floatatom 820 87 5 0 0 0 - - - 0; 34 | #X msg 820 106 offset \$1; 35 | #X text 25 158 abl_link~ responds to six methods \, for connecting with other Link instances \, for setting the resolution of the step outlet (in steps per beat) \, the tempo (in beats per minute) \, the play state (on or off) \, the latency offset \, and for resetting the beat time and quantum by having Link perform a quantized launch.; 36 | #X connect 0 0 10 0; 37 | #X connect 1 0 10 0; 38 | #X connect 2 0 10 0; 39 | #X connect 3 0 2 0; 40 | #X connect 9 0 17 0; 41 | #X connect 10 0 7 0; 42 | #X connect 10 1 5 0; 43 | #X connect 10 2 4 0; 44 | #X connect 10 3 8 0; 45 | #X connect 10 4 22 0; 46 | #X connect 11 0 0 0; 47 | #X connect 12 0 3 1; 48 | #X connect 13 0 3 0; 49 | #X connect 14 0 1 0; 50 | #X connect 17 0 10 0; 51 | #X connect 20 0 19 0; 52 | #X connect 23 0 24 0; 53 | #X connect 24 0 10 0; 54 | #X connect 27 0 28 0; 55 | #X connect 28 0 10 0; 56 | -------------------------------------------------------------------------------- /external/abl_link~.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * For information on usage and redistribution, and for a DISCLAIMER OF ALL 3 | * WARRANTIES, see the file, LICENSE, in the root of this repository. 4 | * 5 | */ 6 | 7 | #include "abl_link~.hpp" 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "abl_link_instance.hpp" 14 | #include "m_pd.h" 15 | 16 | static t_class *abl_link_tilde_class; 17 | 18 | typedef struct _abl_link_tilde { 19 | t_object obj; 20 | t_clock *clock; 21 | t_outlet *step_out; 22 | t_outlet *phase_out; 23 | t_outlet *beat_out; 24 | t_outlet *tempo_out; 25 | t_outlet *is_playing_out; 26 | double steps_per_beat; 27 | double prev_beat_time; 28 | double quantum; 29 | double tempo; 30 | int is_playing; 31 | int reset_flag; 32 | std::shared_ptr link; 33 | } t_abl_link_tilde; 34 | 35 | static void abl_link_tilde_enable(t_abl_link_tilde *x, t_floatarg enabled) { 36 | x->link->enable(enabled); 37 | } 38 | 39 | static t_int *abl_link_tilde_perform(t_int *w) { 40 | t_abl_link_tilde *x = (t_abl_link_tilde *)(w[1]); 41 | clock_delay(x->clock, 0); 42 | return (w+2); 43 | } 44 | 45 | static void abl_link_tilde_dsp(t_abl_link_tilde *x, t_signal **sp) { 46 | dsp_add(abl_link_tilde_perform, 1, x); 47 | } 48 | 49 | static void abl_link_tilde_tick(t_abl_link_tilde *x) { 50 | std::chrono::microseconds curr_time; 51 | auto& session_state = x->link->acquireAudioSessionState(&curr_time); 52 | if (x->is_playing < 0) { 53 | session_state.setIsPlaying(x->is_playing + 2, curr_time); 54 | } 55 | const int prev_play = x->is_playing; 56 | x->is_playing = session_state.isPlaying(); 57 | if (prev_play != x->is_playing) { 58 | outlet_float(x->is_playing_out, x->is_playing); 59 | } 60 | if (x->tempo < 0) { 61 | session_state.setTempo(-x->tempo, curr_time); 62 | } 63 | const double prev_tempo = x->tempo; 64 | x->tempo = session_state.tempo(); 65 | if (prev_tempo != x->tempo) { 66 | outlet_float(x->tempo_out, x->tempo); 67 | } 68 | double curr_beat_time; 69 | if (x->reset_flag) { 70 | session_state.requestBeatAtTime(x->prev_beat_time, curr_time, x->quantum); 71 | curr_beat_time = session_state.beatAtTime(curr_time, x->quantum); 72 | x->prev_beat_time = curr_beat_time - 1e-6; 73 | x->reset_flag = 0; 74 | } else { 75 | curr_beat_time = session_state.beatAtTime(curr_time, x->quantum); 76 | } 77 | outlet_float(x->beat_out, curr_beat_time); 78 | const double curr_phase = fmod(curr_beat_time, x->quantum); 79 | outlet_float(x->phase_out, curr_phase); 80 | if (curr_beat_time > x->prev_beat_time) { 81 | const double prev_phase = fmod(x->prev_beat_time, x->quantum); 82 | const double prev_step = floor(prev_phase * x->steps_per_beat); 83 | const double curr_step = floor(curr_phase * x->steps_per_beat); 84 | if (prev_phase - curr_phase > x->quantum / 2 || prev_step != curr_step) { 85 | outlet_float(x->step_out, curr_step); 86 | } 87 | } 88 | x->prev_beat_time = curr_beat_time; 89 | x->link->releaseAudioSessionState(); 90 | } 91 | 92 | static void abl_link_tilde_set_tempo(t_abl_link_tilde *x, t_floatarg bpm) { 93 | x->tempo = -bpm; // Negative values signal tempo changes. 94 | } 95 | 96 | static void abl_link_tilde_play(t_abl_link_tilde *x, t_floatarg is_playing) { 97 | x->is_playing = (is_playing != 0) - 2; 98 | } 99 | 100 | static void abl_link_tilde_set_resolution(t_abl_link_tilde *x, 101 | t_floatarg steps_per_beat) { 102 | x->steps_per_beat = steps_per_beat; 103 | } 104 | 105 | static void abl_link_tilde_set_offset(t_abl_link_tilde *x, 106 | t_floatarg offset_ms) { 107 | x->link->set_offset(offset_ms); 108 | } 109 | 110 | static void abl_link_tilde_reset(t_abl_link_tilde *x, t_symbol *s, 111 | int argc, t_atom *argv) { 112 | x->prev_beat_time = 0; 113 | x->reset_flag = 1; 114 | switch (argc) { 115 | default: 116 | pd_error(x, "abl_link~ reset: Unexpected number of parameters: %d", argc); 117 | case 2: 118 | x->quantum = atom_getfloat(argv + 1); 119 | case 1: 120 | x->prev_beat_time = atom_getfloat(argv); 121 | case 0: 122 | break; 123 | } 124 | } 125 | 126 | static void *abl_link_tilde_new(t_symbol *s, int argc, t_atom *argv) { 127 | t_abl_link_tilde *x = (t_abl_link_tilde *)pd_new(abl_link_tilde_class); 128 | x->clock = clock_new(x, (t_method)abl_link_tilde_tick); 129 | x->step_out = outlet_new(&x->obj, &s_float); 130 | x->phase_out = outlet_new(&x->obj, &s_float); 131 | x->beat_out = outlet_new(&x->obj, &s_float); 132 | x->tempo_out = outlet_new(&x->obj, &s_float); 133 | x->is_playing_out = outlet_new(&x->obj, &s_float); 134 | x->steps_per_beat = 1; 135 | x->prev_beat_time = 0; 136 | x->quantum = 4; 137 | x->tempo = 0; 138 | x->is_playing = 2; 139 | x->reset_flag = 1; 140 | double initial_tempo = 120.0; 141 | switch (argc) { 142 | default: 143 | pd_error(x, "abl_link~: Unexpected number of creation args: %d", argc); 144 | case 4: 145 | initial_tempo = atom_getfloat(argv + 3); 146 | case 3: 147 | x->quantum = atom_getfloat(argv + 2); 148 | case 2: 149 | x->prev_beat_time = atom_getfloat(argv + 1); 150 | case 1: 151 | x->steps_per_beat = atom_getfloat(argv); 152 | case 0: 153 | break; 154 | } 155 | x->link = abl_link::AblLinkWrapper::getSharedInstance(initial_tempo); 156 | return x; 157 | } 158 | 159 | static void abl_link_tilde_free(t_abl_link_tilde *x) { 160 | clock_free(x->clock); 161 | x->link = nullptr; 162 | } 163 | 164 | extern "C" { 165 | 166 | void abl_link_tilde_setup() { 167 | post("setting up abl_link~"); 168 | abl_link_tilde_class = class_new(gensym("abl_link~"), 169 | (t_newmethod)abl_link_tilde_new, 170 | (t_method)abl_link_tilde_free, 171 | sizeof(t_abl_link_tilde), CLASS_DEFAULT, A_GIMME, 0); 172 | class_addmethod(abl_link_tilde_class, (t_method)abl_link_tilde_dsp, 173 | gensym("dsp"), A_NULL); 174 | class_addmethod(abl_link_tilde_class, (t_method)abl_link_tilde_enable, 175 | gensym("connect"), A_DEFFLOAT, 0); 176 | class_addmethod(abl_link_tilde_class, (t_method)abl_link_tilde_play, 177 | gensym("play"), A_DEFFLOAT, 0); 178 | class_addmethod(abl_link_tilde_class, (t_method)abl_link_tilde_set_tempo, 179 | gensym("tempo"), A_DEFFLOAT, 0); 180 | class_addmethod(abl_link_tilde_class, (t_method)abl_link_tilde_set_resolution, 181 | gensym("resolution"), A_DEFFLOAT, 0); 182 | class_addmethod(abl_link_tilde_class, (t_method)abl_link_tilde_reset, 183 | gensym("reset"), A_GIMME, 0); 184 | class_addmethod(abl_link_tilde_class, (t_method)abl_link_tilde_set_offset, 185 | gensym("offset"), A_DEFFLOAT, 0); 186 | } 187 | 188 | } //extern "C" 189 | 190 | -------------------------------------------------------------------------------- /external/abl_link~.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * For information on usage and redistribution, and for a DISCLAIMER OF ALL 3 | * WARRANTIES, see the file, LICENSE, in the root of this repository. 4 | * 5 | */ 6 | 7 | #ifndef __ABL_LINK_TILDE_H__ 8 | #define __ABL_LINK_TILDE_H__ 9 | 10 | extern "C" { 11 | void abl_link_tilde_setup(); 12 | } 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /external/android-ifaddrs/foo.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1995, 1999 3 | * Berkeley Software Design, Inc. All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 11 | * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND 12 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 13 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 14 | * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE 15 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 16 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 17 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 18 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 19 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 20 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 21 | * SUCH DAMAGE. 22 | * 23 | * BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp 24 | */ 25 | 26 | #ifndef _IFADDRS_H_ 27 | #define _IFADDRS_H_ 28 | 29 | struct ifaddrs { 30 | struct ifaddrs *ifa_next; 31 | char *ifa_name; 32 | unsigned int ifa_flags; 33 | struct sockaddr *ifa_addr; 34 | struct sockaddr *ifa_netmask; 35 | struct sockaddr *ifa_dstaddr; 36 | void *ifa_data; 37 | }; 38 | 39 | /* 40 | * This may have been defined in . Note that if is 41 | * to be included it must be included before this header file. 42 | */ 43 | #ifndef ifa_broadaddr 44 | #define ifa_broadaddr ifa_dstaddr /* broadcast address interface */ 45 | #endif 46 | 47 | #include 48 | 49 | __BEGIN_DECLS 50 | extern int getifaddrs(struct ifaddrs **ifap); 51 | extern void freeifaddrs(struct ifaddrs *ifa); 52 | __END_DECLS 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /external/android-ifaddrs/ifaddrs.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * libjingle 3 | * Copyright 2012, Google Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | #if defined(ANDROID) 28 | #include "ifaddrs.h" 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | struct netlinkrequest { 42 | nlmsghdr header; 43 | ifaddrmsg msg; 44 | }; 45 | namespace { 46 | const int kMaxReadSize = 4096; 47 | }; 48 | int set_ifname(struct ifaddrs* ifaddr, int interface) { 49 | char buf[IFNAMSIZ] = {0}; 50 | char* name = if_indextoname(interface, buf); 51 | if (name == NULL) { 52 | return -1; 53 | } 54 | ifaddr->ifa_name = new char[strlen(name) + 1]; 55 | strncpy(ifaddr->ifa_name, name, strlen(name) + 1); 56 | return 0; 57 | } 58 | int set_flags(struct ifaddrs* ifaddr) { 59 | int fd = socket(AF_INET, SOCK_DGRAM, 0); 60 | if (fd == -1) { 61 | return -1; 62 | } 63 | ifreq ifr; 64 | memset(&ifr, 0, sizeof(ifr)); 65 | strncpy(ifr.ifr_name, ifaddr->ifa_name, IFNAMSIZ - 1); 66 | int rc = ioctl(fd, SIOCGIFFLAGS, &ifr); 67 | close(fd); 68 | if (rc == -1) { 69 | return -1; 70 | } 71 | ifaddr->ifa_flags = ifr.ifr_flags; 72 | return 0; 73 | } 74 | int set_addresses(struct ifaddrs* ifaddr, ifaddrmsg* msg, void* data, 75 | size_t len) { 76 | if (msg->ifa_family == AF_INET) { 77 | sockaddr_in* sa = new sockaddr_in; 78 | sa->sin_family = AF_INET; 79 | memcpy(&sa->sin_addr, data, len); 80 | ifaddr->ifa_addr = reinterpret_cast(sa); 81 | } else if (msg->ifa_family == AF_INET6) { 82 | sockaddr_in6* sa = new sockaddr_in6; 83 | sa->sin6_family = AF_INET6; 84 | sa->sin6_scope_id = msg->ifa_index; 85 | memcpy(&sa->sin6_addr, data, len); 86 | ifaddr->ifa_addr = reinterpret_cast(sa); 87 | } else { 88 | return -1; 89 | } 90 | return 0; 91 | } 92 | int make_prefixes(struct ifaddrs* ifaddr, int family, int prefixlen) { 93 | char* prefix = NULL; 94 | if (family == AF_INET) { 95 | sockaddr_in* mask = new sockaddr_in; 96 | mask->sin_family = AF_INET; 97 | memset(&mask->sin_addr, 0, sizeof(in_addr)); 98 | ifaddr->ifa_netmask = reinterpret_cast(mask); 99 | if (prefixlen > 32) { 100 | prefixlen = 32; 101 | } 102 | prefix = reinterpret_cast(&mask->sin_addr); 103 | } else if (family == AF_INET6) { 104 | sockaddr_in6* mask = new sockaddr_in6; 105 | mask->sin6_family = AF_INET6; 106 | memset(&mask->sin6_addr, 0, sizeof(in6_addr)); 107 | ifaddr->ifa_netmask = reinterpret_cast(mask); 108 | if (prefixlen > 128) { 109 | prefixlen = 128; 110 | } 111 | prefix = reinterpret_cast(&mask->sin6_addr); 112 | } else { 113 | return -1; 114 | } 115 | for (int i = 0; i < (prefixlen / 8); i++) { 116 | *prefix++ = 0xFF; 117 | } 118 | char remainder = 0xff; 119 | remainder <<= (8 - prefixlen % 8); 120 | *prefix = remainder; 121 | return 0; 122 | } 123 | int populate_ifaddrs(struct ifaddrs* ifaddr, ifaddrmsg* msg, void* bytes, 124 | size_t len) { 125 | if (set_ifname(ifaddr, msg->ifa_index) != 0) { 126 | return -1; 127 | } 128 | if (set_flags(ifaddr) != 0) { 129 | return -1; 130 | } 131 | if (set_addresses(ifaddr, msg, bytes, len) != 0) { 132 | return -1; 133 | } 134 | if (make_prefixes(ifaddr, msg->ifa_family, msg->ifa_prefixlen) != 0) { 135 | return -1; 136 | } 137 | return 0; 138 | } 139 | int getifaddrs(struct ifaddrs** result) { 140 | int fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); 141 | if (fd < 0) { 142 | return -1; 143 | } 144 | netlinkrequest ifaddr_request; 145 | memset(&ifaddr_request, 0, sizeof(ifaddr_request)); 146 | ifaddr_request.header.nlmsg_flags = NLM_F_ROOT | NLM_F_REQUEST; 147 | ifaddr_request.header.nlmsg_type = RTM_GETADDR; 148 | ifaddr_request.header.nlmsg_len = NLMSG_LENGTH(sizeof(ifaddrmsg)); 149 | ssize_t count = send(fd, &ifaddr_request, ifaddr_request.header.nlmsg_len, 0); 150 | if (static_cast(count) != ifaddr_request.header.nlmsg_len) { 151 | close(fd); 152 | return -1; 153 | } 154 | struct ifaddrs* start = NULL; 155 | struct ifaddrs* current = NULL; 156 | char buf[kMaxReadSize]; 157 | ssize_t amount_read = recv(fd, &buf, kMaxReadSize, 0); 158 | while (amount_read > 0) { 159 | nlmsghdr* header = reinterpret_cast(&buf[0]); 160 | size_t header_size = static_cast(amount_read); 161 | for ( ; NLMSG_OK(header, header_size); 162 | header = NLMSG_NEXT(header, header_size)) { 163 | switch (header->nlmsg_type) { 164 | case NLMSG_DONE: 165 | // Success. Return. 166 | *result = start; 167 | close(fd); 168 | return 0; 169 | case NLMSG_ERROR: 170 | close(fd); 171 | freeifaddrs(start); 172 | return -1; 173 | case RTM_NEWADDR: { 174 | ifaddrmsg* address_msg = 175 | reinterpret_cast(NLMSG_DATA(header)); 176 | rtattr* rta = IFA_RTA(address_msg); 177 | ssize_t payload_len = IFA_PAYLOAD(header); 178 | while (RTA_OK(rta, payload_len)) { 179 | if (rta->rta_type == IFA_ADDRESS) { 180 | int family = address_msg->ifa_family; 181 | if (family == AF_INET || family == AF_INET6) { 182 | ifaddrs* newest = new ifaddrs; 183 | memset(newest, 0, sizeof(ifaddrs)); 184 | if (current) { 185 | current->ifa_next = newest; 186 | } else { 187 | start = newest; 188 | } 189 | if (populate_ifaddrs(newest, address_msg, RTA_DATA(rta), 190 | RTA_PAYLOAD(rta)) != 0) { 191 | freeifaddrs(start); 192 | *result = NULL; 193 | return -1; 194 | } 195 | current = newest; 196 | } 197 | } 198 | rta = RTA_NEXT(rta, payload_len); 199 | } 200 | break; 201 | } 202 | } 203 | } 204 | amount_read = recv(fd, &buf, kMaxReadSize, 0); 205 | } 206 | close(fd); 207 | freeifaddrs(start); 208 | return -1; 209 | } 210 | void freeifaddrs(struct ifaddrs* addrs) { 211 | struct ifaddrs* last = NULL; 212 | struct ifaddrs* cursor = addrs; 213 | while (cursor) { 214 | delete[] cursor->ifa_name; 215 | delete cursor->ifa_addr; 216 | delete cursor->ifa_netmask; 217 | last = cursor; 218 | cursor = cursor->ifa_next; 219 | delete last; 220 | } 221 | } 222 | #endif // defined(ANDROID) 223 | -------------------------------------------------------------------------------- /external/android-ifaddrs/ifaddrs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libjingle 3 | * Copyright 2013, Google Inc. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright notice, 11 | * this list of conditions and the following disclaimer in the documentation 12 | * and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | #ifndef TALK_BASE_IFADDRS_ANDROID_H_ 28 | #define TALK_BASE_IFADDRS_ANDROID_H_ 29 | #include 30 | #include 31 | // Implementation of getifaddrs for Android. 32 | // Fills out a list of ifaddr structs (see below) which contain information 33 | // about every network interface available on the host. 34 | // See 'man getifaddrs' on Linux or OS X (nb: it is not a POSIX function). 35 | struct ifaddrs { 36 | struct ifaddrs* ifa_next; 37 | char* ifa_name; 38 | unsigned int ifa_flags; 39 | struct sockaddr* ifa_addr; 40 | struct sockaddr* ifa_netmask; 41 | // Real ifaddrs has broadcast, point to point and data members. 42 | // We don't need them (yet?). 43 | }; 44 | int getifaddrs(struct ifaddrs** result); 45 | void freeifaddrs(struct ifaddrs* addrs); 46 | #endif // TALK_BASE_IFADDRS_ANDROID_H_ 47 | -------------------------------------------------------------------------------- /external/metronome.pd: -------------------------------------------------------------------------------- 1 | #N canvas 612 242 351 368 10; 2 | #X obj 156 242 osc~ 440; 3 | #X obj 112 272 *~; 4 | #X obj 112 316 dac~; 5 | #X obj 82 243 vline~; 6 | #X msg 82 222 1 \, 0 250; 7 | #X obj 112 294 *~ 0.25; 8 | #X msg 93 64 tempo \$1; 9 | #X msg 156 64 resolution \$1; 10 | #X msg 253 64 reset 0 \$1; 11 | #X floatatom 93 45 5 0 0 2 tempo tempo -, f 5; 12 | #X floatatom 156 46 5 0 0 2 resolution resolution -, f 5; 13 | #X floatatom 253 46 5 0 0 2 quantum quantum -, f 5; 14 | #X obj 201 219 f 440; 15 | #X obj 119 113 abl_link~ 1 0 4 140; 16 | #X obj 156 219 f 880; 17 | #X obj 156 175 select 0; 18 | #X obj 156 198 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 19 | -1 -1; 20 | #X obj 201 197 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 21 | -1 -1; 22 | #X obj 230 134 print tempo; 23 | #X msg 263 213 \; pd dsp 1; 24 | #X obj 18 45 tgl 15 0 empty empty connected 0 -8 0 10 -262144 -1 -1 25 | 0 1; 26 | #X msg 18 65 connect \$1; 27 | #X obj 199 302 print num_peers; 28 | #X obj 199 280 r #abl_link_num_peers; 29 | #X obj 119 142 t b f; 30 | #X connect 0 0 1 1; 31 | #X connect 1 0 5 0; 32 | #X connect 3 0 1 0; 33 | #X connect 4 0 3 0; 34 | #X connect 4 0 3 0; 35 | #X connect 5 0 2 0; 36 | #X connect 5 0 2 1; 37 | #X connect 6 0 13 0; 38 | #X connect 7 0 13 0; 39 | #X connect 8 0 13 0; 40 | #X connect 9 0 6 0; 41 | #X connect 10 0 7 0; 42 | #X connect 11 0 8 0; 43 | #X connect 12 0 0 0; 44 | #X connect 13 0 24 0; 45 | #X connect 13 3 18 0; 46 | #X connect 14 0 0 0; 47 | #X connect 15 0 16 0; 48 | #X connect 15 1 17 0; 49 | #X connect 16 0 14 0; 50 | #X connect 17 0 12 0; 51 | #X connect 20 0 21 0; 52 | #X connect 21 0 13 0; 53 | #X connect 23 0 22 0; 54 | #X connect 24 0 4 0; 55 | #X connect 24 1 15 0; 56 | --------------------------------------------------------------------------------