├── 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 |
--------------------------------------------------------------------------------