コード例 #1
0
ファイル: timeline.py プロジェクト: pussinboot/sol
class MidiThread(threading.Thread):
	def __init__(self,timeline):
		super().__init__()
		self.stopped = False
		self.MC = MidiControl()
		self.timeline = timeline

	def run(self):
		print('running')
		while not self.isStopped():
			res = self.MC.test_inp()
			if res:
				#print(res)
				n = res[1]
				if n > 120:
					n = n - 128
				if n < 10:
					timeline.integrate_midi(n)
				#print(n)

		print('stopped')
		
	def isStopped(self):
		return self.stopped

	def stop(self):
		self.stopped = True
		self.MC.quit()
コード例 #2
0
ファイル: main.py プロジェクト: Xycl/BackingTrackPlayer
class BackingTrackPlayerApp(App):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.mc = MidiControl()

    def build(self):
        self.title = 'Backing Track Player V1.0'
        self.use_kivy_settings = False
        Window.bind(on_dropfile=self._dropfile_action)
        return Builder.load_string(kv)

    def _dropfile_action(self, window, path):
        self.root.set_backing_track(path.decode())

    def on_start(self):
        names = self.mc.get_midi_ports()
        self.root.ids.midi_devices.values = names
        m_input = self.config.getdefault('MIDI', 'input', 'None')
        ch = self.config.get('MIDI', 'channel')
        song = self.config.get('Track', 'song')
        if m_input in names:
            self.root.set_backing_track(
                song
            )  # before set midi ports - so errors can show in track area
            self.mc.set_midi_port(m_input)
            self.mc.midi_channel = int(ch)
            self.root.ids.midi_devices.text = m_input
            self.root.ids.midi_ch.text = str(int(ch) + 1)
        Clock.schedule_interval(self.mc.read_midi_callback, .1)

    def open_settings(self, *largs):  # kivy control panel will not open
        pass

    def build_config(self, config):
        config.setdefaults('MIDI', {'input': 'None', 'channel': 'None'})
        config.setdefaults('Track', {'song': 'None'})

    def get_application_config(self, defaultpath='%(appdir)s/%(appname)s.ini'):
        if platform == 'macosx':  # mac will not write into app folder
            s = '~/.%(appname)s.ini'
        else:
            s = defaultpath
        return super().get_application_config(defaultpath=s)

    def on_stop(self):
        if self.mc.midi_in_port and self.mc.midi_channel is not None and self.root.track_path:
            self.config.set('MIDI', 'input', self.mc.midi_in_port.name)
            self.config.set('MIDI', 'channel', self.mc.midi_channel)
            self.config.set('Track', 'song', self.root.track_path)
            self.config.write()
コード例 #3
0
ファイル: timeline.py プロジェクト: pussinboot/sol
	def __init__(self,timeline):
		super().__init__()
		self.stopped = False
		self.MC = MidiControl()
		self.timeline = timeline
コード例 #4
0
 def __init__(self, **kwargs):
     super().__init__(**kwargs)
     self.mc = MidiControl()
コード例 #5
0
class BackingTrackPlayerApp(App):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.mc = MidiControl()

    def build(self):
        self.title = 'Backing Track Player V1.01'
        self.use_kivy_settings = False
        Window.minimum_width = window_width
        Window.minimum_height = window_height
        # Window.size = 800, 375
        Window.bind(on_dropfile=self._dropfile_action)
        Window.bind(on_request_close=self.window_request_close)
        return Builder.load_string(kv)

    def _dropfile_action(self, _, path):
        self.root.ids.sm.get_screen('play_screen').set_backing_track(
            path.decode())

    def on_start(self):
        names = self.mc.get_midi_ports()
        self.root.ids.midi_devices.values = names
        m_input = self.config.getdefault('MIDI', 'input', 'None')
        ch = self.config.get('MIDI', 'channel')
        song = self.config.get('Track', 'song')
        if not Path(song).exists(
        ):  # if track that was in config file was no longer exists...
            song = 'None'
        self.root.ids.sm.get_screen('play_screen').set_backing_track(song)
        # before set midi ports - so errors can show in track area
        if m_input in names:
            self.mc.set_midi_port(m_input)
            self.mc.midi_channel = int(ch)
            self.root.ids.midi_devices.text = m_input
            self.root.ids.midi_ch.text = str(int(ch) + 1)
        Clock.schedule_interval(self.mc.read_midi_callback, .1)

    def open_settings(self, *largs):  # kivy control panel will not open
        pass

    def build_config(self, config):
        config.setdefaults('MIDI', {'input': 'None', 'channel': 'None'})
        config.setdefaults('Track', {'song': 'None'})
        config.setdefaults(
            'Window', {
                'width': window_width,
                'height': window_height,
                'top': window_top,
                'left': window_left
            })

    def get_application_config(self, defaultpath='%(appdir)s/%(appname)s.ini'):
        if platform == 'win' or platform == 'macosx':  # mac will not write into app folder
            s = self.user_data_dir + '/%(appname)s.ini'  # puts ini in AppData on Windows
        else:
            s = defaultpath
        return super().get_application_config(defaultpath=s)

    def window_request_close(self, _):
        # Window.size is automatically adjusted for density, must divide by density when saving size
        config = self.config
        config.set('Window', 'width', int(Window.size[0] / Metrics.density))
        config.set('Window', 'height', int(Window.size[1] / Metrics.density))
        config.set('Window', 'top', Window.top)
        config.set('Window', 'left', Window.left)
        self.config.write()
        return False

    def on_stop(self):
        p = self.root.ids.sm.get_screen('play_screen').track_path
        if p:
            self.config.set('Track', 'song', p)
            self.config.write()
        if self.mc.midi_in_port and self.mc.midi_channel is not None:
            self.config.set('MIDI', 'input', self.mc.midi_in_port.name)
            self.config.set('MIDI', 'channel', self.mc.midi_channel)
            self.config.write()
コード例 #6
0
ファイル: sol_backend.py プロジェクト: pussinboot/sol
	def setup_midi(self):
		self.midi_control = MidiControl(self)
コード例 #7
0
ファイル: sol_backend.py プロジェクト: pussinboot/sol
class Backend:
	"""
	entire backend for sol
	"""
	def __init__(self,xmlfile=None,gui=None,ports=(7007,7008)):
		self.xmlfile = xmlfile
		self.library = Library(xmlfile)
		self.cur_clip = Clip('',[-1,-1],"no clip loaded")
		self.cur_song = None
		self.cur_rec = None
		self.cur_col = -1
		self.search = SearchR(self.library.clips)
		self.osc_client = ControlR(self,port=ports[0]) 
		self.osc_server = ServeR(gui,port=ports[1])
		self.record = RecordR(self)
		self.last_save_file = None

		self.cur_time = RefObj("cur_time")
		self.cur_clip_pos = RefObj("cur_clip_pos",0.0)

		def update_time(_,msg): # this is the driving force behind the (audio) backend :o)
			try:
				self.cur_time.value = int(msg)
			except:
				pass
		def update_song_info(_,msg):
			if self.cur_song:
				self.cur_song.vars['total_len'] = int(msg)
		self.osc_server.map("/pyaud/pos/frame",update_time)
		self.osc_server.map("/pyaud/info/song_len",update_song_info)
		self.osc_server.map("/activeclip/video/position/values",self.cur_clip_pos.update_generator('float'))

		### MIDI CONTROL
		# basically, here are the descriptions that map to functions
		# then in the midi config it reads the keys and figures out 
		# what keys to set to which functions
		# which are then mapped thru the osc server to figure out 
		# what to do with the note value (different types of notes)
		self.desc_to_fun = {
			'clip_play'    : self.osc_client.play         ,
			'clip_pause'   : self.osc_client.pause        ,
			'clip_reverse' : self.osc_client.reverse      ,
			'clip_random'  : self.osc_client.random_play  ,
			'clip_clear'   : self.osc_client.clear        ,

		}
		# can also auto-gen some of these for cue select etc

		def gen_selector(i):
			index = i
			def fun_tor():
				self.select_clip(self.library.clip_collections[self.cur_col][index])
			return fun_tor
		for i in range(C.NO_Q):
			self.desc_to_fun['clip_{}'.format(i)] = gen_selector(i)
		# no clue how im going to add midi out.. for now
		self.midi_control = None
		#self.load_last()

	def setup_midi(self):
		self.midi_control = MidiControl(self)

	def save_data(self,savefile=None):
		if not os.path.exists('./savedata'): os.makedirs('./savedata')
		if not savefile:
			if not self.last_save_file:
				filename = os.path.splitext(self.xmlfile)[0]
				filename = filename.split('/')[-1]
				savefile = "./savedata/{}".format(filename)
			else:
				savefile = self.last_save_file
		########
		savedata = {'xmlfile':self.xmlfile,'library':self.library,
		 'current_clip':self.cur_clip,'current_collection':self.cur_col}
		########
		with open(savefile,'wb') as f:
			dill.dump(savedata,f)
			with open('./savedata/last_save','w') as last_save:
				last_save.write(savefile)
			print('successfully saved',savefile)
			self.last_save_file = savefile
			return savefile # success

	def load_data(self,savefile):
		if os.path.exists(savefile):
			with open(savefile,'rb') as save:
				savedata = dill.load(save)
				########
				loaddata = {'xmlfile':'self.xmlfile','library':'self.library',
						 'current_clip':'self.cur_clip','current_collection':'self.cur_col'}
				########
				for key in loaddata:
					if key in savedata:
						exec("{} = savedata[key]".format(loaddata[key]))
				self.search = SearchR(self.library.clips)
				print('successfully loaded',savefile)
				self.last_save_file = savefile

	def load_composition(self,fname):
		if fname == self.xmlfile:
			# add any new clips
			self.library.update_from_xml(fname)
			print('updated library from',fname)
		else:
			self.xmlfile = fname
			self.library = Library(fname)
			self.cur_clip = Clip('',[-1,-1],"no clip loaded")
			self.cur_col = -1
			print('loaded library from',fname)
		self.search = SearchR(self.library.clips)


	def load_last(self):
		if os.path.exists('./savedata/last_save'):
			with open('./savedata/last_save') as last_save:
				fname = last_save.read()
				self.load_data(fname)
				if self.midi_control is not None: self.load_last_midi()
				#self.record.load_last() dangerous (have to implement dependency on audio track 2 do this)

	def load_last_midi(self):
		if os.path.exists('./savedata/last_midi'):
			with open('./savedata/last_midi','r') as last_midi:
				fname = last_midi.read()
				self.midi_control.map_midi(fname)

	def change_clip(self,newclip):
		if self.cur_clip is not None: self.cur_clip.last_pos = self.cur_clip_pos.value
		self.cur_clip = newclip
		self.osc_client.select_clip(newclip)

	def select_clip(self,newclip): # function to be overwritten : )
		self.change_clip(newclip)