colinmcardell / SwiftMonome

A Monome library written in Swift

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

SwiftMonome

A Monome library written in Swift

SwiftMonome is a package that wraps around the libmonome C library allowing connection and communication to Monome Grid and Arc devices using the Swift programming language.

Tested and working on MacOS and Linux.

Prerequisites

Platform Information Instructions
Mac OS Use Homebrew brew install libmonome
Linux Manual Compile Recommended More info here
Raspberry Pi Manual Compile Recommended More info here
Platform Information Instructions
Mac OS Comes with Xcode Get Xcode
Linux A good number of official distributions Download here
Raspberry Pi Compiling takes forever, try an unofficial pre-compiled version Download here

Install & Connect

Add SwiftMonome to your Package.swift as a dependency:

// Package.swift

// swift-tools-version:4.2
import PackageDescription

let package = Package(
    // ...
    dependencies: [
        .Package(url: "https://github.com/colinmcardell/SwiftMonome.git", from: "0.0.5")
    ],
    // ...
    targets: [
        .target(
            //...
            dependencies: ["SwiftMonome"]),
    ]
)

Basic connection to an attached Monome device:

import SwiftMonome

// Monome? Failable Initializer, optional value of Monome or nil

// Linux device path
let monome: Monome? = Monome("/dev/ttyUSB0")

// or
// Mac OS device path
let monome: Monome? = Monome("/dev/cu.usbserial-m1000286")

// or
// OSC path (serialoscd)
let monome: Monome? = Monome("osc.udp://127.0.0.1:9000/monome")

// or
// default device "osc.udp://127.0.0.1:8080/monome"
let monome: Monome? = Monome()

// or
// Using guard during initialization
guard let monome = Monome("/dev/ttyUSB0") else {
    fatalError("Error connecting to Monome device.")
}

Usage Basics

Here are some basic examples on how to communicate to a Monome device with SwiftMonome. These examples all assume an optional constant let monome: Monome? = Monome() described in the section above on connecting to a Monome device...

For additional examples look in the /Sources/monome-examples folder of this repo.

LED on/off/level

// Setting the status of all LEDs on a Grid

// Value of 0 or 1
monome?.all(1) // All LEDs on
// Setting the intensity of all of the LEDs that are set to on

// Value of 0 through 15
monome?.intensity(15) // All LEDs that are on scaled to 100% brightness
// Setting the status of a specific LED

monome?.set(x: 0, y: 0, status: 1) // Top left corner set to on
monome?.set(x: 7, y: 15, status: 1) // Bottom right corner set to on
monome?.set(x: 0, y: 0, status: 0) // Top left corner set to off
// Display a map of values
// ... specifically a nice greeting from your Monome grid

func displayHello() {
    let hello: [[UInt8]] = [
        [0b01110101,
         0b00010101,
         0b00110111,
         0b00010101,
         0b00010101,
         0b00010101,
         0b00010101,
         0b01110101], // H E
        [0b01100101,
         0b10010101,
         0b10010101,
         0b10010101,
         0b10010101,
         0b10010101,
         0b10010101,
         0b01101111] // L L O
    ]
    monome?.map(x: 0, y: 0, data: hello[0])
    monome?.map(x: 8, y: 0, data: hello[1])
}

displayHello()

Rotation

// Setting the Monome rotation (where the USB cable is)

monome?.rotation = .left // Default
monome?.rotation = .bottom
monome?.rotation = .right
monome?.rotation = .top

Events

Events are handled by closures and/or delegation.

// Adding a event handling closure to respond to grid button events

monome?.gridEventHandler = { event in
    let x = event.x // Int value
    let y = event.y // Int value

    switch event.action {
    case .buttonDown:
        print("Got a button goin' dooooown - x: \(x), y: \(y)")
    case .buttonUp:
        print("Got a button jumpin' up - x: \(x), y: \(y)")
    }
}
// Setting a class as an event delegate

class MonomeController: MonomeGridEventDelegate {

    let monome = Monome()

    init() {
        monome?.gridEventDelegate = self
        // ... a bit of code to drive the eventHandleNext() call (see next code block)
    }

    func handleGridEvent(monome: Monome, event: GridEvent) {
        switch event.action {
        case .buttonDown:
            print("Button Down! Button Down!")
        case .buttonUp:
            print("Nevermind, it's back up.")
        }
    }
}

Events that have been triggered need to be driven by a periodic call to eventHandleNext().

// Driving the events of the connected Monome device

monome?.eventHandleNext()

// or
// Using a blocking loop
var shouldQuit = false
while !shouldQuit {
    monome?.eventHandleNext()
}

// or
// Using a dispatch source
let timeInterval: DispatchTimeInterval = .milliseconds(16)
let queue: DispatchQueue = DispatchQueue.global(qos: .userInteractive)
let timer: DispatchSourceTimer = DispatchSource.makeTimerSource(queue: queue)
timer.setEventHandler {
    monome?.eventHandleNext()
}
timer.schedule(deadline: .now(), repeating: timeInterval)
timer.resume()

More Examples

A number of Swift reimplementations of the libmonome examples are provided that can be used as a reference, here.

You can run these examples:

  1. Clone this repository - git clone https://github.com/colinmcardell/SwiftMonome.git
  2. cd SwiftMonome
  3. make run (assuming you have all of the prerequisites satisfied)
  4. Follow the on-screen usage instructions

Contribution

Feedback, comments, bug reports are welcome. Please file an issue or make a PR.

Thanks!

Colin McArdell - colin(at)colinmcardell(dot)com

About

A Monome library written in Swift

License:MIT License


Languages

Language:Swift 98.7%Language:Makefile 0.9%Language:C 0.5%