diff --git a/extmod/machine_i2c.c b/extmod/machine_i2c.c index 85b46a9f6b..4129ace0a0 100644 --- a/extmod/machine_i2c.c +++ b/extmod/machine_i2c.c @@ -318,7 +318,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_init_obj, 1, machine_i2c_obj_init); STATIC mp_obj_t machine_i2c_scan(mp_obj_t self_in) { mp_obj_base_t *self = MP_OBJ_TO_PTR(self_in); - mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; + mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c); mp_obj_t list = mp_obj_new_list(0, NULL); // 7-bit addresses 0b0000xxx and 0b1111xxx are reserved for (int addr = 0x08; addr < 0x78; ++addr) { @@ -333,7 +333,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_scan_obj, machine_i2c_scan); STATIC mp_obj_t machine_i2c_start(mp_obj_t self_in) { mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in); - mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; + mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c); if (i2c_p->start == NULL) { mp_raise_msg(&mp_type_OSError, translate("I2C operation not supported")); } @@ -347,7 +347,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_start_obj, machine_i2c_start); STATIC mp_obj_t machine_i2c_stop(mp_obj_t self_in) { mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in); - mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; + mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c); if (i2c_p->stop == NULL) { mp_raise_msg(&mp_type_OSError, translate("I2C operation not supported")); } @@ -361,7 +361,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_stop_obj, machine_i2c_stop); STATIC mp_obj_t machine_i2c_readinto(size_t n_args, const mp_obj_t *args) { mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]); - mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; + mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c); if (i2c_p->read == NULL) { mp_raise_msg(&mp_type_OSError, translate("I2C operation not supported")); } @@ -385,7 +385,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readinto_obj, 2, 3, machine_i2c_ STATIC mp_obj_t machine_i2c_write(mp_obj_t self_in, mp_obj_t buf_in) { mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in); - mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; + mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c); if (i2c_p->write == NULL) { mp_raise_msg(&mp_type_OSError, translate("I2C operation not supported")); } @@ -407,7 +407,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(machine_i2c_write_obj, machine_i2c_write); STATIC mp_obj_t machine_i2c_readfrom(size_t n_args, const mp_obj_t *args) { mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]); - mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; + mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c); mp_int_t addr = mp_obj_get_int(args[1]); vstr_t vstr; vstr_init_len(&vstr, mp_obj_get_int(args[2])); @@ -422,7 +422,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readfrom_obj, 3, 4, machine_i2c_ STATIC mp_obj_t machine_i2c_readfrom_into(size_t n_args, const mp_obj_t *args) { mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]); - mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; + mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c); mp_int_t addr = mp_obj_get_int(args[1]); mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_WRITE); @@ -437,7 +437,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_readfrom_into_obj, 3, 4, machine STATIC mp_obj_t machine_i2c_writeto(size_t n_args, const mp_obj_t *args) { mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]); - mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; + mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c); mp_int_t addr = mp_obj_get_int(args[1]); mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); @@ -453,7 +453,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_writeto_obj, 3, 4, machin STATIC int read_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t addrsize, uint8_t *buf, size_t len) { mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in); - mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; + mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c); uint8_t memaddr_buf[4]; size_t memaddr_len = 0; for (int16_t i = addrsize - 8; i >= 0; i -= 8) { @@ -473,7 +473,7 @@ STATIC int read_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t a STATIC int write_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t addrsize, const uint8_t *buf, size_t len) { mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in); - mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol; + mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)mp_proto_get(self, QSTR_protocol_i2c); // need some memory to create the buffer to send; try to use stack if possible uint8_t buf2_stack[MAX_MEMADDR_SIZE + BUF_STACK_SIZE]; @@ -621,6 +621,7 @@ int mp_machine_soft_i2c_write(mp_obj_base_t *self_in, const uint8_t *src, size_t } STATIC const mp_machine_i2c_p_t mp_machine_soft_i2c_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_i2c) .start = (int(*)(mp_obj_base_t*))mp_hal_i2c_start, .stop = (int(*)(mp_obj_base_t*))mp_hal_i2c_stop, .read = mp_machine_soft_i2c_read, diff --git a/extmod/machine_i2c.h b/extmod/machine_i2c.h index f5af6656f5..7f5ee568e3 100644 --- a/extmod/machine_i2c.h +++ b/extmod/machine_i2c.h @@ -27,10 +27,12 @@ #define MICROPY_INCLUDED_EXTMOD_MACHINE_I2C_H #include "py/obj.h" +#include "py/proto.h" // I2C protocol // the first 4 methods can be NULL, meaning operation is not supported typedef struct _mp_machine_i2c_p_t { + MP_PROTOCOL_HEAD int (*start)(mp_obj_base_t *obj); int (*stop)(mp_obj_base_t *obj); int (*read)(mp_obj_base_t *obj, uint8_t *dest, size_t len, bool nack); diff --git a/extmod/machine_pinbase.c b/extmod/machine_pinbase.c index 997a6fd991..6cd14c187e 100644 --- a/extmod/machine_pinbase.c +++ b/extmod/machine_pinbase.c @@ -74,6 +74,7 @@ mp_uint_t pinbase_ioctl(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *err } STATIC const mp_pin_p_t pinbase_pin_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_pin) .ioctl = pinbase_ioctl, }; diff --git a/extmod/machine_signal.c b/extmod/machine_signal.c index 62658cbb17..50501e34fe 100644 --- a/extmod/machine_signal.c +++ b/extmod/machine_signal.c @@ -47,12 +47,7 @@ STATIC mp_obj_t signal_make_new(const mp_obj_type_t *type, size_t n_args, const bool invert = false; #if defined(MICROPY_PY_MACHINE_PIN_MAKE_NEW) - mp_pin_p_t *pin_p = NULL; - - if (MP_OBJ_IS_OBJ(pin)) { - mp_obj_base_t *pin_base = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]); - pin_p = (mp_pin_p_t*)pin_base->type->protocol; - } + mp_pin_p_t *pin_p = (mp_pin_t*)mp_proto_get(QSTR_pin_protocol, pin); if (pin_p == NULL) { // If first argument isn't a Pin-like object, we filter out "invert" @@ -170,6 +165,7 @@ STATIC const mp_rom_map_elem_t signal_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(signal_locals_dict, signal_locals_dict_table); STATIC const mp_pin_p_t signal_pin_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_pin) .ioctl = signal_ioctl, }; diff --git a/extmod/machine_spi.c b/extmod/machine_spi.c index c5707a3d0b..4ead321d90 100644 --- a/extmod/machine_spi.c +++ b/extmod/machine_spi.c @@ -67,7 +67,7 @@ mp_obj_t mp_machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, const STATIC mp_obj_t machine_spi_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { mp_obj_base_t *s = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]); - mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t*)s->type->protocol; + mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t*)mp_proto_get(QSTR_protocol_spi, s); spi_p->init(s, n_args - 1, args + 1, kw_args); return mp_const_none; } @@ -75,7 +75,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_spi_init_obj, 1, machine_spi_init); STATIC mp_obj_t machine_spi_deinit(mp_obj_t self) { mp_obj_base_t *s = (mp_obj_base_t*)MP_OBJ_TO_PTR(self); - mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t*)s->type->protocol; + mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t*)mp_proto_get(QSTR_protocol_spi, s); if (spi_p->deinit != NULL) { spi_p->deinit(s); } @@ -85,7 +85,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_spi_deinit_obj, machine_spi_deinit); STATIC void mp_machine_spi_transfer(mp_obj_t self, size_t len, const void *src, void *dest) { mp_obj_base_t *s = (mp_obj_base_t*)MP_OBJ_TO_PTR(self); - mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t*)s->type->protocol; + mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t*)mp_proto_get(QSTR_protocol_spi, s); spi_p->transfer(s, len, src, dest); } @@ -268,6 +268,7 @@ STATIC void mp_machine_soft_spi_transfer(mp_obj_base_t *self_in, size_t len, con } const mp_machine_spi_p_t mp_machine_soft_spi_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_spi) .init = mp_machine_soft_spi_init, .deinit = NULL, .transfer = mp_machine_soft_spi_transfer, diff --git a/extmod/machine_spi.h b/extmod/machine_spi.h index db21e1cd31..365b44d6e8 100644 --- a/extmod/machine_spi.h +++ b/extmod/machine_spi.h @@ -27,11 +27,13 @@ #define MICROPY_INCLUDED_EXTMOD_MACHINE_SPI_H #include "py/obj.h" +#include "py/proto.h" #include "py/mphal.h" #include "drivers/bus/spi.h" // SPI protocol typedef struct _mp_machine_spi_p_t { + MP_PROTOCOL_HEAD void (*init)(mp_obj_base_t *obj, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); void (*deinit)(mp_obj_base_t *obj); // can be NULL void (*transfer)(mp_obj_base_t *obj, size_t len, const uint8_t *src, uint8_t *dest); diff --git a/extmod/modframebuf.c b/extmod/modframebuf.c index 561b842bcc..a51d1c3804 100644 --- a/extmod/modframebuf.c +++ b/extmod/modframebuf.c @@ -28,6 +28,7 @@ #include #include "py/runtime.h" +#include "py/proto.h" #if MICROPY_PY_FRAMEBUF @@ -46,6 +47,7 @@ typedef uint32_t (*getpixel_t)(const mp_obj_framebuf_t*, int, int); typedef void (*fill_rect_t)(const mp_obj_framebuf_t *, int, int, int, int, uint32_t); typedef struct _mp_framebuf_p_t { + MP_PROTOCOL_HEAD setpixel_t setpixel; getpixel_t getpixel; fill_rect_t fill_rect; @@ -227,13 +229,13 @@ STATIC void gs8_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int } STATIC mp_framebuf_p_t formats[] = { - [FRAMEBUF_MVLSB] = {mvlsb_setpixel, mvlsb_getpixel, mvlsb_fill_rect}, - [FRAMEBUF_RGB565] = {rgb565_setpixel, rgb565_getpixel, rgb565_fill_rect}, - [FRAMEBUF_GS2_HMSB] = {gs2_hmsb_setpixel, gs2_hmsb_getpixel, gs2_hmsb_fill_rect}, - [FRAMEBUF_GS4_HMSB] = {gs4_hmsb_setpixel, gs4_hmsb_getpixel, gs4_hmsb_fill_rect}, - [FRAMEBUF_GS8] = {gs8_setpixel, gs8_getpixel, gs8_fill_rect}, - [FRAMEBUF_MHLSB] = {mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect}, - [FRAMEBUF_MHMSB] = {mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect}, + [FRAMEBUF_MVLSB] = {MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuf) mvlsb_setpixel, mvlsb_getpixel, mvlsb_fill_rect}, + [FRAMEBUF_RGB565] = {MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuf) rgb565_setpixel, rgb565_getpixel, rgb565_fill_rect}, + [FRAMEBUF_GS2_HMSB] = {MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuf) gs2_hmsb_setpixel, gs2_hmsb_getpixel, gs2_hmsb_fill_rect}, + [FRAMEBUF_GS4_HMSB] = {MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuf) gs4_hmsb_setpixel, gs4_hmsb_getpixel, gs4_hmsb_fill_rect}, + [FRAMEBUF_GS8] = {MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuf) gs8_setpixel, gs8_getpixel, gs8_fill_rect}, + [FRAMEBUF_MHLSB] = {MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuf) mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect}, + [FRAMEBUF_MHMSB] = {MP_PROTO_IMPLEMENT(MP_QSTR_protocol_framebuf) mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect}, }; static inline void setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t col) { diff --git a/extmod/modlwip.c b/extmod/modlwip.c index e5e92c42b5..776b81ee51 100644 --- a/extmod/modlwip.c +++ b/extmod/modlwip.c @@ -1261,6 +1261,7 @@ STATIC const mp_rom_map_elem_t lwip_socket_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(lwip_socket_locals_dict, lwip_socket_locals_dict_table); STATIC const mp_stream_p_t lwip_socket_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = lwip_socket_read, .write = lwip_socket_write, .ioctl = lwip_socket_ioctl, diff --git a/extmod/modussl_axtls.c b/extmod/modussl_axtls.c index cfa6525853..032dea09fd 100644 --- a/extmod/modussl_axtls.c +++ b/extmod/modussl_axtls.c @@ -221,6 +221,7 @@ STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(ussl_socket_locals_dict, ussl_socket_locals_dict_table); STATIC const mp_stream_p_t ussl_socket_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = socket_read, .write = socket_write, .ioctl = socket_ioctl, diff --git a/extmod/modussl_mbedtls.c b/extmod/modussl_mbedtls.c index 08807d20ba..9abdeb966e 100644 --- a/extmod/modussl_mbedtls.c +++ b/extmod/modussl_mbedtls.c @@ -305,6 +305,7 @@ STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(ussl_socket_locals_dict, ussl_socket_locals_dict_table); STATIC const mp_stream_p_t ussl_socket_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = socket_read, .write = socket_write, .ioctl = socket_ioctl, diff --git a/extmod/moduzlib.c b/extmod/moduzlib.c index 7f15d02a8e..3a081bc452 100644 --- a/extmod/moduzlib.c +++ b/extmod/moduzlib.c @@ -134,6 +134,7 @@ STATIC const mp_rom_map_elem_t decompio_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(decompio_locals_dict, decompio_locals_dict_table); STATIC const mp_stream_p_t decompio_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = decompio_read, }; diff --git a/extmod/modwebrepl.c b/extmod/modwebrepl.c index 06da210d15..fb4d97358d 100644 --- a/extmod/modwebrepl.c +++ b/extmod/modwebrepl.c @@ -331,6 +331,7 @@ STATIC const mp_rom_map_elem_t webrepl_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(webrepl_locals_dict, webrepl_locals_dict_table); STATIC const mp_stream_p_t webrepl_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = webrepl_read, .write = webrepl_write, .ioctl = webrepl_ioctl, diff --git a/extmod/modwebsocket.c b/extmod/modwebsocket.c index 997c7e2625..496e4b5bb3 100644 --- a/extmod/modwebsocket.c +++ b/extmod/modwebsocket.c @@ -286,6 +286,7 @@ STATIC const mp_rom_map_elem_t websocket_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(websocket_locals_dict, websocket_locals_dict_table); STATIC const mp_stream_p_t websocket_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = websocket_read, .write = websocket_write, .ioctl = websocket_ioctl, diff --git a/extmod/vfs.c b/extmod/vfs.c index 7d6e6999bd..2bb4057e7e 100644 --- a/extmod/vfs.c +++ b/extmod/vfs.c @@ -126,7 +126,7 @@ mp_import_stat_t mp_vfs_import_stat(const char *path) { } // If the mounted object has the VFS protocol, call its import_stat helper - const mp_vfs_proto_t *proto = mp_obj_get_type(vfs->obj)->protocol; + const mp_vfs_proto_t *proto = (mp_vfs_proto_t*)mp_proto_get(MP_QSTR_protocol_vfs, vfs->obj); if (proto != NULL) { return proto->import_stat(MP_OBJ_TO_PTR(vfs->obj), path_out); } diff --git a/extmod/vfs.h b/extmod/vfs.h index 38c77943c7..6c0692365f 100644 --- a/extmod/vfs.h +++ b/extmod/vfs.h @@ -28,6 +28,7 @@ #include "py/lexer.h" #include "py/obj.h" +#include "py/proto.h" // return values of mp_vfs_lookup_path // ROOT is 0 so that the default current directory is the root directory @@ -47,6 +48,7 @@ // At the moment the VFS protocol just has import_stat, but could be extended to other methods typedef struct _mp_vfs_proto_t { + MP_PROTOCOL_HEAD mp_import_stat_t (*import_stat)(void *self, const char *path); } mp_vfs_proto_t; diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index 20d3e3e5ce..60f4393f43 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -488,6 +488,7 @@ STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(fat_vfs_locals_dict, fat_vfs_locals_dict_table); STATIC const mp_vfs_proto_t fat_vfs_proto = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_vfs) .import_stat = fat_vfs_import_stat, }; diff --git a/extmod/vfs_fat_file.c b/extmod/vfs_fat_file.c index 6aad1884cb..3ea9cee529 100644 --- a/extmod/vfs_fat_file.c +++ b/extmod/vfs_fat_file.c @@ -254,6 +254,7 @@ STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table); #if MICROPY_PY_IO_FILEIO STATIC const mp_stream_p_t fileio_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = file_obj_read, .write = file_obj_write, .ioctl = file_obj_ioctl, @@ -272,6 +273,7 @@ const mp_obj_type_t mp_type_vfs_fat_fileio = { #endif STATIC const mp_stream_p_t textio_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = file_obj_read, .write = file_obj_write, .ioctl = file_obj_ioctl, diff --git a/extmod/vfs_posix.c b/extmod/vfs_posix.c index d28dfe4516..56a5de303d 100644 --- a/extmod/vfs_posix.c +++ b/extmod/vfs_posix.c @@ -350,6 +350,7 @@ STATIC const mp_rom_map_elem_t vfs_posix_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(vfs_posix_locals_dict, vfs_posix_locals_dict_table); STATIC const mp_vfs_proto_t vfs_posix_proto = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_vfs) .import_stat = mp_vfs_posix_import_stat, }; diff --git a/extmod/vfs_posix_file.c b/extmod/vfs_posix_file.c index b760b38474..be455fa281 100644 --- a/extmod/vfs_posix_file.c +++ b/extmod/vfs_posix_file.c @@ -220,6 +220,7 @@ STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table); #if MICROPY_PY_IO_FILEIO STATIC const mp_stream_p_t fileio_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = vfs_posix_file_read, .write = vfs_posix_file_write, .ioctl = vfs_posix_file_ioctl, @@ -238,6 +239,7 @@ const mp_obj_type_t mp_type_vfs_posix_fileio = { #endif STATIC const mp_stream_p_t textio_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = vfs_posix_file_read, .write = vfs_posix_file_write, .ioctl = vfs_posix_file_ioctl, diff --git a/extmod/virtpin.c b/extmod/virtpin.c index dbfa21d669..559f992650 100644 --- a/extmod/virtpin.c +++ b/extmod/virtpin.c @@ -25,15 +25,16 @@ */ #include "extmod/virtpin.h" +#include "py/proto.h" int mp_virtual_pin_read(mp_obj_t pin) { mp_obj_base_t* s = (mp_obj_base_t*)MP_OBJ_TO_PTR(pin); - mp_pin_p_t *pin_p = (mp_pin_p_t*)s->type->protocol; + const mp_pin_p_t *pin_p = mp_proto_get(MP_QSTR_protocol_pin, s); return pin_p->ioctl(pin, MP_PIN_READ, 0, NULL); } void mp_virtual_pin_write(mp_obj_t pin, int value) { mp_obj_base_t* s = (mp_obj_base_t*)MP_OBJ_TO_PTR(pin); - mp_pin_p_t *pin_p = (mp_pin_p_t*)s->type->protocol; + const mp_pin_p_t *pin_p = mp_proto_get(MP_QSTR_protocol_pin, s); pin_p->ioctl(pin, MP_PIN_WRITE, value, NULL); } diff --git a/extmod/virtpin.h b/extmod/virtpin.h index 706affc192..591249e48d 100644 --- a/extmod/virtpin.h +++ b/extmod/virtpin.h @@ -27,6 +27,7 @@ #define MICROPY_INCLUDED_EXTMOD_VIRTPIN_H #include "py/obj.h" +#include "py/proto.h" #define MP_PIN_READ (1) #define MP_PIN_WRITE (2) @@ -35,6 +36,7 @@ // Pin protocol typedef struct _mp_pin_p_t { + MP_PROTOCOL_HEAD mp_uint_t (*ioctl)(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode); } mp_pin_p_t; diff --git a/lib/utils/sys_stdio_mphal.c b/lib/utils/sys_stdio_mphal.c index 266783f376..c1607dfe8c 100644 --- a/lib/utils/sys_stdio_mphal.c +++ b/lib/utils/sys_stdio_mphal.c @@ -123,6 +123,7 @@ STATIC const mp_rom_map_elem_t stdio_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(stdio_locals_dict, stdio_locals_dict_table); STATIC const mp_stream_p_t stdio_obj_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = stdio_read, .write = stdio_write, .ioctl = stdio_ioctl, @@ -158,6 +159,7 @@ STATIC mp_uint_t stdio_buffer_write(mp_obj_t self_in, const void *buf, mp_uint_t } STATIC const mp_stream_p_t stdio_buffer_obj_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = stdio_buffer_read, .write = stdio_buffer_write, .is_text = false, diff --git a/locale/ID.po b/locale/ID.po index 6a0b73b6f7..472c042c60 100644 --- a/locale/ID.po +++ b/locale/ID.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-11-27 14:54-0500\n" +"POT-Creation-Date: 2019-12-06 13:25-0600\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -120,6 +120,10 @@ msgstr "" msgid "'%s' integer 0x%x does not fit in mask 0x%x" msgstr "'%s' integer 0x%x tidak cukup didalam mask 0x%x" +#: py/proto.c +msgid "'%s' object does not support '%q'" +msgstr "" + #: py/obj.c #, c-format msgid "'%s' object does not support item assignment" diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index a24ab186a4..1541b1f74d 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-11-27 14:54-0500\n" +"POT-Creation-Date: 2019-12-06 13:25-0600\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -119,6 +119,10 @@ msgstr "" msgid "'%s' integer 0x%x does not fit in mask 0x%x" msgstr "" +#: py/proto.c +msgid "'%s' object does not support '%q'" +msgstr "" + #: py/obj.c #, c-format msgid "'%s' object does not support item assignment" diff --git a/locale/de_DE.po b/locale/de_DE.po index 37937b94f7..b34626ea1a 100644 --- a/locale/de_DE.po +++ b/locale/de_DE.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-11-27 14:54-0500\n" +"POT-Creation-Date: 2019-12-06 13:25-0600\n" "PO-Revision-Date: 2018-07-27 11:55-0700\n" "Last-Translator: Pascal Deneaux\n" "Language-Team: Sebastian Plamauer, Pascal Deneaux\n" @@ -121,6 +121,10 @@ msgstr "'%s' integer %d ist nicht im Bereich %d..%d" msgid "'%s' integer 0x%x does not fit in mask 0x%x" msgstr "'%s' Integer 0x%x passt nicht in Maske 0x%x" +#: py/proto.c +msgid "'%s' object does not support '%q'" +msgstr "" + #: py/obj.c #, c-format msgid "'%s' object does not support item assignment" diff --git a/locale/en_US.po b/locale/en_US.po index e0e63e4fd4..95884c7b25 100644 --- a/locale/en_US.po +++ b/locale/en_US.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-11-27 14:54-0500\n" +"POT-Creation-Date: 2019-12-06 13:25-0600\n" "PO-Revision-Date: 2018-07-27 11:55-0700\n" "Last-Translator: \n" "Language-Team: \n" @@ -119,6 +119,10 @@ msgstr "" msgid "'%s' integer 0x%x does not fit in mask 0x%x" msgstr "" +#: py/proto.c +msgid "'%s' object does not support '%q'" +msgstr "" + #: py/obj.c #, c-format msgid "'%s' object does not support item assignment" diff --git a/locale/en_x_pirate.po b/locale/en_x_pirate.po index b22687469c..ed7d2cec72 100644 --- a/locale/en_x_pirate.po +++ b/locale/en_x_pirate.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-11-27 14:54-0500\n" +"POT-Creation-Date: 2019-12-06 13:25-0600\n" "PO-Revision-Date: 2018-07-27 11:55-0700\n" "Last-Translator: \n" "Language-Team: @sommersoft, @MrCertainly\n" @@ -121,6 +121,10 @@ msgstr "" msgid "'%s' integer 0x%x does not fit in mask 0x%x" msgstr "" +#: py/proto.c +msgid "'%s' object does not support '%q'" +msgstr "" + #: py/obj.c #, c-format msgid "'%s' object does not support item assignment" diff --git a/locale/es.po b/locale/es.po index 4e8df4195b..fac38c0817 100644 --- a/locale/es.po +++ b/locale/es.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-11-27 14:54-0500\n" +"POT-Creation-Date: 2019-12-06 13:25-0600\n" "PO-Revision-Date: 2018-08-24 22:56-0500\n" "Last-Translator: \n" "Language-Team: \n" @@ -121,6 +121,10 @@ msgstr "'%s' entero %d no esta dentro del rango %d..%d" msgid "'%s' integer 0x%x does not fit in mask 0x%x" msgstr "'%s' entero 0x%x no cabe en la máscara 0x%x" +#: py/proto.c +msgid "'%s' object does not support '%q'" +msgstr "" + #: py/obj.c #, c-format msgid "'%s' object does not support item assignment" diff --git a/locale/fil.po b/locale/fil.po index f3f2b7e3b0..776002768d 100644 --- a/locale/fil.po +++ b/locale/fil.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-11-27 14:54-0500\n" +"POT-Creation-Date: 2019-12-06 13:25-0600\n" "PO-Revision-Date: 2018-12-20 22:15-0800\n" "Last-Translator: Timothy \n" "Language-Team: fil\n" @@ -122,6 +122,10 @@ msgstr "'%s' integer %d ay wala sa sakop ng %d..%d" msgid "'%s' integer 0x%x does not fit in mask 0x%x" msgstr "'%s' integer 0x%x ay wala sa mask na sakop ng 0x%x" +#: py/proto.c +msgid "'%s' object does not support '%q'" +msgstr "" + #: py/obj.c #, c-format msgid "'%s' object does not support item assignment" diff --git a/locale/fr.po b/locale/fr.po index 098bd8d1fc..78d079bf12 100644 --- a/locale/fr.po +++ b/locale/fr.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-11-27 14:54-0500\n" +"POT-Creation-Date: 2019-12-06 13:25-0600\n" "PO-Revision-Date: 2019-04-14 20:05+0100\n" "Last-Translator: Pierrick Couturier \n" "Language-Team: fr\n" @@ -123,6 +123,10 @@ msgstr "'%s' l'entier %d n'est pas dans la gamme %d..%d" msgid "'%s' integer 0x%x does not fit in mask 0x%x" msgstr "'%s' l'entier 0x%x ne correspond pas au masque 0x%x" +#: py/proto.c +msgid "'%s' object does not support '%q'" +msgstr "" + #: py/obj.c #, c-format msgid "'%s' object does not support item assignment" diff --git a/locale/it_IT.po b/locale/it_IT.po index 154dda932e..67585fe2fb 100644 --- a/locale/it_IT.po +++ b/locale/it_IT.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-11-27 14:54-0500\n" +"POT-Creation-Date: 2019-12-06 13:25-0600\n" "PO-Revision-Date: 2018-10-02 16:27+0200\n" "Last-Translator: Enrico Paganin \n" "Language-Team: \n" @@ -121,6 +121,10 @@ msgstr "intero '%s' non è nell'intervallo %d..%d" msgid "'%s' integer 0x%x does not fit in mask 0x%x" msgstr "intero '%s' non è nell'intervallo %d..%d" +#: py/proto.c +msgid "'%s' object does not support '%q'" +msgstr "" + #: py/obj.c #, c-format msgid "'%s' object does not support item assignment" diff --git a/locale/ko.po b/locale/ko.po index 5fc91553b2..0cf6747370 100644 --- a/locale/ko.po +++ b/locale/ko.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-11-27 14:54-0500\n" +"POT-Creation-Date: 2019-12-06 13:25-0600\n" "PO-Revision-Date: 2019-05-06 14:22-0700\n" "Last-Translator: \n" "Language-Team: LANGUAGE \n" @@ -121,6 +121,10 @@ msgstr "" msgid "'%s' integer 0x%x does not fit in mask 0x%x" msgstr "" +#: py/proto.c +msgid "'%s' object does not support '%q'" +msgstr "" + #: py/obj.c #, c-format msgid "'%s' object does not support item assignment" diff --git a/locale/pl.po b/locale/pl.po index edfce95c62..0e33f3022c 100644 --- a/locale/pl.po +++ b/locale/pl.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-11-27 14:54-0500\n" +"POT-Creation-Date: 2019-12-06 13:25-0600\n" "PO-Revision-Date: 2019-03-19 18:37-0700\n" "Last-Translator: Radomir Dopieralski \n" "Language-Team: pl\n" @@ -120,6 +120,10 @@ msgstr "'%s' liczba %d poza zakresem %d..%d" msgid "'%s' integer 0x%x does not fit in mask 0x%x" msgstr "'%s' liczba 0x%x nie pasuje do maski 0x%x" +#: py/proto.c +msgid "'%s' object does not support '%q'" +msgstr "" + #: py/obj.c #, c-format msgid "'%s' object does not support item assignment" diff --git a/locale/pt_BR.po b/locale/pt_BR.po index a2b259fc46..f1f707f63d 100644 --- a/locale/pt_BR.po +++ b/locale/pt_BR.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-11-27 14:54-0500\n" +"POT-Creation-Date: 2019-12-06 13:25-0600\n" "PO-Revision-Date: 2018-10-02 21:14-0000\n" "Last-Translator: \n" "Language-Team: \n" @@ -121,6 +121,10 @@ msgstr "" msgid "'%s' integer 0x%x does not fit in mask 0x%x" msgstr "" +#: py/proto.c +msgid "'%s' object does not support '%q'" +msgstr "" + #: py/obj.c #, c-format msgid "'%s' object does not support item assignment" diff --git a/locale/zh_Latn_pinyin.po b/locale/zh_Latn_pinyin.po index de78d35b5f..6e49774b56 100644 --- a/locale/zh_Latn_pinyin.po +++ b/locale/zh_Latn_pinyin.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: circuitpython-cn\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-11-27 14:54-0500\n" +"POT-Creation-Date: 2019-12-06 13:25-0600\n" "PO-Revision-Date: 2019-04-13 10:10-0700\n" "Last-Translator: hexthat\n" "Language-Team: Chinese Hanyu Pinyin\n" @@ -121,6 +121,10 @@ msgstr "'%s' zhěngshù %d bùzài fànwéi nèi %d.%d" msgid "'%s' integer 0x%x does not fit in mask 0x%x" msgstr "'%s' zhěngshù 0x%x bù shìyòng yú yǎn mǎ 0x%x" +#: py/proto.c +msgid "'%s' object does not support '%q'" +msgstr "" + #: py/obj.c #, c-format msgid "'%s' object does not support item assignment" diff --git a/ports/unix/coverage.c b/ports/unix/coverage.c index 841924c58d..849820fffd 100644 --- a/ports/unix/coverage.c +++ b/ports/unix/coverage.c @@ -96,6 +96,7 @@ STATIC const mp_rom_map_elem_t rawfile_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table); STATIC const mp_stream_p_t fileio_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = stest_read, .write = stest_write, .ioctl = stest_ioctl, @@ -123,6 +124,7 @@ STATIC const mp_rom_map_elem_t rawfile_locals_dict_table2[] = { STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict2, rawfile_locals_dict_table2); STATIC const mp_stream_p_t textio_stream_p2 = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = stest_read2, .write = NULL, .is_text = true, diff --git a/ports/unix/file.c b/ports/unix/file.c index c0cf6dcc43..e5c73d26c2 100644 --- a/ports/unix/file.c +++ b/ports/unix/file.c @@ -230,6 +230,7 @@ STATIC MP_DEFINE_CONST_DICT(rawfile_locals_dict, rawfile_locals_dict_table); #if MICROPY_PY_IO_FILEIO STATIC const mp_stream_p_t fileio_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = fdfile_read, .write = fdfile_write, .ioctl = fdfile_ioctl, @@ -248,6 +249,7 @@ const mp_obj_type_t mp_type_fileio = { #endif STATIC const mp_stream_p_t textio_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = fdfile_read, .write = fdfile_write, .ioctl = fdfile_ioctl, diff --git a/ports/unix/modusocket.c b/ports/unix/modusocket.c index 84e9298fd3..95da276ed9 100644 --- a/ports/unix/modusocket.c +++ b/ports/unix/modusocket.c @@ -374,6 +374,7 @@ STATIC const mp_rom_map_elem_t usocket_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(usocket_locals_dict, usocket_locals_dict_table); STATIC const mp_stream_p_t usocket_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = socket_read, .write = socket_write, .ioctl = socket_ioctl, diff --git a/py/modio.c b/py/modio.c index d7c1a58a8c..17840a6d87 100644 --- a/py/modio.c +++ b/py/modio.c @@ -90,6 +90,7 @@ STATIC mp_uint_t iobase_ioctl(mp_obj_t obj, mp_uint_t request, uintptr_t arg, in } STATIC const mp_stream_p_t iobase_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = iobase_read, .write = iobase_write, .ioctl = iobase_ioctl, @@ -185,6 +186,7 @@ STATIC const mp_rom_map_elem_t bufwriter_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(bufwriter_locals_dict, bufwriter_locals_dict_table); STATIC const mp_stream_p_t bufwriter_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .write = bufwriter_write, }; diff --git a/py/objstringio.c b/py/objstringio.c index d2ca6decdb..178e6446cc 100644 --- a/py/objstringio.c +++ b/py/objstringio.c @@ -240,6 +240,7 @@ STATIC const mp_rom_map_elem_t stringio_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(stringio_locals_dict, stringio_locals_dict_table); STATIC const mp_stream_p_t stringio_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = stringio_read, .write = stringio_write, .ioctl = stringio_ioctl, @@ -247,6 +248,7 @@ STATIC const mp_stream_p_t stringio_stream_p = { }; STATIC const mp_stream_p_t bytesio_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = stringio_read, .write = stringio_write, .ioctl = stringio_ioctl, diff --git a/py/proto.c b/py/proto.c new file mode 100644 index 0000000000..e5053130b8 --- /dev/null +++ b/py/proto.c @@ -0,0 +1,50 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Jeff Epler for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/obj.h" +#include "py/proto.h" +#include "py/runtime.h" + +#ifndef MICROPY_UNSAFE_PROTO +const void *mp_proto_get(uint16_t name, mp_const_obj_t obj) { + mp_obj_type_t *type = mp_obj_get_type(obj); + if (!type->protocol) return NULL; + uint16_t proto_name = *(const uint16_t*) type->protocol; + if (proto_name == name) { + return type->protocol; + } + return NULL; +} +#endif + +const void *mp_proto_get_or_throw(uint16_t name, mp_const_obj_t obj) { + const void *proto = mp_proto_get(name, obj); + if (proto) { + return proto; + } + mp_raise_TypeError_varg(translate("'%s' object does not support '%q'"), + mp_obj_get_type_str(obj), name); +} diff --git a/py/proto.h b/py/proto.h new file mode 100644 index 0000000000..2d4f805659 --- /dev/null +++ b/py/proto.h @@ -0,0 +1,43 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Jeff Epler for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_PY_PROTO_H +#define MICROPY_INCLUDED_PY_PROTO_H + +#ifdef MICROPY_UNSAFE_PROTO +#define MP_PROTOCOL_HEAD /* NOTHING */ +#define MP_PROTO_IMPLEMENT(name) /* NOTHING */ +static inline void *mp_proto_get(uint16_t name, mp_const_obj_type_t obj) { return mp_obj_get_type(obj)->protocol; } +#else +#define MP_PROTOCOL_HEAD \ + uint16_t name; // The name of this protocol, a qstr +#define MP_PROTO_IMPLEMENT(n) .name = n, +const void *mp_proto_get(uint16_t name, mp_const_obj_t obj); +const void *mp_proto_get_or_throw(uint16_t name, mp_const_obj_t obj); +#endif + +#endif + diff --git a/py/py.mk b/py/py.mk index 17cb792646..ae9b005b6c 100644 --- a/py/py.mk +++ b/py/py.mk @@ -214,6 +214,7 @@ PY_CORE_O_BASENAME = $(addprefix py/,\ objtype.o \ objzip.o \ opmethods.o \ + proto.o \ reload.o \ sequence.o \ stream.o \ diff --git a/py/stream.c b/py/stream.c index 1d25f64706..2ff2b76a61 100644 --- a/py/stream.c +++ b/py/stream.c @@ -86,8 +86,7 @@ mp_uint_t mp_stream_rw(mp_obj_t stream, void *buf_, mp_uint_t size, int *errcode } const mp_stream_p_t *mp_get_stream_raise(mp_obj_t self_in, int flags) { - mp_obj_type_t *type = mp_obj_get_type(self_in); - const mp_stream_p_t *stream_p = type->protocol; + const mp_stream_p_t *stream_p = mp_proto_get(MP_QSTR_protocol_stream, self_in); if (stream_p == NULL || ((flags & MP_STREAM_OP_READ) && stream_p->read == NULL) || ((flags & MP_STREAM_OP_WRITE) && stream_p->write == NULL) @@ -522,7 +521,7 @@ int mp_stream_errno; ssize_t mp_stream_posix_write(mp_obj_t stream, const void *buf, size_t len) { mp_obj_base_t* o = (mp_obj_base_t*)MP_OBJ_TO_PTR(stream); - const mp_stream_p_t *stream_p = o->type->protocol; + const mp_stream_p_t *stream_p = mp_get_stream(o); mp_uint_t out_sz = stream_p->write(stream, buf, len, &mp_stream_errno); if (out_sz == MP_STREAM_ERROR) { return -1; @@ -533,7 +532,7 @@ ssize_t mp_stream_posix_write(mp_obj_t stream, const void *buf, size_t len) { ssize_t mp_stream_posix_read(mp_obj_t stream, void *buf, size_t len) { mp_obj_base_t* o = (mp_obj_base_t*)MP_OBJ_TO_PTR(stream); - const mp_stream_p_t *stream_p = o->type->protocol; + const mp_stream_p_t *stream_p = mp_get_stream(o); mp_uint_t out_sz = stream_p->read(stream, buf, len, &mp_stream_errno); if (out_sz == MP_STREAM_ERROR) { return -1; @@ -544,7 +543,7 @@ ssize_t mp_stream_posix_read(mp_obj_t stream, void *buf, size_t len) { off_t mp_stream_posix_lseek(mp_obj_t stream, off_t offset, int whence) { const mp_obj_base_t* o = (mp_obj_base_t*)MP_OBJ_TO_PTR(stream); - const mp_stream_p_t *stream_p = o->type->protocol; + const mp_stream_p_t *stream_p = mp_get_stream(o); struct mp_stream_seek_t seek_s; seek_s.offset = offset; seek_s.whence = whence; @@ -557,7 +556,7 @@ off_t mp_stream_posix_lseek(mp_obj_t stream, off_t offset, int whence) { int mp_stream_posix_fsync(mp_obj_t stream) { mp_obj_base_t* o = (mp_obj_base_t*)MP_OBJ_TO_PTR(stream); - const mp_stream_p_t *stream_p = o->type->protocol; + const mp_stream_p_t *stream_p = mp_get_stream(o); mp_uint_t res = stream_p->ioctl(stream, MP_STREAM_FLUSH, 0, &mp_stream_errno); if (res == MP_STREAM_ERROR) { return -1; diff --git a/py/stream.h b/py/stream.h index 03e24c7469..543fe8c82a 100644 --- a/py/stream.h +++ b/py/stream.h @@ -27,6 +27,7 @@ #define MICROPY_INCLUDED_PY_STREAM_H #include "py/obj.h" +#include "py/proto.h" #include "py/mperrno.h" #define MP_STREAM_ERROR ((mp_uint_t)-1) @@ -64,6 +65,7 @@ struct mp_stream_seek_t { // Stream protocol typedef struct _mp_stream_p_t { + MP_PROTOCOL_HEAD // On error, functions should return MP_STREAM_ERROR and fill in *errcode (values // are implementation-dependent, but will be exposed to user, e.g. via exception). mp_uint_t (*read)(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode); @@ -93,7 +95,7 @@ MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_ioctl_obj); // Object is assumed to have a non-NULL stream protocol with valid r/w/ioctl methods static inline const mp_stream_p_t *mp_get_stream(mp_const_obj_t self) { - return (const mp_stream_p_t*)((const mp_obj_base_t*)MP_OBJ_TO_PTR(self))->type->protocol; + return mp_proto_get(MP_QSTR_protocol_stream, self); } const mp_stream_p_t *mp_get_stream_raise(mp_obj_t self_in, int flags); diff --git a/shared-bindings/_bleio/CharacteristicBuffer.c b/shared-bindings/_bleio/CharacteristicBuffer.c index e7524da2d5..fc95d0d503 100644 --- a/shared-bindings/_bleio/CharacteristicBuffer.c +++ b/shared-bindings/_bleio/CharacteristicBuffer.c @@ -230,6 +230,7 @@ STATIC const mp_rom_map_elem_t bleio_characteristic_buffer_locals_dict_table[] = STATIC MP_DEFINE_CONST_DICT(bleio_characteristic_buffer_locals_dict, bleio_characteristic_buffer_locals_dict_table); STATIC const mp_stream_p_t characteristic_buffer_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = bleio_characteristic_buffer_read, .write = bleio_characteristic_buffer_write, .ioctl = bleio_characteristic_buffer_ioctl, diff --git a/shared-bindings/audiocore/RawSample.c b/shared-bindings/audiocore/RawSample.c index 07f8c683f2..87d410ea1a 100644 --- a/shared-bindings/audiocore/RawSample.c +++ b/shared-bindings/audiocore/RawSample.c @@ -180,9 +180,20 @@ STATIC const mp_rom_map_elem_t audioio_rawsample_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(audioio_rawsample_locals_dict, audioio_rawsample_locals_dict_table); +STATIC const audiosample_p_t audioio_rawsample_proto = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample) + .sample_rate = (audiosample_sample_rate_fun)common_hal_audioio_rawsample_get_sample_rate, + .bits_per_sample = (audiosample_bits_per_sample_fun)common_hal_audioio_rawsample_get_bits_per_sample, + .channel_count = (audiosample_channel_count_fun)common_hal_audioio_rawsample_get_channel_count, + .reset_buffer = (audiosample_reset_buffer_fun)audioio_rawsample_reset_buffer, + .get_buffer = (audiosample_get_buffer_fun)audioio_rawsample_get_buffer, + .get_buffer_structure = (audiosample_get_buffer_structure_fun)audioio_rawsample_get_buffer_structure, +}; + const mp_obj_type_t audioio_rawsample_type = { { &mp_type_type }, .name = MP_QSTR_RawSample, .make_new = audioio_rawsample_make_new, .locals_dict = (mp_obj_dict_t*)&audioio_rawsample_locals_dict, + .protocol = &audioio_rawsample_proto, }; diff --git a/shared-bindings/audiocore/RawSample.h b/shared-bindings/audiocore/RawSample.h index b02778cad3..61f61a0662 100644 --- a/shared-bindings/audiocore/RawSample.h +++ b/shared-bindings/audiocore/RawSample.h @@ -39,6 +39,8 @@ void common_hal_audioio_rawsample_construct(audioio_rawsample_obj_t* self, void common_hal_audioio_rawsample_deinit(audioio_rawsample_obj_t* self); bool common_hal_audioio_rawsample_deinited(audioio_rawsample_obj_t* self); uint32_t common_hal_audioio_rawsample_get_sample_rate(audioio_rawsample_obj_t* self); +uint8_t common_hal_audioio_rawsample_get_bits_per_sample(audioio_rawsample_obj_t* self); +uint8_t common_hal_audioio_rawsample_get_channel_count(audioio_rawsample_obj_t* self); void common_hal_audioio_rawsample_set_sample_rate(audioio_rawsample_obj_t* self, uint32_t sample_rate); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOIO_RAWSAMPLE_H diff --git a/shared-bindings/audiocore/WaveFile.c b/shared-bindings/audiocore/WaveFile.c index 1b3a94ff37..178d2a1393 100644 --- a/shared-bindings/audiocore/WaveFile.c +++ b/shared-bindings/audiocore/WaveFile.c @@ -206,9 +206,21 @@ STATIC const mp_rom_map_elem_t audioio_wavefile_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(audioio_wavefile_locals_dict, audioio_wavefile_locals_dict_table); +STATIC const audiosample_p_t audioio_wavefile_proto = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample) + .sample_rate = (audiosample_sample_rate_fun)common_hal_audioio_wavefile_get_sample_rate, + .bits_per_sample = (audiosample_bits_per_sample_fun)common_hal_audioio_wavefile_get_bits_per_sample, + .channel_count = (audiosample_channel_count_fun)common_hal_audioio_wavefile_get_channel_count, + .reset_buffer = (audiosample_reset_buffer_fun)audioio_wavefile_reset_buffer, + .get_buffer = (audiosample_get_buffer_fun)audioio_wavefile_get_buffer, + .get_buffer_structure = (audiosample_get_buffer_structure_fun)audioio_wavefile_get_buffer_structure, +}; + + const mp_obj_type_t audioio_wavefile_type = { { &mp_type_type }, .name = MP_QSTR_WaveFile, .make_new = audioio_wavefile_make_new, .locals_dict = (mp_obj_dict_t*)&audioio_wavefile_locals_dict, + .protocol = &audioio_wavefile_proto, }; diff --git a/shared-bindings/audiomixer/Mixer.c b/shared-bindings/audiomixer/Mixer.c index ed7b95d9e0..03ffb9373b 100644 --- a/shared-bindings/audiomixer/Mixer.c +++ b/shared-bindings/audiomixer/Mixer.c @@ -291,9 +291,20 @@ STATIC const mp_rom_map_elem_t audiomixer_mixer_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(audiomixer_mixer_locals_dict, audiomixer_mixer_locals_dict_table); +STATIC const audiosample_p_t audiomixer_mixer_proto = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_audiosample) + .sample_rate = (audiosample_sample_rate_fun)common_hal_audiomixer_mixer_get_sample_rate, + .bits_per_sample = (audiosample_bits_per_sample_fun)common_hal_audiomixer_mixer_get_bits_per_sample, + .channel_count = (audiosample_channel_count_fun)common_hal_audiomixer_mixer_get_channel_count, + .reset_buffer = (audiosample_reset_buffer_fun)audiomixer_mixer_reset_buffer, + .get_buffer = (audiosample_get_buffer_fun)audiomixer_mixer_get_buffer, + .get_buffer_structure = (audiosample_get_buffer_structure_fun)audiomixer_mixer_get_buffer_structure, +}; + const mp_obj_type_t audiomixer_mixer_type = { { &mp_type_type }, .name = MP_QSTR_Mixer, .make_new = audiomixer_mixer_make_new, .locals_dict = (mp_obj_dict_t*)&audiomixer_mixer_locals_dict, + .protocol = &audiomixer_mixer_proto, }; diff --git a/shared-bindings/audiomixer/Mixer.h b/shared-bindings/audiomixer/Mixer.h index 9eabbf61df..a99e1bf62a 100644 --- a/shared-bindings/audiomixer/Mixer.h +++ b/shared-bindings/audiomixer/Mixer.h @@ -47,5 +47,7 @@ bool common_hal_audiomixer_mixer_deinited(audiomixer_mixer_obj_t* self); bool common_hal_audiomixer_mixer_get_playing(audiomixer_mixer_obj_t* self); uint32_t common_hal_audiomixer_mixer_get_sample_rate(audiomixer_mixer_obj_t* self); +uint8_t common_hal_audiomixer_mixer_get_channel_count(audiomixer_mixer_obj_t* self); +uint8_t common_hal_audiomixer_mixer_get_bits_per_sample(audiomixer_mixer_obj_t* self); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_AUDIOMIXER_MIXER_H diff --git a/shared-bindings/busio/UART.c b/shared-bindings/busio/UART.c index 7a3b48e895..1fc81e78e2 100644 --- a/shared-bindings/busio/UART.c +++ b/shared-bindings/busio/UART.c @@ -398,6 +398,7 @@ STATIC const mp_rom_map_elem_t busio_uart_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(busio_uart_locals_dict, busio_uart_locals_dict_table); STATIC const mp_stream_p_t uart_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = busio_uart_read, .write = busio_uart_write, .ioctl = busio_uart_ioctl, diff --git a/shared-bindings/socket/__init__.c b/shared-bindings/socket/__init__.c index 6d04a98936..2d6c16e90f 100644 --- a/shared-bindings/socket/__init__.c +++ b/shared-bindings/socket/__init__.c @@ -500,6 +500,7 @@ mp_uint_t socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int * } STATIC const mp_stream_p_t socket_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .ioctl = socket_ioctl, .is_text = false, }; diff --git a/shared-bindings/terminalio/Terminal.c b/shared-bindings/terminalio/Terminal.c index cdde672d3a..9c01fba20b 100644 --- a/shared-bindings/terminalio/Terminal.c +++ b/shared-bindings/terminalio/Terminal.c @@ -112,6 +112,7 @@ STATIC const mp_rom_map_elem_t terminalio_terminal_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(terminalio_terminal_locals_dict, terminalio_terminal_locals_dict_table); STATIC const mp_stream_p_t terminalio_terminal_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = NULL, .write = terminalio_terminal_write, .ioctl = terminalio_terminal_ioctl, diff --git a/shared-bindings/usb_midi/PortIn.c b/shared-bindings/usb_midi/PortIn.c index 356a81d52c..e2df56e954 100644 --- a/shared-bindings/usb_midi/PortIn.c +++ b/shared-bindings/usb_midi/PortIn.c @@ -107,6 +107,7 @@ STATIC const mp_rom_map_elem_t usb_midi_portin_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(usb_midi_portin_locals_dict, usb_midi_portin_locals_dict_table); STATIC const mp_stream_p_t usb_midi_portin_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = usb_midi_portin_read, .write = NULL, .ioctl = usb_midi_portin_ioctl, diff --git a/shared-bindings/usb_midi/PortOut.c b/shared-bindings/usb_midi/PortOut.c index 6f4ce67165..e3eddfaf57 100644 --- a/shared-bindings/usb_midi/PortOut.c +++ b/shared-bindings/usb_midi/PortOut.c @@ -89,6 +89,7 @@ STATIC const mp_rom_map_elem_t usb_midi_portout_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(usb_midi_portout_locals_dict, usb_midi_portout_locals_dict_table); STATIC const mp_stream_p_t usb_midi_portout_stream_p = { + MP_PROTO_IMPLEMENT(MP_QSTR_protocol_stream) .read = NULL, .write = usb_midi_portout_write, .ioctl = usb_midi_portout_ioctl, diff --git a/shared-module/audiocore/RawSample.c b/shared-module/audiocore/RawSample.c index d6bf3a567a..a69ddeb650 100644 --- a/shared-module/audiocore/RawSample.c +++ b/shared-module/audiocore/RawSample.c @@ -60,6 +60,12 @@ void common_hal_audioio_rawsample_set_sample_rate(audioio_rawsample_obj_t* self, uint32_t sample_rate) { self->sample_rate = sample_rate; } +uint8_t common_hal_audioio_rawsample_get_bits_per_sample(audioio_rawsample_obj_t* self) { + return self->bits_per_sample; +} +uint8_t common_hal_audioio_rawsample_get_channel_count(audioio_rawsample_obj_t* self) { + return self->channel_count; +} void audioio_rawsample_reset_buffer(audioio_rawsample_obj_t* self, bool single_channel, diff --git a/shared-module/audiocore/__init__.c b/shared-module/audiocore/__init__.c index f9762676fd..1553dbe961 100644 --- a/shared-module/audiocore/__init__.c +++ b/shared-module/audiocore/__init__.c @@ -36,103 +36,37 @@ #include "shared-module/audiomixer/Mixer.h" uint32_t audiosample_sample_rate(mp_obj_t sample_obj) { - if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) { - audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj); - return sample->sample_rate; - } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) { - audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj); - return file->sample_rate; - #if CIRCUITPY_AUDIOMIXER - } else if (MP_OBJ_IS_TYPE(sample_obj, &audiomixer_mixer_type)) { - audiomixer_mixer_obj_t* mixer = MP_OBJ_TO_PTR(sample_obj); - return mixer->sample_rate; - #endif - } - return 16000; + const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj); + return proto->sample_rate(MP_OBJ_TO_PTR(sample_obj)); } uint8_t audiosample_bits_per_sample(mp_obj_t sample_obj) { - if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) { - audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj); - return sample->bits_per_sample; - } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) { - audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj); - return file->bits_per_sample; - #if CIRCUITPY_AUDIOMIXER - } else if (MP_OBJ_IS_TYPE(sample_obj, &audiomixer_mixer_type)) { - audiomixer_mixer_obj_t* mixer = MP_OBJ_TO_PTR(sample_obj); - return mixer->bits_per_sample; - #endif - } - return 8; + const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj); + return proto->bits_per_sample(MP_OBJ_TO_PTR(sample_obj)); } uint8_t audiosample_channel_count(mp_obj_t sample_obj) { - if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) { - audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj); - return sample->channel_count; - } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) { - audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj); - return file->channel_count; - #if CIRCUITPY_AUDIOMIXER - } else if (MP_OBJ_IS_TYPE(sample_obj, &audiomixer_mixer_type)) { - audiomixer_mixer_obj_t* mixer = MP_OBJ_TO_PTR(sample_obj); - return mixer->channel_count; - #endif - } - return 1; + const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj); + return proto->channel_count(MP_OBJ_TO_PTR(sample_obj)); } void audiosample_reset_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t audio_channel) { - if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) { - audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj); - audioio_rawsample_reset_buffer(sample, single_channel, audio_channel); - } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) { - audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj); - audioio_wavefile_reset_buffer(file, single_channel, audio_channel); - #if CIRCUITPY_AUDIOMIXER - } else if (MP_OBJ_IS_TYPE(sample_obj, &audiomixer_mixer_type)) { - audiomixer_mixer_obj_t* file = MP_OBJ_TO_PTR(sample_obj); - audiomixer_mixer_reset_buffer(file, single_channel, audio_channel); - #endif - } + const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj); + proto->reset_buffer(MP_OBJ_TO_PTR(sample_obj)); } audioio_get_buffer_result_t audiosample_get_buffer(mp_obj_t sample_obj, bool single_channel, uint8_t channel, uint8_t** buffer, uint32_t* buffer_length) { - if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) { - audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj); - return audioio_rawsample_get_buffer(sample, single_channel, channel, buffer, buffer_length); - } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) { - audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj); - return audioio_wavefile_get_buffer(file, single_channel, channel, buffer, buffer_length); - #if CIRCUITPY_AUDIOMIXER - } else if (MP_OBJ_IS_TYPE(sample_obj, &audiomixer_mixer_type)) { - audiomixer_mixer_obj_t* file = MP_OBJ_TO_PTR(sample_obj); - return audiomixer_mixer_get_buffer(file, single_channel, channel, buffer, buffer_length); - #endif - } - return GET_BUFFER_DONE; + const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj); + return proto->get_buffer(MP_OBJ_TO_PTR(sample_obj), single_channel, channel, buffer, buffer_length); } void audiosample_get_buffer_structure(mp_obj_t sample_obj, bool single_channel, bool* single_buffer, bool* samples_signed, uint32_t* max_buffer_length, uint8_t* spacing) { - if (MP_OBJ_IS_TYPE(sample_obj, &audioio_rawsample_type)) { - audioio_rawsample_obj_t* sample = MP_OBJ_TO_PTR(sample_obj); - audioio_rawsample_get_buffer_structure(sample, single_channel, single_buffer, - samples_signed, max_buffer_length, spacing); - } else if (MP_OBJ_IS_TYPE(sample_obj, &audioio_wavefile_type)) { - audioio_wavefile_obj_t* file = MP_OBJ_TO_PTR(sample_obj); - audioio_wavefile_get_buffer_structure(file, single_channel, single_buffer, samples_signed, - max_buffer_length, spacing); - #if CIRCUITPY_AUDIOMIXER - } else if (MP_OBJ_IS_TYPE(sample_obj, &audiomixer_mixer_type)) { - audiomixer_mixer_obj_t* file = MP_OBJ_TO_PTR(sample_obj); - audiomixer_mixer_get_buffer_structure(file, single_channel, single_buffer, samples_signed, - max_buffer_length, spacing); - #endif - } + const audiosample_p_t *proto = mp_proto_get_or_throw(MP_QSTR_protocol_audiosample, sample_obj); + proto->get_buffer_structure(MP_OBJ_TO_PTR(sample_obj), single_channel, single_buffer, + samples_signed, max_buffer_length, spacing); } diff --git a/shared-module/audiocore/__init__.h b/shared-module/audiocore/__init__.h index 7aa0c1824a..38c1f5aeb1 100644 --- a/shared-module/audiocore/__init__.h +++ b/shared-module/audiocore/__init__.h @@ -31,6 +31,7 @@ #include #include "py/obj.h" +#include "py/proto.h" typedef enum { GET_BUFFER_DONE, // No more data to read @@ -38,6 +39,28 @@ typedef enum { GET_BUFFER_ERROR, // Error while reading data. } audioio_get_buffer_result_t; +typedef uint32_t (*audiosample_sample_rate_fun)(mp_obj_t); +typedef uint8_t (*audiosample_bits_per_sample_fun)(mp_obj_t); +typedef uint8_t (*audiosample_channel_count_fun)(mp_obj_t); +typedef void (*audiosample_reset_buffer_fun)(mp_obj_t); +typedef audioio_get_buffer_result_t (*audiosample_get_buffer_fun)(mp_obj_t, + bool single_channel, uint8_t channel, uint8_t** buffer, + uint32_t* buffer_length); +typedef void (*audiosample_get_buffer_structure_fun)(mp_obj_t, + bool single_channel, bool* single_buffer, + bool* samples_signed, uint32_t *max_buffer_length, + uint8_t* spacing); + +typedef struct _audiosample_p_t { + MP_PROTOCOL_HEAD // MP_QSTR_protocol_audiosample + audiosample_sample_rate_fun sample_rate; + audiosample_bits_per_sample_fun bits_per_sample; + audiosample_channel_count_fun channel_count; + audiosample_reset_buffer_fun reset_buffer; + audiosample_get_buffer_fun get_buffer; + audiosample_get_buffer_structure_fun get_buffer_structure; +} audiosample_p_t; + uint32_t audiosample_sample_rate(mp_obj_t sample_obj); uint8_t audiosample_bits_per_sample(mp_obj_t sample_obj); uint8_t audiosample_channel_count(mp_obj_t sample_obj); diff --git a/shared-module/audiomixer/Mixer.c b/shared-module/audiomixer/Mixer.c index a52489f856..afa3a06323 100644 --- a/shared-module/audiomixer/Mixer.c +++ b/shared-module/audiomixer/Mixer.c @@ -76,6 +76,14 @@ uint32_t common_hal_audiomixer_mixer_get_sample_rate(audiomixer_mixer_obj_t* sel return self->sample_rate; } +uint8_t common_hal_audiomixer_mixer_get_channel_count(audiomixer_mixer_obj_t* self) { + return self->channel_count; +} + +uint8_t common_hal_audiomixer_mixer_get_bits_per_sample(audiomixer_mixer_obj_t* self) { + return self->bits_per_sample; +} + bool common_hal_audiomixer_mixer_get_playing(audiomixer_mixer_obj_t* self) { for (uint8_t v = 0; v < self->voice_count; v++) { if (common_hal_audiomixer_mixervoice_get_playing(MP_OBJ_TO_PTR(self->voice[v]))) {