Skip to content

Commit 96118b2

Browse files
committed
android: implement android backend
1 parent 64e861a commit 96118b2

File tree

14 files changed

+866
-3
lines changed

14 files changed

+866
-3
lines changed

.gitignore

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,86 @@ build
9393

9494
.vscode
9595

96+
### Generated by gibo (https://github.com/simonwhitaker/gibo)
97+
### https://raw.github.com/github/gitignore/15d684578f37580886f29e4b8462f3a27f722cb5/Android.gitignore
98+
99+
# Gradle files
100+
.gradle/
101+
build/
102+
103+
# Local configuration file (sdk path, etc)
104+
local.properties
105+
106+
# Log/OS Files
107+
*.log
108+
109+
# Android Studio generated files and folders
110+
captures/
111+
.externalNativeBuild/
112+
.cxx/
113+
*.aab
114+
*.apk
115+
output-metadata.json
116+
117+
# IntelliJ
118+
*.iml
119+
.idea/
120+
misc.xml
121+
deploymentTargetDropDown.xml
122+
render.experimental.xml
123+
124+
# Keystore files
125+
*.jks
126+
*.keystore
127+
128+
# Google Services (e.g. APIs or Firebase)
129+
google-services.json
130+
131+
# Android Profiling
132+
*.hprof
133+
### Generated by gibo (https://github.com/simonwhitaker/gibo)
134+
### https://raw.github.com/github/gitignore/15d684578f37580886f29e4b8462f3a27f722cb5/Gradle.gitignore
135+
136+
.gradle
137+
**/build/
138+
!**/src/**/build/
139+
140+
# Ignore Gradle GUI config
141+
gradle-app.setting
142+
143+
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
144+
!gradle-wrapper.jar
145+
146+
# Avoid ignore Gradle wrappper properties
147+
!gradle-wrapper.properties
148+
149+
# Cache of project
150+
.gradletasknamecache
151+
152+
# Eclipse Gradle plugin generated files
153+
# Eclipse Core
154+
.project
155+
# JDT-specific (Eclipse Java Development Tools)
156+
.classpath
157+
### Generated by gibo (https://github.com/simonwhitaker/gibo)
158+
### https://raw.github.com/github/gitignore/15d684578f37580886f29e4b8462f3a27f722cb5/CMake.gitignore
159+
160+
CMakeLists.txt.user
161+
CMakeCache.txt
162+
CMakeFiles
163+
CMakeScripts
164+
Testing
165+
Makefile
166+
cmake_install.cmake
167+
install_manifest.txt
168+
compile_commands.json
169+
CTestTestfile.cmake
170+
_deps
171+
CMakeUserPresets.json
172+
173+
# CLion
174+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
175+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
176+
# and can be added to the global gitignore or merged into this file. For a more nuclear
177+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
178+
#cmake-build-*

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ option(LIBREMIDI_NO_JACK "Disable JACK back-end" OFF)
3535
option(LIBREMIDI_NO_PIPEWIRE "Disable PipeWire back-end" OFF)
3636
option(LIBREMIDI_NO_NETWORK "Disable Network back-end" OFF)
3737
option(LIBREMIDI_NO_KEYBOARD "Disable Computer keyboard back-end" OFF)
38+
cmake_dependent_option(LIBREMIDI_NO_ANDROID "Disable Android AMidi back-end" OFF "ANDROID" OFF)
3839

3940
option(LIBREMIDI_NO_EXPORTS "Disable dynamic symbol exporting" OFF)
4041
option(LIBREMIDI_NO_BOOST "Do not use Boost if available" OFF)
@@ -70,6 +71,7 @@ include(libremidi.jack)
7071
include(libremidi.pipewire)
7172
include(libremidi.keyboard)
7273
include(libremidi.net)
74+
include(libremidi.android)
7375

7476
### Install ###
7577
include(libremidi.install)

cmake/libremidi.android.cmake

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
### Android ###
2+
if(ANDROID AND NOT LIBREMIDI_NO_ANDROID)
3+
# Check for AMidi API availability (API level 29+)
4+
# Also we need API 31+ for JNI_GetCreatedJavaVMs
5+
if(ANDROID_NATIVE_API_LEVEL AND ANDROID_NATIVE_API_LEVEL GREATER_EQUAL 31)
6+
message(STATUS "libremidi: Using Android AMidi API")
7+
message(STATUS " !!! Remember to include MidiDeviceCallback.java in your Android app")
8+
message(STATUS " !!! See the example in examples/android/java/dev/celtera/libremidi")
9+
10+
target_compile_definitions(libremidi ${_public} LIBREMIDI_ANDROID=1)
11+
target_link_libraries(libremidi ${_public} amidi log nativehelper)
12+
target_sources(libremidi ${_public}
13+
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/libremidi/backends/android/helpers.cpp>"
14+
)
15+
else()
16+
message(FATAL_ERROR "libremidi: Android AMidi API requires API level 31+ (current: ${ANDROID_NATIVE_API_LEVEL})")
17+
endif()
18+
endif()

include/libremidi/api-c.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ typedef enum libremidi_api
2222
PIPEWIRE, /*!< PipeWire */
2323
KEYBOARD, /*!< Computer keyboard input */
2424
NETWORK, /*!< MIDI over IP */
25+
ANDROID_AMIDI, /*!< Android AMidi API */
2526

2627
// MIDI 2.0 APIs
2728
ALSA_RAW_UMP = 0x1000, /*!< Raw ALSA API for MIDI 2.0 */

include/libremidi/api.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ inline constexpr libremidi::API default_api() noexcept
6464
return API::ALSA_SEQ;
6565
#elif defined(__emscripten__)
6666
return API::EMSCRIPTEN_WEBMIDI;
67+
#elif defined(LIBREMIDI_ANDROID)
68+
return API::ANDROID_AMIDI;
6769
#else
6870
return API::DUMMY;
6971
#endif

include/libremidi/backends.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@
7171
#include <libremidi/backends/network_ump.hpp>
7272
#endif
7373

74+
#if defined(LIBREMIDI_ANDROID)
75+
#include <libremidi/backends/android/android.hpp>
76+
#endif
77+
7478
namespace libremidi
7579
{
7680
// The order here will control the order of the API search in
@@ -124,6 +128,10 @@ static constexpr auto available_backends = make_tl(
124128
#if defined(LIBREMIDI_NETWORK)
125129
,
126130
net::backend{}
131+
#endif
132+
#if defined(LIBREMIDI_ANDROID)
133+
,
134+
android::backend{}
127135
#endif
128136
,
129137
dummy_backend{});
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#pragma once
2+
#include <libremidi/backends/android/config.hpp>
3+
#include <libremidi/backends/android/midi_in.hpp>
4+
#include <libremidi/backends/android/midi_out.hpp>
5+
#include <libremidi/backends/android/observer.hpp>
6+
7+
namespace libremidi
8+
{
9+
namespace android
10+
{
11+
struct backend
12+
{
13+
using midi_in = android::midi_in;
14+
using midi_out = android::midi_out;
15+
using midi_observer = android::observer;
16+
using midi_in_configuration = android::input_configuration;
17+
using midi_out_configuration = android::output_configuration;
18+
using midi_observer_configuration = android::observer_configuration;
19+
static const constexpr auto API = libremidi::API::ANDROID_AMIDI;
20+
static const constexpr std::string_view name = "android";
21+
static const constexpr std::string_view display_name = "Android MIDI API";
22+
23+
static bool available() noexcept
24+
{
25+
#if defined(__ANDROID__)
26+
return true;
27+
#else
28+
return false;
29+
#endif
30+
}
31+
};
32+
}
33+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#pragma once
2+
#include <libremidi/config.hpp>
3+
4+
namespace libremidi
5+
{
6+
namespace android
7+
{
8+
struct input_configuration
9+
{
10+
std::string_view client_name = "libremidi client";
11+
};
12+
13+
struct output_configuration
14+
{
15+
std::string_view client_name = "libremidi client";
16+
};
17+
18+
struct observer_configuration
19+
{
20+
std::string_view client_name = "libremidi client";
21+
};
22+
}
23+
}

0 commit comments

Comments
 (0)