Hi all, this is my first post, although I've been enjoying Pythonista for several years now. Wonderful app!
Recently I've been working with the new Widget functionality. I'm currently trying to make a widget that represents the decibel sound level. I'm able to get this decibel information from an "AVAudioSession" using objc_util. My problem is displaying it.
The below code works fine in the widget simulator (when it's run from the file, in-app), but only refreshes once in Today View. I have tried everything I can think of: wrapping it in a ui.View class, creating a custom draw method, calling set_needs_display, ... nothing works. I ran into this same problem when I tried to write a text-based snake game for the widget. Hopefully one of you will be able to figure out where I went wrong.
(I say "self-called refresh" as opposed to being called by a touch or button--those seem to work fine. Perhaps the solution is to simulate a button press to refresh.)
#!python3
from objc_util import *
import os, ui
import appex
import time
def record():
AVAudioSession = ObjCClass('AVAudioSession')
NSURL = ObjCClass('NSURL')
AVAudioRecorder = ObjCClass('AVAudioRecorder')
shared_session = AVAudioSession.sharedInstance()
category_set = shared_session.setCategory_error_(ns('AVAudioSessionCategoryPlayAndRecord'), None)
settings = {ns('AVFormatIDKey'): ns(1633772320), ns('AVSampleRateKey'):ns(0.5), ns('AVNumberOfChannelsKey'):ns(1)}
output_path = os.path.abspath('Recording.m4a')
out_url = NSURL.fileURLWithPath_(ns(output_path))
recorder = AVAudioRecorder.alloc().initWithURL_settings_error_(out_url, settings, None)
recorder.record()
recorder.setMeteringEnabled_(True)
return recorder
label = ui.Label()
label.text = 'Please wait...'
label.font = ('Menlo', 24)
label.alignment = ui.ALIGN_CENTER
label.text_color = 'red'
appex.set_widget_view(label)
recorder = record()
while True:
recorder.updateMeters()
label.text = str(recorder.peakPowerForChannel_(0))[: 6] + ' dB'
label.set_needs_display()
time.sleep(.25)