This commit is contained in:
yumoqing 2021-02-09 20:57:55 +08:00
parent ac8ff8b36e
commit 66d0a18bcd
7 changed files with 83 additions and 83 deletions

View File

@ -0,0 +1,44 @@
import tempfile
import pyaudio
import wave
from kivy.event import EventDispatcher
from kivy.properties import NumericProperty
from kivyblocks.baseWidget import HBox
from kviyblocks.micphone import Micphone
class AudioRecorder(EventDispatcher):
fs = NumericProperty(None)
filename = StringProperty(None)
voice_src = OjbectProperty(None)
def __init__(self, **kw):
super(AudioRecorder, self).__init__(**kw)
self.saving = False
if not self.filename:
self.mk_temp_file()
def mk_temp_file(self):
self.filename = tempfile.mktemp(suffix='.wav')
def on_filename(self, *args):
self.wf = wave.open(self.filename, 'wb')
def on_voice_src(self, *args):
audio_profile = self.voice_src.audio_profile()
self.wf.setnchannels(audio_profile['channels'])
self.wf.setsamplewidth(audio_profile['sample_size'])
self.wf.setframerate(audio_profiel['sample_rate'])
self.voice_src.bind(on_fps=self.write)
def write(self, o, d):
if self.saving:
self.wf.write(''.join(d))
def start(self):
if not self.voice_src.recording:
self.voice_src.start()
self.saving = True
def stop(self):
self.saving = False
wf.close()

View File

@ -572,8 +572,10 @@ class Blocks(EventDispatcher):
} }
""" """
def doit(desc): def doit(desc):
if isinstance(desc,DictObject):
desc = desc.to_dict()
if not isinstance(desc,dict): if not isinstance(desc,dict):
Logger.info('Block: desc must be a dict object', Logger.info('Block: desc(%s) must be a dict object(%s)',
desc,type(desc)) desc,type(desc))
return None return None

View File

@ -31,6 +31,14 @@ description file format
print('size changed') print('size changed')
for c in self._inner.children: for c in self._inner.children:
c.width = self.width c.width = self.width
if isinstance(c, Factory.Text):
_, h = c.get_wraped_size()
clen = CSize(1)
if not h or h < clen:
c.height = clen
else:
c.height = h
self._inner.do_layout()
def load_text(self, *args): def load_text(self, *args):
print('source fired, hahaha', *args) print('source fired, hahaha', *args)
@ -51,14 +59,13 @@ description file format
l = ''.join([i for i in l if i != '\r']) l = ''.join([i for i in l if i != '\r'])
self.parse_line(l) self.parse_line(l)
def parse_title(self,txt, level): def parse_title(self, txt, level):
w = Factory.Blocks().widgetBuild({ w = Factory.Blocks().widgetBuild({
"widgettype":f"Title{level}", "widgettype":f"Title{level}",
"options":{ "options":{
"text":txt, "text":txt,
"size_hint_x":None, "size_hint_x":None,
"width":self.width, "width":self.width,
"minimum_width":self.width,
"size_hint_y":None, "size_hint_y":None,
"markup":True, "markup":True,
"wrap":True, "wrap":True,
@ -66,12 +73,14 @@ description file format
"valign":"middle" "valign":"middle"
} }
}) })
_,h = w.get_wraped_size() if not w:
return
w1,h1 = w.get_wraped_size()
clen = CSize(1) clen = CSize(1)
if h is None or h < clen: if h1 is None or h1 < clen:
h = clen h1 = clen
w.height = h w.height = h1
print(w,h,w.height) print(w, w1, h1, w.height)
w.bind(on_ref_press=self.open_new_md) w.bind(on_ref_press=self.open_new_md)
self.add_widget(w) self.add_widget(w)
@ -102,12 +111,13 @@ description file format
"wrap":True, "wrap":True,
"size_hint_x":None, "size_hint_x":None,
"width":self.width, "width":self.width,
"minimum_width":self.width,
"markup":True, "markup":True,
"valign":"middle", "valign":"middle",
"halign":"left" "halign":"left"
} }
}) })
if not w:
return
_,h = w.get_wraped_size() _,h = w.get_wraped_size()
clen = CSize(1) clen = CSize(1)
if h is None or h < clen: if h is None or h < clen:

View File

@ -6,13 +6,14 @@ import wave
CHUNK = 1024 CHUNK = 1024
CHANNELS = 2 CHANNELS = 2
FORMAT = pyaudio.paInt16 FORMAT = pyaudio.paInt16
rate = 48000 samplerate = 48000
class Micphone: class Micphone(EventDispatcher):
channels = NumericProperty(2) channels = NumericProperty(2)
rate = NumericProperty(48000) samplerate = NumericProperty(48000)
fps = NumericProperty(1/60) fps = NumericProperty(1/60)
def __init__(self, **kw): def __init__(self, **kw):
super(Micphone, self).__init__(**kw)
self.chunk = CHUNK self.chunk = CHUNK
self.format = pyaudio.Int16 self.format = pyaudio.Int16
self.chunk_buffer = [] self.chunk_buffer = []
@ -21,21 +22,29 @@ class Micphone:
self._audio = puaudio.PyAudio() self._audio = puaudio.PyAudio()
self._mic = p.open(format=self.format, self._mic = p.open(format=self.format,
channels=self.channels, channels=self.channels,
rate=self.rate, rate=self.samplerate,
input=True, input=True,
frames_per_buffer=self.chunk) frames_per_buffer=self.chunk)
self.sampe_size = self.audio.get_sample_size(self.format) self.sampe_size = self.audio.get_sample_size(self.format)
self.register_event_type('on_fps') self.register_event_type('on_fps')
self.register_event_type('on_start')
self.register_event_type('on_end')
self.fps_task = None self.fps_task = None
def on_fps(self, d): def on_fps(self, d):
print('on_fps fired') print('on_fps fired')
def on_start(self):
print('on_start fired')
def on_end(self):
print('on_end fired')
def audio_profile(self): def audio_profile(self):
return { return {
'channels':self.channels, 'channels':self.channels,
'sample_size':self.sample_size, 'sample_size':self.sample_size,
'rate':self.rate 'sample_rate':self.samplerate
} }
def get_frames(self, *args): def get_frames(self, *args):
@ -52,6 +61,7 @@ class Micphone:
def start(self, *args): def start(self, *args):
self.recording = True self.recording = True
Background(self._record) Background(self._record)
self.dispatch('on_start')
self.fps_task = Clock.schedule_interval(self.get_frames, self.fps) self.fps_task = Clock.schedule_interval(self.get_frames, self.fps)
def _record(self): def _record(self):
@ -65,6 +75,7 @@ class Micphone:
def stop(self, *args): def stop(self, *args):
self.recording = False self.recording = False
self.fps_task.cancel() self.fps_task.cancel()
self.dispatch('on_end')
def close(self): def close(self):
self._mic.stop_stream() self._mic.stop_stream()

View File

@ -1,67 +0,0 @@
import json
from functools import partial
from kivy.event import EventDispatcher
from kivy.clock import Clock
from oscpy.server import OSCThreadServer
from oscpy.client import send_message, OSCClient
class OSCServer(EventDispatcher):
def __init__(self,addr='0.0.0.0',
port=60405,
apis=[]):
self.port = port
self.addr = addr
self.clients = []
self.osc_server = OSCThreadServer()
sock = self.osc_server.listen(self.addr,port=self.port,default=True)
EventDispatcher.__init__(self)
apis.append('broadcast')
for api in apis:
event_name = 'on_%s' % api
f = partial(self.handle, api)
setattr(self, event_name, f)
self.register_event_type(event_name)
api_f = partial(self.apihandle,api)
bstr = '/%s' % api
bstr.encode('utf-8')
self.osc_server.bind(bstr, api_f, sock)
def info(self):
ip,port = self.osc_server.getaddress()
return {
"ip":ip,
"port":port
}
def stop(self):
self.osc_server.stop()
def handle(self,api,o,*args):
print(api, *args)
def apihandle(self, api, *args):
print('OSCServer():apihandle():api=', api, 'args=',args)
data = args[0].decode('utf-8')
data = json.loads(data)
sock, ip_address, response_port = self.osc_server.get_sender()
self.dispatch('on_%s' % api, api, data)
if api == 'broadcast':
return
if not address in self.clients:
self.clients.append([ip_address, response_port])
def send_message(self,api, data, addr, port):
data = json.dumps(data)
data = data.encode('utf-8')
bstr = '/%s' % api
bstr = bstr.encode('utf-8')
print('api=', bstr,
'data=', data,
'addr=', addr,
'port=',port)
send_message(bstr, [data], addr, port)
def broadcast(self, data):
for address in self.clients:
self.osc_server.send_message('broadcast', data, *address)

View File

@ -1,4 +1,3 @@
from kivy.event import EventDispatcher
from kivy.core.window import Window from kivy.core.window import Window
from kivy.utils import platform from kivy.utils import platform
from kivy.app import App from kivy.app import App

View File

@ -16,6 +16,7 @@ from .baseWidget import PressableLabel
from .color_definitions import getColors from .color_definitions import getColors
from .bgcolorbehavior import BGColorBehavior from .bgcolorbehavior import BGColorBehavior
from .utils import alert,absurl from .utils import alert,absurl
from .threadcall import HttpClient
class EmptyBox(Label): class EmptyBox(Label):
def __init__(self,size_cnt=1): def __init__(self,size_cnt=1):
@ -323,7 +324,7 @@ class Tree(BGColorBehavior, ScrollWidget):
self.NodeKlass = klass self.NodeKlass = klass
def getUrlData(self,callback,kv=None): def getUrlData(self,callback,kv=None):
hc = App.get_running_app().hc hc = HttpClient()
params = self.options.get('params',{}).copy() params = self.options.get('params',{}).copy()
if not kv is None: if not kv is None:
for k,v in kv.items(): for k,v in kv.items():