Example #1
0
def exit_process(signum, frame):

	global running

	logservice.log(logservice.LOG_INFO, 'Got SIGINT, shutting down...')

	signal.setitimer(signal.ITIMER_REAL, 0, 0)

	# Kill any running patches and wait for them to exit
	patchservice.kill_running_patch()

	# Clean up shared memory
	eventservice.shutdown()

	interface_process.terminate()
	time.sleep(0.1)
	interface_process.join()

	display_process.terminate()
	time.sleep(0.1)
	display_process.join()

	web_process.terminate()
	time.sleep(0.1)
	web_process.join()

	bc_process.terminate()
	time.sleep(0.1)
	bc_process.join()

	running = 0
Example #2
0
def loadpatch(parent):

	# TODO: provide a quick way to get to running patch

	global running_patch
	global patch_menu


	# If the running one is not the one that's to be loaded, then load it.
	if (running_patch is None) or (running_patch["patchfilepath"] != parent["patchfilepath"]):

		kill_running_patch()

		# Clear our state management now that nothing is running
		patch_menu = {}
		controllermodel.controller_processes = []
		controllermodel.controller_count.value = 0

		# Load the config
		with open(parent["patchfilepath"]) as data_file:

			data = json.load(data_file)

			# TODO: What if the data's not there?
			for controllerdata in data["program"]["controllers"][:controllermodel.MAX_CONTROLLERS]:

				controllername = controllerdata["module"]

				logservice.log(logservice.LOG_INFO, 'Loading controller "{0}"'.format(controllername))

				controllermodule = importlib.import_module(controllername)

				# Start up the worker for this controller
                		cw = controllerworker.ControllerWorker(controllermodule, data, controllermodel.controller_queues[controllermodel.controller_count.value])

				controllermodel.controller_count.value += 1

				controller_process = Process(target=cw.run)

				# Remember our process for later
				controllermodel.controller_processes.append(controller_process)
				running_patch = parent

				# Add the menu
				# TODO: support multiple menus
				patch_menu = [{
						'text': 'brightness',
						'integervalue': 'brightness',
						'min': 0,
						'max': 255
					},
					{
						'text': 'reset',
						'action': 'reset'
					}]

				# Start the process
				controller_process.start()

	return patch_menu
Example #3
0
def refresh():

    removed = []

    for device_filename in os.listdir(systemmodel.DEV_INPUT):

        if device_filename.startswith('js') and device_filename not in device_names:

            # TODO: We can write to these guys too
            # Open the file, blocking
            time.sleep(0.5)
            f = open("/dev/input/" + device_filename, 'rb')
            
            # Get the device name JSIOCGNAME(len)
            buf = array.array('c', ['\0'] * 64)
            ioctl(f, 0x80006a13 + (0x10000 * len(buf)), buf)
            name = buf.tostring()
            
            logservice.log(logservice.LOG_INFO, 'New game controller: {0}'.format(device_filename))
            displaymodel.alert("New gamepad:", device_filename)            
            
            # Add to the device list
            devices[f.fileno()] = {
                
                "type" : gamepadmodel.DEVICE_TYPE_GAMEPAD,
                "filename" : device_filename,
                "name" : name,
                "file" : f,
                "getevent" : getevent
            }

            device_names.add(device_filename)

    
    return removed
Example #4
0
	def __init__(self, controllermodule, config, q):

		"""
		Instantiates a new Controller.

		:param controllermodule: A controller instance.
		:param config: The parsed json defining a given patch
		:param q: The message queue assigned to this worker
		"""

		signal.signal(signal.SIGINT, signal.SIG_IGN)

		self.config = config

		self.q = q

		self.controller = controllermodule.Controller(config)

		self.clocked = isinstance(self.controller, BaseClockedController)

		# Setup the thread we are on
		self.configure_thread()

		#TODO: sync start time across threads
		# Start absolute system time
		self.t = precision_timer.getabsolutetime()

		logservice.log(logservice.LOG_DEBUG, 'Start time for controller worker {0:.6f}'.format(self.t))

		self.next_t = self.t
Example #5
0
	def __init__(self, config):

		# Create a thread that just listens to semaphore events

		self.event_thread = EventThread()

		self.event_thread.start()

		logservice.log(logservice.LOG_ERR, 'Initialized value debug')
Example #6
0
File: devio.py Project: nw2s/b2-dsp
def process():
    
    event = None
    
    while 1:

        # TODO Monitor udev for new devices instead?
        # Wait for a device to have data ready, abort after 5 seconds and refresh the device list            
        r, w, x = select(devices.keys(), [], [], 5)

        for fd in r:

            # Get a handier reference to the device that has data ready
            device = devices[fd]

            # Decode the available chunks
            try: 

                event = device["getevent"](device)
        
            except IOError:
        
                logservice.log(logservice.LOG_INFO, "Error reading from device, removing")
                
                del devices[fd]
        
        
            if event is not None:

                # Add the key of the source device
                event["source"] = fd

                # If it's a responseq item, send to its destination
                if (device["type"] == responseqio.DEVICE_TYPE_RESPONSEQ):
                
                    if event["target"] in devices:
                        
                        devices[event["target"]]["message"](devices[event["target"]], event)
                        
                    else:
                        
                        logservice.log(logservice.LOG_INFO, "Got a message for a missing device. Discarding.")
            
                else:
                    
                    # Filter and handle the events
                    for handler in handlers.values():

                        if handler["filter"](device, event): handler["handler"](device, event)
                    
                                            
        # After select times out, refresh the devices
        # TODO: this will also happen after an event which we don't want
        refresh()
Example #7
0
def getpatchname(patchpath, patchfilename):

	try:

		with open(os.path.join(patchpath, patchfilename)) as data_file:

			data = json.load(data_file)

			return data["program"]["name"]

	except Exception as e:

		logservice.log(logservice.LOG_ERR, 'Error getting patch name for "{0}": {1}'.format(patchfilename, e))
		logservice.log(logservice.LOG_ERR, traceback.format_exc())

		return patchfilename[:16]
Example #8
0
	def configure_thread(self):

		# TODO: setup prctl for embedded platform

		try:

			os.nice(-15)

		except OSError:

			logservice.log(logservice.LOG_ERR, 'Unable to set nice level on worker. Leaving as-is')

		# If mach/osx, allow thread to access precision timers
		if not systemmodel.EMBEDDED:

			logservice.log(logservice.LOG_INFO, 'Configuring thread access to timers')
			precision_timer.configurethread(0, 5, 10)
Example #9
0
def run():
	signal.signal(signal.SIGINT, signal.SIG_IGN)

	# Initialize our possible input devices
	devio.initialize()

	# Set up our filters and callbacks
	devio.add_handler("interface_game_buttons", filter_buttons, handle_buttons)
	devio.add_handler("interface_stdin", filter_stdin, handle_stdin)
	devio.add_handler("patchmessages", filter_patch, handle_patch)

	# Loop forever
	while 1:

		# If we get an exception, show the error and start over
		try:

			# Show welcome message and sleep for 1s
			displaymodel.display_line_one("nw2s:b2/dsp v0.1")
			displaymodel.display_line_two("")

			time.sleep(1.0)

			# Show the main menu
			oledmenuservice.navigateroot()

			# Hand off control to the input manager
			devio.process()

		except Exception as e:

			logservice.log(logservice.LOG_ERR, 'Error in interface worker thread: {0}'.format(e))
			logservice.log(logservice.LOG_ERR, traceback.format_exc())

			# Reset the menu
			oledmenuservice.reset()

			# Show the error:
			displaymodel.display_line_one('Error:')
			displaymodel.display_line_two(str(e)[:16])

			time.sleep(2.0)
Example #10
0
def getevent(device):

    try:
        
        # gamepads spit 8 bytes per chunk
        data = device["file"].read(8)
    
        # unpack the data...
        time, value, type, number = struct.unpack('IhBB', data)

        # ...and make it look like something useful
        return { "type" : type, "number" : number, "value" : value }
        
    except IOError as err:
        
        logservice.log(logservice.LOG_INFO, "Error reading from js device")
        
        device_names.remove(device["filename"])
        del devices[device["file"].fileno()]

        raise err
Example #11
0
	def run(self):

		while self.running:

			try:

				# Wait for the value to go above 0
				self.sem.acquire()

			except sysv_ipc.Error as ex:

				pass


			# Semaphore available, something changed
			for x in (p for p in enumerate(izip(self.triggers, eventmodel.triggers)) if p[1][0] != p[1][1]):

				logservice.log(logservice.LOG_ERR, 'changed trigger: ' + str(x))

				self.triggers[x[0]] = x[1][1]

			for x in (p for p in enumerate(izip(self.cvalues, eventmodel.cvalues)) if p[1][0] != p[1][1]):

				logservice.log(logservice.LOG_ERR, 'changed cvalue: ' + str(x))

				self.cvalues[x[0]] = x[1][1]

			for x in (p for p in enumerate(izip(self.dvalues, eventmodel.dvalues)) if p[1][0] != p[1][1]):

				logservice.log(logservice.LOG_ERR, 'changed dvalue: ' + str(x))

				self.dvalues[x[0]] = x[1][1]
Example #12
0
File: oto.py Project: nw2s/b2-dsp
	def __init__(self, config):

		# Events
		self.event_sem = eventservice.get_event_semaphore()

		# Sources
		self.sources = []
		self.devices = {}

		# Storage for raw button states
		self.buttons = {}

		# Storage for the active cell states
		self.cells = {}

		# Track serial numbers issues to cells
		self.serial = 0

		# Assume a basic tempo
		self.tempo = 120

		logservice.log(logservice.LOG_ERR, 'Initialized otogrid')
Example #13
0
def getevent(device):

	event = None

	# We're getting weird errors when disconnecting device. Make sure it's there first.
	if not os.path.exists(device["filename"]):

		return None


	# Pulling the event out of the buffer by hand - if it's ready
	try:

		event = device["monome"].next_event()

	except RuntimeError as e:

		logservice.log(logservice.LOG_ERR, 'Error catching monome event: {0}'.format(e))
		logservice.log(logservice.LOG_ERR, traceback.format_exc())

		device_names_invalid.add(device['filename'])

		event = None


	# TODO: Maybe we get more than one event at a time? If we miss some, refactor this
	if event is not None:

		# This event that goes on the queue needs to be pickleable, so just putting in the important info
		qevent = {

			"type": DEVICE_TYPE_MONOME,

			"device": {

				"type": DEVICE_TYPE_MONOME,
				"name": device["monome"].name,
				"protocol": device["monome"].protocol,
				"rows": device["monome"].rows,
				"columns": device["monome"].columns
			},

			"event": {}
		}

		# TODO: Support other types of monome events
		if isinstance(event, monome.MonomeGridEvent):

			qevent["event"]["pressed"] = event.pressed
			qevent["event"]["x"] = event.x
			qevent["event"]["y"] = event.y

		logservice.log(logservice.LOG_DEBUG, str(qevent))

		return qevent

	# Otherwise, we'll try again later.
	return None
Example #14
0
def run():

    signal.signal(signal.SIGINT, signal.SIG_IGN)

    try:

        if not os.path.exists(DISPLAY_DEVICE_PATH):
            
            # If we don't have a device, just send data to dev null and log it.
            logservice.log(logservice.LOG_ERR, "No such display device: " + DISPLAY_DEVICE_PATH)
            display_device_path = "/dev/null"

        logservice.log(logservice.LOG_INFO, "Opening display device " + display_device_path)
        
        display_device = open(display_device_path, "a")

        while 1:
            
            # See if anything is on the queue
            displaymessage = displaymodel.getmessage()
            
            # If so, then show it for 2 seconds
            if displaymessage is not None:
                
                line1 = '{0: <16}'.format(displaymessage["line1"][:16])
                line2 = '{0: <16}'.format(displaymessage["line2"][:16])
                
                display_device.write(line1 + line2)
                display_device.flush()
                
                time.sleep(2)
                
                # TODO: Don't do this if we have more waiting
                display_device.write(displaymodel.get_data())
                display_device.flush()

            elif displaymodel.is_modified():

                display_device.write(displaymodel.get_data())
                display_device.flush()
                
                print(displaymodel.get_data())

            #powernap.nap(0.05)
            time.sleep(0.05)
            
        display_device.close()
        
    except Exception as e:

        logservice.log(logservice.LOG_ERR, 'Exception in displayworker thread: {0}'.format(e))
Example #15
0
	web_process.terminate()
	time.sleep(0.1)
	web_process.join()

	bc_process.terminate()
	time.sleep(0.1)
	bc_process.join()

	running = 0


# Setup Ctrl-C to exit gracefully
signal.signal(signal.SIGINT, exit_process)

# Log any interesting information as we get started
logservice.log(logservice.LOG_INFO, "Platform: " + platform.platform())

# Start up the display worker
display_process = Process(target=displayworker.run)
display_process.start()

# Start up the interface worker
interface_process = Process(target=interfaceworker.run)
interface_process.start()

# Start up web worker
web_process = Process(target=webworker.run)
web_process.start()

# Start broadcast worker
bc_process = Process(target=broadcastworker.run)
Example #16
0
def refresh():

	removed = []

	for device in devices.keys():

		# See if the file is still there
		if not os.path.exists(devices[device]["filename"]):

			# If not, remove it from all the places we track them
			device_names.remove(devices[device]["filename"])
			del devices[device]
			removed.append(device)


	# If the file is gone, we can also remove it from our bad guy list.
	toremove = []

	for filename in device_names_invalid:

		# If not, remove it from all the places we track them
		if not os.path.exists(filename):

			toremove.append(filename)

	for filename in toremove:

		device_names_invalid.remove(filename)

	# Refresh the device list every once in a while
	for device_filename in glob.glob(monomemodel.GRID_DEV_GLOB):

		if (device_filename not in device_names) and (device_filename not in device_names_invalid):

			try:

				# Sleep for a bit just to see if udev needs time
				time.sleep(0.5)

				# Try to create the device
				device = monome.Monome(device_filename)

				# Get the serial number, names, etc.
				devices[device.fileno()] = {

					"type": DEVICE_TYPE_MONOME,
					"filename": device_filename,
					"monome": device,
					"getevent": getevent,
					"message": message
				}

				# TODO - display in window
				logservice.log(logservice.LOG_INFO, 'New monome controller: {0}'.format(device_filename))
				displaymodel.alert("New monome:", device_filename)

				# TODO: Need to remove them too
				device_names.add(device_filename)

				# Set Rotation
				device.rotation = monome.ROTATE_0

				# TODO: Why is this crashing the device?!
				# Clear the device
				# device.led_all(1)
				# time.sleep(0.1)
				# device.led_all(0)
				# time.sleep(0.1)


			except Exception:

				# Add to the invalid list
				device_names_invalid.add(device_filename)

				logservice.log(logservice.LOG_INFO, 'Device {0} was not a monome or there was an error trying.'.format(device_filename))

	# Pass back any that got removed
	return removed
Example #17
0
File: oto.py Project: nw2s/b2-dsp
	def button_handler(self, source, device, event):


		if source not in self.sources:

			self.sources.append(source)
			self.devices[source] = device
			self.cells[source] = []
			self.buttons[source] = [[0 for x in xrange(0, device['columns'])] for x in xrange(0, device['rows'])]

			logservice.log(logservice.LOG_ERR, "Added a new oto source: " + str(source))
			logservice.log(logservice.LOG_ERR, "Columns: " + str(device['columns']))
			logservice.log(logservice.LOG_ERR, "Rows: " + str(device['rows']))

		# Add this cell
		direction = CELL_UP

		# If it was added on an edge, correct the direction
		if event['x'] == 0:

			direction = CELL_RIGHT

		if event['x'] == device['columns'] - 1:

			direction = CELL_LEFT

		if event['y'] == 0:

			direction = CELL_DOWN

		remove_action = False

		# If it collides with an existing cell, then remove them both
		for cell in self.cells[source]:

			if cell['row'] == event['y'] and cell['column'] == event['x'] and cell['serial'] != self.serial:

				self.cells[source].remove(cell)
				remove_action = True

		if not remove_action:

			self.cells[source].append( {

				'direction': direction,
				'column': event['x'],
				'row': event['y'],
				'serial' : self.serial
			})

			self.serial += 1



		x = event["x"]
		y = event["y"]

		self.buttons[source][y][x] ^= 1

		if self.buttons[source][y][x]:

			responseq.put({

				"type": monomeio.DEVICE_TYPE_MONOME,
				"command": monomemodel.COMMAND_LED_ON,
				"target": source,
				"x": x,
				"y": y

			})

		else:

			responseq.put({

				"type": monomeio.DEVICE_TYPE_MONOME,
				"command": monomemodel.COMMAND_LED_OFF,
				"target": source,
				"x": x,
				"y": y

			})
Example #18
0
	def clock(self, t):

		logservice.log(logservice.LOG_ERR, 'clocked template tick')
Example #19
0
	def __init__(self, config):

		self.last_trigger_t = 0.0
		self.sem = eventservice.get_event_semaphore()

		logservice.log(logservice.LOG_ERR, 'Initialized probability trigger')
Example #20
0
	def __init__(self, config):

		# Not much to initialize at the moment.
		logservice.log(logservice.LOG_ERR, 'Initialized template')