Building a Finder Extension for Capture One

29 Jun 2022 ∞

Way back with macOS Yosemite Apple introduced an API meant for cloud sync applications like Dropbox to be able to add badges to files and folders, and after finding an application called GitFinder which leverages theses APIs to do something other than sync it got me thinking about building an extension that adds common digital tech tasks directly into the Finder.

A very simple version would just add menu items for setting the capture folder and adding folders to favorites, but the Fun Version would also sync those states as badges. A couple days a I decided to really look at the extension API to see if I could build such a thing.

The short answer is "yes".

As part of myriad other projects I've built myself a fairly robust bridge between Capture One's AppleScript library and Swift. The bridge has its own mini-API for interacting with Capture One and handles converting AppleEvents to and from Swift objects1. The Finder Sync API is relatively straight forward, it asks you about files and folder and in return you tell it what badge to display.

However, because nothing can be so simple, one issue I ran into was actually interacting with Capture One. The app extension refused to send Apple Events, which I assume is a security measure. After looking into the docs a bit more I figured an XPC service, which lets you move some of the business logic into its own process, was the way to go. I've never built anything using XPC and making sense of the API required a fair amount of research2.

Eventually I did manage to get everything working. The extension adds menus for setting the capture folder, adding and removing folders from favorites, and viewing a folder in Capture One. Crucially it also adds badges for the current capture folder and folders that are in favorites. The badges will even update in (somewhat) real-time to reflect changes made in Capture One.

While it does work the entire thing feels incredibly fragile. The extension communicates via XPC with the launch agent, which in turn calls Capture One via AppleEvents, which may time out and never complete. Updating based on changes in Capture One requires a repeating timer rather than actually being notified of the event. There are a number of states that could easily get out of sync. Everything only works on the current document, and would almost certainly break if multiple were open.

Honestly this is something I would love for Capture One to integrate themselves. I can't imagine them doing so anytime soon, but it would be a nice feature that could directly benefit working digital techs.

  1. I should probably publish that code into its own library.

  2. For instance, Apple's own XPC template won't compile.

capture-one digital-tech applescript swift software

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:

2022.2

Added

  • 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

Changed

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

Fixed

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

2022.3

Added

  • 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

Changed

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

Fixed

  • 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.

capture-one 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.

capture-one 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 raspberry-pi 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 capture-one scripting digital-tech

SwiftOccupancy

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.

home-automation swift raspberry-pi

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 capture-one 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.

capture-one digital-tech