AudioFlinger framework: simplify import, use singleton class

This commit is contained in:
Thomas Farstrike
2026-01-13 23:48:52 +01:00
parent b7db1a7fd2
commit fd548d45f1
12 changed files with 503 additions and 361 deletions
+3 -1
View File
@@ -1,10 +1,12 @@
0.5.3
0.6.0
=====
- AppStore app: add Settings screen to choose backend
- Camera app: fix aspect ratio for higher resolutions
- WiFi app: check "hidden" in EditNetwork
- Wifi app: add support for scanning wifi QR codes to "Add Network"
- Make "Power Off" button on desktop exit completely
- App framework: simplify MANIFEST.JSON
- AudioFlinger framework: simplify import, use singleton class
- Create new SettingsActivity and SettingActivity framework so apps can easily add settings screens with just a few lines of code
- Improve robustness by catching unhandled app exceptions
- Improve robustness with custom exception that does not deinit() the TaskHandler
@@ -2,7 +2,7 @@ import machine
import os
import time
from mpos import Activity, Intent, sdcard, get_event_name, audio as AudioFlinger
from mpos import Activity, Intent, sdcard, get_event_name, AudioFlinger
class MusicPlayer(Activity):
@@ -2,7 +2,7 @@
import os
import time
from mpos import Activity, ui, audio as AudioFlinger
from mpos import Activity, ui, AudioFlinger
def _makedirs(path):
+2 -1
View File
@@ -5,6 +5,7 @@ from .config import SharedPreferences
from .net.connectivity_manager import ConnectivityManager
from .net import download_manager as DownloadManager
from .net.wifi_service import WifiService
from .audio.audioflinger import AudioFlinger
from .content.intent import Intent
from .activity_navigator import ActivityNavigator
from .content.package_manager import PackageManager
@@ -61,7 +62,7 @@ __all__ = [
"App",
"Activity",
"SharedPreferences",
"ConnectivityManager", "DownloadManager", "WifiService", "Intent",
"ConnectivityManager", "DownloadManager", "WifiService", "AudioFlinger", "Intent",
"ActivityNavigator", "PackageManager", "TaskManager",
# Common activities
"ChooserActivity", "ViewActivity", "ShareActivity",
+25 -26
View File
@@ -2,37 +2,36 @@
# Android-inspired audio routing with priority-based audio focus
# Simple routing: play_wav() -> I2S, play_rtttl() -> buzzer, record_wav() -> I2S mic
from . import audioflinger
from .audioflinger import AudioFlinger
# Re-export main API
from .audioflinger import (
# Stream types (for priority-based audio focus)
STREAM_MUSIC,
STREAM_NOTIFICATION,
STREAM_ALARM,
# Create singleton instance
_instance = AudioFlinger.get()
# Core playback functions
init,
play_wav,
play_rtttl,
stop,
pause,
resume,
set_volume,
get_volume,
is_playing,
# Re-export stream type constants for convenience
STREAM_MUSIC = AudioFlinger.STREAM_MUSIC
STREAM_NOTIFICATION = AudioFlinger.STREAM_NOTIFICATION
STREAM_ALARM = AudioFlinger.STREAM_ALARM
# Recording functions
record_wav,
is_recording,
# Hardware availability checks
has_i2s,
has_buzzer,
has_microphone,
)
# Re-export main API from singleton instance for backward compatibility
init = _instance.init
play_wav = _instance.play_wav
play_rtttl = _instance.play_rtttl
stop = _instance.stop
pause = _instance.pause
resume = _instance.resume
set_volume = _instance.set_volume
get_volume = _instance.get_volume
is_playing = _instance.is_playing
record_wav = _instance.record_wav
is_recording = _instance.is_recording
has_i2s = _instance.has_i2s
has_buzzer = _instance.has_buzzer
has_microphone = _instance.has_microphone
__all__ = [
# Class
'AudioFlinger',
# Stream types
'STREAM_MUSIC',
'STREAM_NOTIFICATION',
File diff suppressed because it is too large Load Diff
@@ -291,7 +291,7 @@ mpos.sdcard.init(spi_bus, cs_pin=14)
# === AUDIO HARDWARE ===
from machine import PWM, Pin
import mpos.audio.audioflinger as AudioFlinger
from mpos import AudioFlinger
# Initialize buzzer (GPIO 46)
buzzer = PWM(Pin(46), freq=550, duty=0)
+1 -1
View File
@@ -96,7 +96,7 @@ def adc_to_voltage(adc_value):
mpos.battery_voltage.init_adc(999, adc_to_voltage)
# === AUDIO HARDWARE ===
import mpos.audio.audioflinger as AudioFlinger
from mpos import AudioFlinger
# Desktop builds have no real audio hardware, but we simulate microphone
# recording with a 440Hz sine wave for testing WAV file generation
@@ -111,7 +111,7 @@ except Exception as e:
print(f"Warning: powering off camera got exception: {e}")
# === AUDIO HARDWARE ===
import mpos.audio.audioflinger as AudioFlinger
from mpos import AudioFlinger
# Note: Waveshare board has no buzzer or I2S audio
AudioFlinger.init()
+1 -1
View File
@@ -1,4 +1,4 @@
CURRENT_OS_VERSION = "0.5.3"
CURRENT_OS_VERSION = "0.6.0"
# Unique string that defines the hardware, used by OSUpdate and the About app
_hardware_id = "missing-hardware-info"
Regular → Executable
View File
+8 -5
View File
@@ -20,7 +20,7 @@ inject_mocks({
})
# Now import the module to test
import mpos.audio.audioflinger as AudioFlinger
from mpos.audio.audioflinger import AudioFlinger
class TestAudioFlinger(unittest.TestCase):
@@ -45,8 +45,9 @@ class TestAudioFlinger(unittest.TestCase):
def test_initialization(self):
"""Test that AudioFlinger initializes correctly."""
self.assertEqual(AudioFlinger._i2s_pins, self.i2s_pins)
self.assertEqual(AudioFlinger._buzzer_instance, self.buzzer)
af = AudioFlinger.get()
self.assertEqual(af._i2s_pins, self.i2s_pins)
self.assertEqual(af._buzzer_instance, self.buzzer)
def test_has_i2s(self):
"""Test has_i2s() returns correct value."""
@@ -134,7 +135,8 @@ class TestAudioFlinger(unittest.TestCase):
def test_audio_focus_check_no_current_stream(self):
"""Test audio focus allows playback when no stream is active."""
result = AudioFlinger._check_audio_focus(AudioFlinger.STREAM_MUSIC)
af = AudioFlinger.get()
result = af._check_audio_focus(AudioFlinger.STREAM_MUSIC)
self.assertTrue(result)
def test_volume_default_value(self):
@@ -156,7 +158,8 @@ class TestAudioFlingerRecording(unittest.TestCase):
self.i2s_pins_no_mic = {'sck': 2, 'ws': 47, 'sd': 16}
# Reset state
AudioFlinger._current_recording = None
af = AudioFlinger.get()
af._current_recording = None
AudioFlinger.set_volume(70)
AudioFlinger.init(