Introducing First Contact

18 Jun 2022 ∞

I'd like to introduce a new app I've been working on called First Contact, a quick and easy way to create contact sheets. First Contact features the right balance of options for customizing the layout while not getting you bogged down.

First Contact

There are a number of ways to make contact sheets, but they tend to be part of expensive subscription plans, a side-feature of a DAM, a fancy print dialogue, or some combination of all three. First Contact aims to be fast and easier without sacrificing flexibility.

When you open images in First Contact the PDF is rendered in real-time, showing you exactly what you'll get and how large the final file will be, important if emailing is a concern. To that end you can also use πŸ₯” Mode, which scales images to the actual dimensions of the cell rather than embedding a larger (or full-size) copy.

The layout is easily customized by selecting the number of rows & columns along with the page margin. Your contact sheet can also be given the classic dark mode treatment for night owls.

Once everything is ready you can save the contact sheet and be on your way.

First Contact is available now for $25 with a 14-day free trial. To celebrate use the code first-contact-launch for 10% off!

digital-tech app first-contact

Building a Network Rack

17 Jun 2022 ∞

Full Stack Network

Recently I've been working on building out a more reliable network for my cart. Anyone who's used Capture Pilot knows that it's temperamental at best and the ports are blocked by corporate IT at worst.

I used some spare Ubiquiti equipment I had after upgrading my home network and build a little "rack" that fits inside a Pelican 1300 case. The frame is made of NanoBeam, a 5mm T-slot extrusion beam, which is perfectly suited for the task.

Assembling the frame was tedious, all of the parts are comically tiny and easy to accidentally knock out of place before locked down. After the shelves were installed the whole thing is quite strong.

The final part was powering the USG and switch. Each has its own power supply, but I didn't want to need to run two cables. Reviewing the requirements for the USG I found I could actually run it with PoE via a splitter. To further simplify I ran a patch cable to a keystone socket so all everything connects like normal rack-mounted networking equipment.

I'm happy with how the project turned out and I've already put it into service on set.

digital-tech networking project unifi

ScreeningRoom 2022.3

17 Mar 2022 ∞

In January I announced ScreeningRoom, and yesterday I released the third update of the year! The last couple of updates bring a bevy of new features, bug fixes, and smaller changes:



  • Change stream scale from preferences
  • Display crosshairs over the cursor
  • Option to float preview windows
  • Take a screenshot of all displays from the menu bar


  • Default resolution scale is now Β½ instead of ΒΌ
  • Popover window is now a HUD panel


  • A possible crash when disconnecting a display
  • You no longer have to click twice to start a stream



  • A configurable global shortcut for toggling the popover
  • Create a separate display window using ⌘ and the display number
  • The Send Feedback menu item now works
  • Toggle a display by pressing its associated number key on the keyboard


  • One license is now valid for a machine, rather than account


  • Windows can now be closed with ⌘W

If you've already downloaded ScreeningRoom, thank you, and the update is available from the menu bar. If you'd like to check it out you can download the latest version over at the project page.

captureone digital-tech

Capturebot Lite 2022.2

26 Feb 2022 ∞

Last year I released Capturebot Lite, an app designed to do one thing: create folders. Tonight I'm releasing the first major update of the year. This includes all of the usual Bug Fixes and Improvements one expects, plus some fun new features.

The headliner for the release is Manual Filenames. 2022.2 brings the ability to edit and remove them, but also the option to create repeating names for the shoots that don't require anything more than: Shot 1, Shot 2, etc.

The export processing order has also been tweaked a bit. Trimming characters is now the first step and changing the text case occurs before replacing whitespace. This allows for transforming filenames into CamelCase, for instance.

There are also a few UI updates, like rounding out some text fields and matching the order of the whitespace and illegal character replacement order.

The Capturebot website also has a new help section for Capturebot Lite explaining some of the specifics around import and export.

As always, you can download the latest version or let the app update itself.

captureone digital-tech capturebot

Hexadecimal LED Display

08 Feb 2022 ∞

A while ago saw a link to some old LED hexadecimal displays, DL2416s, little four character modules that accept ASCII and have an LED matrix for the display. I was captivated by them and purchased a handful from eBay with the idea that I'd use them as a thermostat as part of my home automation.

Long story short, I designed a very flawed circuit board that I never quite got working correctly, and abandoned the project. Recently I decided to pick it back up and realized that not once had anyone needed to control the heating via a physical device, so I scrapped it and figured I'd just build a single generic 16-character display.

The Hardware

One goal I had was to minimize the visible PCB, which was tricky because of the through-hole sockets for the display modules. Eventually I decided on a two PCB design: one display module and one logic board for the microcontroller. This would allow the two PCBs to be mounted at 90ΒΊ and give some flexibility for which microcontroller to use.

While prototyping everything on a breadboard I'd never used more than two displays simply due to the wiring complexity. Each display requires 18 pins, all of which are connected together. While I would have liked to installed all four displays, at the end of the day it wouldn't have mattered because I'd still be routing everything in CAD anyway with no way of knowing I'd done it transferred all of the wires correctly.

Once I got the PCBs back and soldered all of the components into place I was relieved to find I had wired everything technically correctly, save one issue that I probably would have found had I prototyped all four displays and a Raspberry Pi Pico instead of an Arduino.

Each digit is addressed with four pins: two chip selects and two digit selects. Something that took me far too long to realize is that when these pins are ordered correctly they make a single 16-bit number, one for each character. When connecting the pins to the Pico I simply matched the pin order of the displays. Had I thought about it I would have realized that placing the pins on adjacent GPIOs (like I did with the data pins) would have meant I could sent the digit enable in a single step.

The Software

Controlling the display is relatively simple:

  1. Select the digit
  2. Pull write low
  3. Write the ASCII character
  4. Pull write high

Similarly a cursor can be shown by setting the bit while the cursor write pin is low, and all cursors can be shown or not with the cursor enable pin. You can also blank the entire display.

With the hardware and basic logic working I next question was what to do with it. The first thing I did while testing reading characters over USB was build a simple terminal based on ASCII control characters. It also serves double duty by allowing a program to interact with the display.

This was also the foundation of the first "real" application: a serial clock. I updated a program I'd written for the 8-character breadboard prototype to make use of the full display and control characters. This worked, but came with the limitation that the Pico couldn't display the time on its own.

The Pico luckily has its own real-time clock (RTC), however setting that clock is a different matter. The simplest way is to just write a program that sends each date and time component bit-by-bit and reassembling it on the other end. On the Pico each component has a fixed length, so counting up the bits isn't too hard.

Letting the Pico handle the date has the advantage of not needing to keep the serial connection open and lets a launch agent reset the clock when the Pico is reconnected.

The Finishing Touches

The final thing I needed to do was find a suitable stand. I figured heading to my local fancy lumber yard and sorting through the scrap bin would be the way to go, and indeed it was. I found a rough hewn piece of ebony wood that really fit the dark PCB and red LEDs.

I proceeded to measure and mark out the length and holes for the standoffs. Unfortunately I decided to do that as the sun was setting and messed up the locations of two of the holes. I filled them and re-drilled, being much more careful, only to break off not one, but two standoffs!

After a couple of tries I got them all in the correct positions and everything assembled. I'm considering adding a bandpass filter in front of the displays, which according to the datasheet will help increase the contrast of the LEDs against background, and a nicer right-angle USB cable.

swift raspberrypi electronics retro project

ScriptSetter 2022.1

18 Jan 2022 ∞

The main window

After, checks notes, three years without any updates I scrapped my original background script plugin and replaced it with a proper application. In short Capture One's plugin API isn't great nor was I even really using it as designed and recent macOS updates broke it the rest of the way.

The new app version of ScriptSetter also gains some new abilities like being able to set scripts for any installed version of Capture One (whether it's running or not), can actually be updated, and is properly signed.

You can check out the update on the project page.

applescript captureone scripting digital-tech


09 Jan 2022 ∞

A project that I've been working on for quite some time is figuring out a good way to do room occupancy using thermopile sensors. I tried lots of different combinations of hardware and software: Wemos D1 boards, MQTT, web sockets, Swift, Raspberry Pis, etc. After each attempt I'd be disappointed with the results and shelve it for a while.

Over the last couple of weeks, however, I feel like I've finally cobbled together a system that's been accurate enough to deploy to a couple rooms in my house. The current solution uses Raspberry Pis, Swift, and MQTT to tie everything together.

The Hardware

A Raspberry Pi Zero and AMG8833 thermopile sensor shoved in a small wooden box, and taped to the top of a door

The hardware is the most straight-forward. It uses an AMG8833 sensor and a Raspberry Pi. Placing the thermopile sensor above a door frame lets it watch people walk through the door. The plan is to eventually make some PCBs to clean up the installation.

The Software

This is, of course, the hard part. Watching a video it's really easy to tell when someone walks under the sensor. Convincing a computer to do that, less so. Luckily there's a lot of prior art I was able to leverage for examples.

The principles are pretty easy:

  1. The sensor is polled 10 times a second for new data
  2. A cluster detection algorithm is run to find a person in frame
  3. The OccupacyCounter is given that data and determines whether someone is walking from top to bottom or visa-versa
  4. The counts are updated and published via MQTT
  5. Other sensors watch MQTT and update their counts for each room

All of this is encapsulated in SwiftOccupancy. It's meant to be run locally on each Raspberry Pi to build a little network of distributed sensors around your house.

Unlike most of the projects I work on, which are apps or basic local command line utilities, debugging was difficult. If for no other reason than I had to get up and walk back and forth through my office door over and over again. This did lead to probably the most comprehensive logging I've done. There's straight logging to a file, several ways to publish raw sensor data to MQTT, a heat-map, and a companion app to pull it all together.

One of the little features I'm proud of is the concept of the Γ¦ther as a room. If you don't want to track occupancy in a room, for instance a door leading outside, you can leave that side empty and internally people will just disappear when they walk into it.

Other Thoughts

The biggest limitation right now is the availability of Raspberry Pi Zero 2s. I bought a bunch of sensors but can't deploy them all because I can only get one Pi at a time.

Another, smaller, issue is power. Any door you want to place a sensor on needs to be close to an outlet. using 15-foot USB cables helps, but doesn't solve everything. For instance I want to place a sensor at the bottom of my stairs, which would mean running a cable from the other side of the hall, up and around the ceiling, then back down.

The other issue that isn't as easily resolved is the cost. A Pi Zero 2 is $15, the AMG88 sensor is ~$25, plus all of the other bits and bobs, each assembled sensor ends up costing $80, probably closer to $100 after shipping and taxes. On the plus side each sensor does cover two rooms, but they add up quickly for a whole house.

All that being said, it's been a fun project and there's still more to work on. If you want to try it out everything's over on GitHub.

homeautomation swift raspberrypi

Camera Setting Monitor Script

08 Jan 2022 ∞

A sample notification

infomercial black & white

Has this ever happened to you: you're in the middle of a shoot, images coming in faster than the computer can keep up with, and suddenly you notice something's wrong. Everything's coming in overexposed! 😫

fade to color

Introducing another script! Simply place the camera_settings_check script in Background Scripts, run it from Capture One's Scripts menu to save your current settings, and you'll be notified after each new capture if the camera's exposure settings have changed.

The script is available as part of my suite of Capture One scripts, for only six easy payments free! However, if you do find my scripts useful consider supporting me on GitHub.

applescript captureone scripting digital-tech

Introducing ScreeningRoom

03 Jan 2022 ∞

The main window

A common occurrence on photo sets is to be running multiple monitors; for the AD, client, stylist, etc. Another common occurrence is not being able to see all of those extra monitors and it's difficult to work when you can't see the display.

Another digital tech, Josh Marrah, had the original idea and asked if I might be able to build an app to let you monitor you monitors. A little bit of playing around with some low-level system APIs and ScreeningRoom was born.

ScreeningRoom lives in your menubar and give you an easy way to glance at all your connected displays, matching their physical layout. You can also create separate windows for any given display for more active monitoring.

It's out now and just $25 with a two-week trial.

captureone digital-tech

Plotting Polynomials

16 Oct 2021 ∞

The first render that worked

Earlier this week I got nerd-sniped by a video about Newton's Fractal, which covered Fun Facts about finding the roots of polynomials that result in a fractal pattern. While watching the video I got caught up in the movement of how a point finds its root, because where there's movement there's something to plot.

One of the nice things about 3Blue1Brown is all of the videos are generated from code, and that code is open source, so I figured I could probably implement the algorithm myself. Eventually I was right, but it took a while to make it all work.

The image to the right is the first render that behaved as expected. I was reimplementing a bunch of methods from JavaScript, most of which used odd syntax I wasn't familiar with. I managed to get most of them working, but the one that ended up causing the most trouble was a method that returned all combinations of the roots. My version never worked correctly, however someone pointed out that what I was trying to do is implemented in Swift Algorithms, so I used that instead and everything came together.

After I had the math part done I could turn my attention to the graphics part. I started off with simple black lines, but one of the more interesting elements of the fractal is which root a points converges on. With this in mind I added colors to the lines, tracing the paths to each root value.

Drawing both the paths and just the pixels at a high enough density shows the fractal emerging, although the path version gets a little too bright with that many lines.

A 6k render

A more reasonable density of lines creates a really nice nebula effect, with most of the paths going towards their closest root, but not all. The overlap produces striking bolts of light between roots.

I'm planning on rendering some for plotting, but first I need to decide whether I'm going to plot them in one color, or try to follow the digital versions and use different colors for each root.

art generative swiftgraphics swift