3030
3131#include "py/runtime.h"
3232#include "py/objproperty.h"
33+ #include "shared/runtime/context_manager_helpers.h"
34+ #include "shared-bindings/util.h"
3335#include "supervisor/shared/translate/translate.h"
3436#include "shared-bindings/gifio/OnDiskGif.h"
3537
9698//| display_bus.send(42, struct.pack(">hh", 0, odg.bitmap.width - 1))
9799//| display_bus.send(43, struct.pack(">hh", 0, odg.bitmap.height - 1))
98100//| display_bus.send(44, d.bitmap)
101+ //|
102+ //| # The following optional code will free the OnDiskGif and allocated resources
103+ //| # after use. This may be required before loading a new GIF in situations
104+ //| # where RAM is limited and the first GIF took most of the RAM.
105+ //| odg.deinit()
106+ //| odg = None
107+ //| gc.collect()
108+ //|
99109//| """
100110//|
101111//| def __init__(self, file: str) -> None:
@@ -125,11 +135,34 @@ STATIC mp_obj_t gifio_ondiskgif_make_new(const mp_obj_type_t *type, size_t n_arg
125135 return MP_OBJ_FROM_PTR (self );
126136}
127137
138+ STATIC void check_for_deinit (gifio_ondiskgif_t * self ) {
139+ if (common_hal_gifio_ondiskgif_deinited (self )) {
140+ raise_deinited_error ();
141+ }
142+ }
143+
144+ //| def __enter__(self) -> OnDiskGif:
145+ //| """No-op used by Context Managers."""
146+ //| ...
147+ // Provided by context manager helper.
148+
149+ //| def __exit__(self) -> None:
150+ //| """Automatically deinitializes the GIF when exiting a context. See
151+ //| :ref:`lifetime-and-contextmanagers` for more info."""
152+ //| ...
153+ STATIC mp_obj_t gifio_ondiskgif_obj___exit__ (size_t n_args , const mp_obj_t * args ) {
154+ (void )n_args ;
155+ common_hal_gifio_ondiskgif_deinit (args [0 ]);
156+ return mp_const_none ;
157+ }
158+ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (gifio_ondiskgif___exit___obj , 4 , 4 , gifio_ondiskgif_obj___exit__ );
159+
128160//| width: int
129161//| """Width of the gif. (read only)"""
130162STATIC mp_obj_t gifio_ondiskgif_obj_get_width (mp_obj_t self_in ) {
131163 gifio_ondiskgif_t * self = MP_OBJ_TO_PTR (self_in );
132164
165+ check_for_deinit (self );
133166 return MP_OBJ_NEW_SMALL_INT (common_hal_gifio_ondiskgif_get_width (self ));
134167}
135168
@@ -143,6 +176,7 @@ MP_PROPERTY_GETTER(gifio_ondiskgif_width_obj,
143176STATIC mp_obj_t gifio_ondiskgif_obj_get_height (mp_obj_t self_in ) {
144177 gifio_ondiskgif_t * self = MP_OBJ_TO_PTR (self_in );
145178
179+ check_for_deinit (self );
146180 return MP_OBJ_NEW_SMALL_INT (common_hal_gifio_ondiskgif_get_height (self ));
147181}
148182
@@ -155,6 +189,8 @@ MP_PROPERTY_GETTER(gifio_ondiskgif_height_obj,
155189//| """The bitmap used to hold the current frame."""
156190STATIC mp_obj_t gifio_ondiskgif_obj_get_bitmap (mp_obj_t self_in ) {
157191 gifio_ondiskgif_t * self = MP_OBJ_TO_PTR (self_in );
192+
193+ check_for_deinit (self );
158194 return common_hal_gifio_ondiskgif_get_bitmap (self );
159195}
160196
@@ -168,6 +204,7 @@ MP_PROPERTY_GETTER(gifio_ondiskgif_bitmap_obj,
168204STATIC mp_obj_t gifio_ondiskgif_obj_next_frame (mp_obj_t self_in ) {
169205 gifio_ondiskgif_t * self = MP_OBJ_TO_PTR (self_in );
170206
207+ check_for_deinit (self );
171208 return mp_obj_new_float ((float )common_hal_gifio_ondiskgif_next_frame (self , true) / 1000 );
172209}
173210
@@ -179,6 +216,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(gifio_ondiskgif_next_frame_obj, gifio_ondiskgif_obj_ne
179216STATIC mp_obj_t gifio_ondiskgif_obj_get_duration (mp_obj_t self_in ) {
180217 gifio_ondiskgif_t * self = MP_OBJ_TO_PTR (self_in );
181218
219+ check_for_deinit (self );
182220 return mp_obj_new_float ((float )common_hal_gifio_ondiskgif_get_duration (self ) / 1000 );
183221}
184222
@@ -192,6 +230,7 @@ MP_PROPERTY_GETTER(gifio_ondiskgif_duration_obj,
192230STATIC mp_obj_t gifio_ondiskgif_obj_get_frame_count (mp_obj_t self_in ) {
193231 gifio_ondiskgif_t * self = MP_OBJ_TO_PTR (self_in );
194232
233+ check_for_deinit (self );
195234 return MP_OBJ_NEW_SMALL_INT (common_hal_gifio_ondiskgif_get_frame_count (self ));
196235}
197236
@@ -205,6 +244,7 @@ MP_PROPERTY_GETTER(gifio_ondiskgif_frame_count_obj,
205244STATIC mp_obj_t gifio_ondiskgif_obj_get_min_delay (mp_obj_t self_in ) {
206245 gifio_ondiskgif_t * self = MP_OBJ_TO_PTR (self_in );
207246
247+ check_for_deinit (self );
208248 return mp_obj_new_float ((float )common_hal_gifio_ondiskgif_get_min_delay (self ) / 1000 );
209249}
210250
@@ -219,6 +259,7 @@ MP_PROPERTY_GETTER(gifio_ondiskgif_min_delay_obj,
219259STATIC mp_obj_t gifio_ondiskgif_obj_get_max_delay (mp_obj_t self_in ) {
220260 gifio_ondiskgif_t * self = MP_OBJ_TO_PTR (self_in );
221261
262+ check_for_deinit (self );
222263 return mp_obj_new_float ((float )common_hal_gifio_ondiskgif_get_max_delay (self ) / 1000 );
223264}
224265
@@ -227,7 +268,21 @@ MP_DEFINE_CONST_FUN_OBJ_1(gifio_ondiskgif_get_max_delay_obj, gifio_ondiskgif_obj
227268MP_PROPERTY_GETTER (gifio_ondiskgif_max_delay_obj ,
228269 (mp_obj_t )& gifio_ondiskgif_get_max_delay_obj );
229270
271+ //| def deinit(self) -> None:
272+ //| """Release resources allocated by OnDiskGif."""
273+ //| ...
274+ //|
275+ STATIC mp_obj_t gifio_ondiskgif_obj_deinit (mp_obj_t self_in ) {
276+ gifio_ondiskgif_t * self = MP_OBJ_TO_PTR (self_in );
277+ common_hal_gifio_ondiskgif_deinit (self );
278+ return mp_const_none ;
279+ }
280+ MP_DEFINE_CONST_FUN_OBJ_1 (gifio_ondiskgif_deinit_obj , gifio_ondiskgif_obj_deinit );
281+
230282STATIC const mp_rom_map_elem_t gifio_ondiskgif_locals_dict_table [] = {
283+ { MP_ROM_QSTR (MP_QSTR_deinit ), MP_ROM_PTR (& gifio_ondiskgif_deinit_obj ) },
284+ { MP_ROM_QSTR (MP_QSTR___enter__ ), MP_ROM_PTR (& default___enter___obj ) },
285+ { MP_ROM_QSTR (MP_QSTR___exit__ ), MP_ROM_PTR (& gifio_ondiskgif___exit___obj ) },
231286 { MP_ROM_QSTR (MP_QSTR_height ), MP_ROM_PTR (& gifio_ondiskgif_height_obj ) },
232287 { MP_ROM_QSTR (MP_QSTR_bitmap ), MP_ROM_PTR (& gifio_ondiskgif_bitmap_obj ) },
233288 { MP_ROM_QSTR (MP_QSTR_width ), MP_ROM_PTR (& gifio_ondiskgif_width_obj ) },
0 commit comments