Compare commits
1 Commits
experiment
...
feat/api_e
| Author | SHA1 | Date | |
|---|---|---|---|
| 8a402e90bd |
@@ -153,8 +153,6 @@
|
||||
<li><button onclick="showScreen('playlist')">Open Playlist Editor</button></li>
|
||||
<!-- More screens can be added later -->
|
||||
</ul>
|
||||
<hr>
|
||||
<button onclick="requestReboot()">Reboot to bootloader</button>
|
||||
</div>
|
||||
|
||||
<!-- CONFIG EDITOR SCREEN -->
|
||||
@@ -966,14 +964,6 @@
|
||||
|
||||
return { init, onShow };
|
||||
})();
|
||||
|
||||
// Misc
|
||||
async function requestReboot() {
|
||||
const resp = await fetch('/api/v1/reboot/bootloader', {'method': 'POST'});
|
||||
if (!resp.ok) {
|
||||
alert('Reboot to bootloader failed: ' + await resp.text());
|
||||
}
|
||||
}
|
||||
|
||||
// Initialization
|
||||
Object.values(Screens).forEach(screen => {
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
# Copyright (c) 2025 Matthias Blankertz <matthias@blankertz.org>
|
||||
|
||||
import _audiocore
|
||||
import asyncio
|
||||
from asyncio import Lock, ThreadSafeFlag
|
||||
from asyncio import ThreadSafeFlag
|
||||
from utils import get_pin_index
|
||||
|
||||
|
||||
@@ -12,34 +11,19 @@ class Audiocore:
|
||||
# PIO requires sideset pins to be adjacent
|
||||
assert get_pin_index(lrclk) == get_pin_index(dclk)+1 or get_pin_index(lrclk) == get_pin_index(dclk)-1
|
||||
self.notify = ThreadSafeFlag()
|
||||
self.audiocore_lock = Lock()
|
||||
self._audiocore = _audiocore.Audiocore(din, dclk, lrclk, self._interrupt)
|
||||
|
||||
def deinit(self):
|
||||
assert not self.audiocore_lock.locked()
|
||||
self._audiocore.deinit()
|
||||
|
||||
def _interrupt(self, _):
|
||||
self.notify.set()
|
||||
|
||||
def flush(self):
|
||||
assert not self.audiocore_lock.locked()
|
||||
self._audiocore.flush()
|
||||
|
||||
async def async_flush(self):
|
||||
async with self.audiocore_lock:
|
||||
self._audiocore.flush(False)
|
||||
while True:
|
||||
if self._audiocore.get_async_result() is not None:
|
||||
return
|
||||
await self.notify.wait()
|
||||
|
||||
async def async_set_volume(self, volume):
|
||||
async with self.audiocore_lock:
|
||||
self._audiocore.set_volume(volume)
|
||||
|
||||
def set_volume(self, volume):
|
||||
asyncio.create_task(self.async_set_volume(volume))
|
||||
self._audiocore.set_volume(volume)
|
||||
|
||||
def put(self, buffer, blocking=False):
|
||||
pos = 0
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
|
||||
// Include MicroPython API.
|
||||
#include "py/mperrno.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/persistentcode.h"
|
||||
#include "py/runtime.h"
|
||||
#include "shared/runtime/mpirq.h"
|
||||
|
||||
@@ -63,20 +61,6 @@ static uint32_t get_fifo_read_value_blocking(struct audiocore_obj *obj)
|
||||
}
|
||||
}
|
||||
|
||||
static bool get_fifo_read_value(struct audiocore_obj *obj, uint32_t *result)
|
||||
{
|
||||
const long flags = save_and_disable_interrupts();
|
||||
const uint32_t value = obj->fifo_read_value;
|
||||
obj->fifo_read_value = 0;
|
||||
if (value & AUDIOCORE_FIFO_DATA_FLAG) {
|
||||
restore_interrupts(flags);
|
||||
*result = value & ~AUDIOCORE_FIFO_DATA_FLAG;
|
||||
return true;
|
||||
}
|
||||
restore_interrupts(flags);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* audiocore.Context.deinit(self)
|
||||
*
|
||||
@@ -141,31 +125,15 @@ static MP_DEFINE_CONST_FUN_OBJ_2(audiocore_put_obj, audiocore_put);
|
||||
* Tells the audiocore to stop playback as soon as all MP3 frames still in the buffer have been decoded.
|
||||
* This function blocks until playback has ended.
|
||||
*/
|
||||
static mp_obj_t audiocore_flush(size_t n_args, const mp_obj_t *args)
|
||||
static mp_obj_t audiocore_flush(mp_obj_t self_in)
|
||||
{
|
||||
struct audiocore_obj *self = MP_OBJ_TO_PTR(args[0]);
|
||||
mp_obj_t blocking = MP_ROM_TRUE;
|
||||
if (n_args == 2) {
|
||||
blocking = args[1];
|
||||
}
|
||||
struct audiocore_obj *self = MP_OBJ_TO_PTR(self_in);
|
||||
multicore_fifo_push_blocking(AUDIOCORE_CMD_FLUSH);
|
||||
wake_core1();
|
||||
if (mp_obj_is_true(blocking))
|
||||
get_fifo_read_value_blocking(self);
|
||||
get_fifo_read_value_blocking(self);
|
||||
return mp_const_none;
|
||||
}
|
||||
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(audiocore_flush_obj, 1, 2, audiocore_flush);
|
||||
|
||||
static mp_obj_t audiocore_get_async_result(mp_obj_t self_in)
|
||||
{
|
||||
uint32_t result;
|
||||
struct audiocore_obj *self = MP_OBJ_TO_PTR(self_in);
|
||||
if (get_fifo_read_value(self, &result)) {
|
||||
return mp_obj_new_int(result);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
static MP_DEFINE_CONST_FUN_OBJ_1(audiocore_get_async_result_obj, audiocore_get_async_result);
|
||||
static MP_DEFINE_CONST_FUN_OBJ_1(audiocore_flush_obj, audiocore_flush);
|
||||
|
||||
/*
|
||||
* audiocore.set_volume(self, volume)
|
||||
@@ -272,7 +240,6 @@ static const mp_rom_map_elem_t audiocore_locals_dict_table[] = {
|
||||
{MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&audiocore_deinit_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_put), MP_ROM_PTR(&audiocore_put_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&audiocore_flush_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_get_async_result), MP_ROM_PTR(&audiocore_get_async_result_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_set_volume), MP_ROM_PTR(&audiocore_set_volume_obj)},
|
||||
};
|
||||
static MP_DEFINE_CONST_DICT(audiocore_locals_dict, audiocore_locals_dict_table);
|
||||
|
||||
@@ -196,5 +196,8 @@ class PlayerApp:
|
||||
def get_playlist_db(self):
|
||||
return self.playlist_db
|
||||
|
||||
def get_timer_manager(self):
|
||||
return self.timer_manager
|
||||
|
||||
def get_leds(self):
|
||||
return self.leds
|
||||
|
||||
@@ -74,7 +74,7 @@ class MP3Player:
|
||||
# Call onPlaybackDone after flush
|
||||
send_done = True
|
||||
finally:
|
||||
await self.audiocore.async_flush()
|
||||
self.audiocore.flush()
|
||||
if send_done:
|
||||
# Only call onPlaybackDone if exit due to end of stream
|
||||
# Use timer with time 0 to call callback "immediately" but from a different task
|
||||
|
||||
@@ -34,7 +34,7 @@ def start_webserver(config_, app_):
|
||||
nfc = app.get_nfc()
|
||||
playlist_db = app.get_playlist_db()
|
||||
leds = app.get_leds()
|
||||
timer_manager = TimerManager()
|
||||
timer_manager = app.get_timer_manager()
|
||||
|
||||
|
||||
@webapp.before_request
|
||||
@@ -259,12 +259,12 @@ async def audiofile_delete(request):
|
||||
@webapp.route('/api/v1/reboot/<method>', methods=['POST'])
|
||||
async def reboot(request, method):
|
||||
if hwconfig.get_on_battery():
|
||||
return 'not allowed: usb not connected', 403
|
||||
return 'not allowed: no vbus', 403
|
||||
|
||||
if method == 'bootloader':
|
||||
leds.set_state(LedManager.REBOOTING)
|
||||
timer_manager.schedule(time.ticks_ms() + 1500, machine.bootloader)
|
||||
elif method == 'application':
|
||||
elif method =='application':
|
||||
leds.set_state(LedManager.REBOOTING)
|
||||
timer_manager.schedule(time.ticks_ms() + 1500, machine.reset)
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user