AdLib music player library for Android
AndPlugLib is an AdLib music player library for Android, using the AdPlug sound player library. Android audio playback and AdPlug native library control is implemented as an application service, with interfaces provided for player control and status callbacks. A separate helper class is also provided, for managing service lifecycle and monitoring the connection state.
AndPlugLib is used in AndPlug music player application for Android devices.
- Android 4.0.3 (API Level: 15) or later (
ICE_CREAM_SANDWICH_MR1) - CMake Release 3.4.1 or later
- Android Gradle Plugin 8.11.1) or later (
gradle:8.11.1) - AdPlug Version 2.3.3 (branch/tag:
release-2.3.3) - libbinio Version 1.5 (tag:
libbionio-1.5) - Oboe Version 1.7.0 (branch:
1.7-stable)
Setup steps:
- Check out a local copy of AndPlugLib repository
- Check out local copies of AdPlug, libbinio, and Oboe libraries under
andpluglib/src/main/cpp - Apply patches to AdPlug and libbinio
- Build library with Gradle, using Android Studio or directly from the command line
$ git clone https://github.com/omicronapps/AndPlugLib.git
$ cd AndPlugLib/andpluglib/src/main/cpp/
$ git clone --branch release-2.3.3 https://github.com/adplug/adplug.git
$ patch adplug/src/version.h -i adplug.patch
$ git clone https://github.com/adplug/libbinio.git
$ patch libbinio/src/binio.h -i libbinio.patch
$ git clone --branch 1.6-stable https://github.com/google/oboe.git
AndPlugLib includes both instrumented unit tests and a simple test application.
Located under andpluglib/src/androidTest.
These tests are run on a hardware device or emulator, and verifies correct operation of the PlayerService implementation and its usage of the native AdPlug library. A set of songs need to be downloaded and installed in order to run the instrumented tests.
Setup steps:
cd AndPlugLib/andpluglib/src/androidTest/res/raw/
wget http://modland.com/pub/modules/Ad%20Lib/EdLib%20D00/MSK/en%20lille%20test.d00 en_lille_test_d00
wget http://modland.com/pub/modules/Ad%20Lib/EdLib%20D00/MSK/fresh.d00 fresh_d00
wget http://modland.com/pub/modules/Ad%20Lib/EdLib%20D00/JCH/gone.d00 gone_d00
wget http://modland.com/pub/modules/Ad%20Lib/EdLib%20D00/Drax/coop-Metal/super%20nova.d00 super_nova_d00
wget http://modland.com/pub/modules/Ad%20Lib/EdLib%20D00/JCH/the%20alibi.d00 the_alibi_d00
Located under app/src/main.
Uses hardcoded path to EdLib songs for playback testing (can be replaced by any other AdPlug compatible songs).
Setup steps:
cd AndPlugLib/app/src/main/assets/
wget http://modland.com/pub/modules/Ad%20Lib/EdLib%20D00/MSK/en%20lille%20test.d00
wget http://modland.com/pub/modules/Ad%20Lib/EdLib%20D00/MSK/fresh.d00
wget http://modland.com/pub/modules/Ad%20Lib/EdLib%20D00/JCH/gone.d00
wget http://modland.com/pub/modules/Ad%20Lib/EdLib%20D00/Drax/coop-Metal/super%20nova.d00
wget http://modland.com/pub/modules/Ad%20Lib/EdLib%20D00/JCH/the%20alibi.d00
AndPlugLib is controlled through the following class and interfaces:
PlayerController- service management classIPlayer- player service interfaceIAndPlugCallback- callback interface
Manages an instance of the PlayerService application service.
PlayerController(IAndPlugCallback callback, Context context)
Constructor for the PlayerController class.
Arguments:
callback- allows registering for callbacks through theIAndPlugCallbackinterfacecontext- required in order forPlayerControllerto manage the application service
void create()
Create and connect (bind) to PlayerService application service. While the service is running, PlayerController monitors its state, and provides callbacks to a registered listener through IAndPlugCallback interface.
boolean destroy()
Disconnect (unbind) from the application service.
void restart()
Convenience method combining create() and destroy() methods.
IPlayer getService()
Returns a reference to a PlayerService instance. Only valid between onServiceConnected() and onServiceDisconnected() callbacks of IAndPlugCallback!
void initialize(Opl emu, int rate, boolean oboe, boolean usestereo, int buffers)
Create native AdPlug instance and initialize AudioTrack. Confirmed initialized if onNewState() callback returns PlayerState.CREATED.
Arguments:
emu- OPL emulatorrate- sample rate (Hz)oboe- Use native OpenSL ES/AAudio playback through Oboeusestereo- true: stereo, false: monobuffers- AdPlug buffer size (bytes)
void uninitialize()
Destroy native AdPlug instance and release AudioTrack. Confirmed destroyed if onNewState() callback returns PlayerState.DEFAULT.
void load(String song)
Loads AdPlug compatible song for playback. Ready for playback if onNewState() callback returns PlayerState.LOADED.
Argument:
song- full path to song
Unload song. Song unloaded once onNewState() callback returns PlayerState.CREATED.
void unload()
void play()
Start playback. Song playback started once onNewState() callback returns PlayerState.PLAYING.
void pause()
Pause playback. Song playback paused once onNewState() callback returns PlayerState.PAUSED.
void stop()
Stop playback. Song playback stopped once onNewState() callback returns PlayerState.STOPPED.
void seek(long ms)
Seek to new position in song.
void rewind(int subsong)
Select sub-song.
Argument:
subsong- index of sub-song
void setRepeat(boolean repeat)
Control repeat behavior of current song.
Argument:
repeat- true: repeat song indefinitely, false: skip to next song at end of current song
void songInfo(String song, long length)
Control repeat behavior of current song.
Argument:
song- full path to songlength- file length
boolean getRepeat()
Return whether current song is on repeat.
String getSong()
Return song file name.
long getSonglength(int subsong)
Return length of song in ms.
String getTitle()
Return song title.
String getAuthor()
Return song author.
String getDesc()
Return song description.
int getSubsongs()
Get number of sub-songs.
int getSubsong()
Get current sub-songs.
void debugPath(boolean audioTrack, boolean opl, String path)
Debug use only! Output PCM data to file.
Arguments:
audioTrack- write PCM data from Java codeopl- write PCM data from native codepath- path to store PCM data
PlayerState getState()
Return playback state.
Callback interface from PlayerService application service instance.
void onServiceConnected()
Application service connected. PlayerController.getService() may be used to retrieve a reference to a PlayerService instance following this callback.
void onServiceDisconnected()
Application service disconnected. Any reference to the PlayerService instance is now invalid.
void onNewState(IPlayer.PlayerRequest request, IPlayer.PlayerState state)
Notification of new PlayerService state.
request- requested statestate- actual state
void onSongInfo(String song, String type, String title, String author, String desc, long length, long songlength, int subsongs, boolean valid, boolean playlist)
Song information from AdPlug.
song- full path to songtype- song typetitle- titleauthor- authordesc- descriptionlength- file lengthsonglength- length of song in mssubsongs- number of subsongsvalid- valid AdPlug songplaylist- playlist
void onTime(long ms, long length)
Playback time and song length.
valid- current playback time in msplaylist- total song length in ms
Implement IAndPlugCallback callback interface:
import com.omicronapplications.andpluglib.IAndPlugCallback;
import com.omicronapplications.andpluglib.IPlayer;
class AndPlugCallback implements IAndPlugCallback {
@Override
public void onServiceConnected() {
// Bound to PlayerService, retrieve IPlayer instance
IPlayer player = mController.getService();
}
@Override
public void onServiceDisconnected() {
// Unbound from PlayerService, IPlayer instance unusable
}
@Override
public void onNewState(IPlayer.PlayerRequest request, IPlayer.PlayerState state) {
// Requested and actual state reported
}
@Override
public void onSongInfo(String song, String type, String title, String author, String desc, long length, long songlength, int subsongs, boolean valid, boolean playlist) {
// Song information
}
@Override
public void onTime(long ms, long length) {
// Playback time and song length
}
}
Load native library, and create a PlayerController instance to bind to PlayerService:
import com.omicronapplications.andpluglib.PlayerController;
System.loadLibrary("andplug");
IAndPlugCallback callback = new AndPlugCallback();
PlayerController controller = new PlayerController(callback, getApplicationContext());
controller.create();
Retrieve IPlayer object on IAndPlugCallback.onServiceConnected() callback, and create player instance:
import com.omicronapplications.andpluglib.IPlayer;
IPlayer player = mController.getService();
player.initialize(IPlayer.Opl.OPL_CEMU, 44100, false, false, 1024);
player.load("the alibi.d00");
player.play();
Stop playback and unload song:
player.stop();
player.unload();
player.uninitialize();
Destroy PlayerController instance to unbind from PlayerService:
controller.destroy();
Copyright (C) 2019-2025 Fredrik Claesson
- 1.0.0 Initial release
- 1.1.0 Player service refactored
- 1.2.0 Updated to AdPlug v2.3.2 and libbinio v1.5, migrated to AndroidX
- 1.3.0 Updated to AdPlug v2.3.3, improved error handling
- 1.4.0 Fixed bug in error reporting
- 1.5.0 Improvements to buffer management and error reporting
- 1.6.0 Improved lower latency player, support for choice of OPL emulator
- 1.7.0 Support for native OpenSL ES/AAudio playback, fixed playback quality issue
- 1.8.0 Fixed crash regression issue due to unallowed concurrent access to Copl and CPlayer
- 1.9.0 Fixed issue with some song formats not repeating
- 2.0.0 Support for retrieving song info separately
- 2.1.0 Include detection for M3U playlist files
- 2.2.0 JNI bug fix
- 2.3.0 Added playback position reporting, updated to Oboe v1.6.1, native playback bug fix
- 2.4.0 Fix player crash on exit
- 2.5.0 Additional player crash fixes
- 2.6.0 Updated to Oboe v1.7.0, minor bugfixes, change to Apache License Version 2.0
- 2.7.0 Fix for audio focus issue, use 16 KB ELF alignment, target Android 15 (API level 35)
AndPlugLib is licensed under Apache License Version 2.0.