Deep Happy
Features
Everything Deep Happy does today, stated in full — not the highlights, the complete list. Every item below says what it does, where you find it, and what it does by default. Every fact here is true of the app as it is built; nothing on this page is a plan for later.
What it is
Deep Happy is a native macOS menu-bar player for internet radio, written in Swift 6 with SwiftUI and AppKit and requiring macOS 26 or later. It has no third-party dependencies, no account, and nothing to sign into.
It is a player, not a broadcaster's app: you point it at a stream, or search a directory for one, and it plays it. Its reason to exist is the part most internet-radio players get wrong — staying playing through the ordinary interruptions of a laptop's day — and its second trick is that the Mac doing the playing can be driven from another Mac.
The short version of all of this is on the Deep Happy overview; the questions people actually ask are on the frequently asked questions page.
Playback that survives sleep, a VPN and a stalled socket
Internet-radio players fail in ordinary situations — a VPN reconnecting, a laptop lid closing, a socket that stalls without reporting it — and the usual failure is not an error message but an app that says Playing while making no sound. Deep Happy exists to make those situations invisible: you press Play once and it stays playing, or it tells you truthfully what is wrong.
Two rules do most of the work. A network path changing is never on its own a reason to tear down a stream that is still producing sound — what decides is whether audio is still arriving, not what the system announced. And when a stream really has failed, recovery always means building a new connection: nothing wedged is ever nudged, resumed or seeked in the hope that it comes back.
You may hear a short gap while that happens. Deep Happy is not gapless and does not claim to be. What it claims is that you should never be left staring at a Playing label with no sound coming out.
Stopping and starting again is quick, too. For about fifteen seconds after you press Stop the app keeps the stream it was playing, so Play picks it straight back up rather than starting cold — instantly, in practice. Leave it stopped for longer and Play connects afresh, taking as long as any cold start does.
The menu-bar popup and the connection status line
Click the icon in the menu bar to open the player. It shows the station you are listening to, the track that is playing, a Play/Stop button, and a status line underneath the title that says what is actually happening — playing, connecting, waiting for the network to come back, reconnecting, or unable to reach the stream. You never have to guess whether it is working.
Until a stream sends a track title, the title line shows the station's own name instead.
Adding and managing your own radio stations
The station's name sits at the top of the player as a filled chip with a chevron. Click it and the player becomes the station list; the chevron at the list's top left brings the player back.
Each row is a station's name with, underneath, what the app has actually measured
about that stream — something like HLS · 25 s cushion, or
No live window · no cushion for a stream it cannot keep a buffer in. A station
you have never played shows no line at all, because nothing is known about it yet. A
checkmark marks the station you are listening to; click another row to switch, and the
player comes back with the new name in the chip. Switching always connects afresh, so you
hear the usual few seconds of connecting rather than the wrong station.
Every row carries its own pencil and trash-can buttons, so Rename and Remove are never something you have to go looking for. Rename opens the same two fields Add does, filled in with the current name; changing it does not interrupt playback. Removing takes two clicks: the first arms the button — it fills solid and turns the accent colour — and the second actually removes the station. Selecting a different row, opening a form, or leaving the page disarms it again, so an armed button never lingers out of sight. The last remaining station's Remove button is dimmed and does nothing, because the player always has to have one to play; removing the station you are listening to switches you to the first in the list. Right-click a row for the same two actions in a menu, if you would rather use that.
Below the stations is Add station…, which opens two fields in place: a
name of your choosing and the stream's address, which has to be a full http://
or https:// URL. If the address is not one the app can use, it says so under
the fields and keeps what you typed. The list is stored per machine, like the other
preferences.
Finding a station in an open directory
Below Add station… is Find a station…, for when you do
not already have a stream's address. It opens a page with a search field: type a station's
name or a genre and press Return, or click Search. Deep Happy asks an open station directory
and lists what it finds — each row shows a trimmed name over a line of what is actually
known about that stream, such as MP3 · 128 kbps · DE. Click a row, or its
+, to add that station to your list; you land back on the station list with it
there.
Typing an address by hand still works exactly as it did. The directory is a second way in, for when you know a name or a genre rather than a URL — not a replacement for the first.
One honest limitation: a station found this way is usually a kind the app does not yet read a live track title from, so its title line keeps showing the station's own name and the lookup buttons stay dim for it — the same as any station before its first play.
Playing from launch, and the silent warm-up
Deep Happy starts playing as soon as it launches; you do not have to click Play just to get sound. Turn Play on launch off in Settings if you would rather it waited for you.
With it off, the hardware play key may open Apple Music instead of Deep Happy until you have pressed Play once in that launch — macOS routes the key to whichever app most recently made sound, and a Deep Happy that has not played yet does not hold that claim.
Also with it off, the app still gets the stream ready in the background as it starts, so your first Play takes about half a second instead of the nine or so a cold connection needs. You cannot see it happening — the player says Stopped and shows the station's name, exactly as it would otherwise. It costs the same bandwidth as playing, so it is held for two minutes and then dropped: press Play within them and it is instant, later and the app connects the normal way.
The optional Dock icon and the player window
Deep Happy has no Dock icon by default — the menu-bar item is the whole app. Switch Show Dock icon on in Settings if you would rather have a window: clicking the icon then opens, or brings forward, a window holding the exact same player. Turning it back off is always safe, since the menu-bar item is there no matter what.
The window is wider than the popup and laid out side by side: the artwork on the left, at full strength with nothing written over it, and the player — station, track, Play/Stop, lookup buttons, recent tracks — in a column on the right. The art is a square only at the window's smallest size; resize it bigger and the art widens into a landscape crop, always filling the space it is given. It is the same player as the popup, so the two can never say different things — the window simply has the room to show the picture properly. It sizes itself to what it has to show, so a long track title makes it taller instead of being cut off. Open Settings from the gear icon in the player, or with the standard ⌘, shortcut.
Copying the artist and title
Click anywhere on the artist-and-title block and both are copied as one string,
Artist - Title — exactly what the stream sent, ready to paste into a search, a
chat or a note. The copy icon briefly turns into a checkmark with Copied
beside it, without hiding the artist or the title. If the stream sends no artist for a track
there is simply no artist line, and the click still copies the title.
Looking a track up, and the recent list
Next to the current track is a small Spotify button — the one lookup service on by default — and clicking it opens a browser search for that track. Turn on Apple Music or Yandex Music in Settings under Look up in and their buttons join it; turn all three off and the row disappears. The buttons are dimmed while the player is showing the station's name rather than a track, since there is nothing to search for.
A Recent list underneath keeps the last three tracks; click one to copy it, or right-click for the same lookup choices.
Hardware media keys and Control Centre
Your keyboard's play/pause and stop keys work with Deep Happy as they do with any other player, and Control Centre shows the current track too — including through a reconnect, so the keys keep controlling Deep Happy instead of switching to some other app.
Volume and mute are the system's, not the app's
The volume slider is the system volume of whichever machine is making the sound — this one while you are listening locally, the machine you are driving while you are not. It is the same dial as your volume keys, Control Centre and every other app on that Mac, so turning the radio down turns everything else down with it, and a slider at zero silences the whole machine. That is a real consequence, not a detail: there is no separate app volume to hide behind.
Move the volume with the keys, the menu bar or another app instead, and the slider follows — on this Mac and on any Mac driving it. Deep Happy never restores a machine's volume on its own; however you leave it is how it stays.
The button at the end of the row is that machine's mute, and it is a separate thing from the slider: muting leaves the volume where it was, so unmuting puts the sound back at exactly the level you left it. Mute the machine any other way — the mute key, the menu bar, another app — and the button lights up and the slider dims, so a panel showing a slider at 13% never leaves you wondering why there is no sound. Press it, or m, to unmute. This matters most while you are driving another Mac, where you cannot see that machine's volume overlay. An output device with no mute control of its own — some do not have one — simply never changes the button; the app records that once in its log and leaves the device alone.
Remote control: driving Deep Happy on another Mac
Deep Happy on one Mac can drive Deep Happy on another — play, stop, and see what is playing — so the machine with the speakers does not have to be the one you are sitting in front of.
Turning it on
Turn it on in Settings → Remote, under This Mac: the Allow remote control switch is off by default, because an app that listens on the network without being asked is not something this project ships. Switched on, the section below shows what this Mac is called and whether it is listening. The first time Deep Happy advertises or discovers a remote-control service, macOS asks for Local Network permission — that prompt is expected, and without it remote control will not find the other Mac.
Pairing
Press Show pairing PIN on the Mac that has the speakers: four digits, a two-minute countdown, and three tries before the window closes and a new PIN is needed. On the Mac you want to drive from, open Settings → Remote → Control another Mac → Pair a new Mac…, pick the first Mac from the list and type the digits. It then appears in the list with a Connect button.
A Mac that plays can have at most three controllers paired at once; a fourth attempt is refused with the reason rather than silently swapping one out. Revoke a controller from the Paired remotes list on the Mac that plays, which drops its connection immediately. When a pairing attempt is refused, the message names which Mac had the problem, rather than implying the other one sent something bad.
Underneath, pairing is a PIN-authenticated key agreement that leaves the two Macs sharing a long-term key; that key is kept in the Keychain, and every session afterwards runs over TLS authenticated with it, so the PIN is typed once and never travels again. The PIN's own protection is exactly its two-minute window and its three-attempt budget — a four-digit code is not a password, and it is not treated as one.
Driving
Press Connect and the panel switches to that Mac's playback: the station, the track, the transport, the volume and the recent list all belong to the machine you are driving, with a row across the top naming it and saying what the session is doing. Playing here and driving another Mac are mutually exclusive — connecting stops whatever was playing here, the same as pressing Stop yourself. Press Disconnect to hand control back; nothing starts playing here on its own.
That row is also where a session comes back from: Driving a named Mac while the link is up, Reconnecting… while it is climbing back — and what is below it is then not presented as current — and not reachable, with a Connect button, once it has stopped trying. The way back is in front of you rather than two windows away, and Settings does the same thing.
You do not usually need it. The app remembers which Mac you were driving and reconnects on its own when you reopen it, when this Mac wakes and when the network comes back — looking the other Mac up afresh, so a changed address or a restarted app there is no obstacle. It tries for about a minute and then rests rather than retrying for ever against a Mac that is switched off; waking this one, or the network returning, starts it again. If the other Mac was playing when the link went, the row says so, but reconnecting never starts playback by itself. Quitting tells the other Mac it is going, rather than leaving it to notice.
When the other Mac cannot be found
The Address field in the pairing form is for when the other Mac cannot be discovered at all, which is what happens under a full-tunnel VPN: it routes every connection off the local network, service discovery included, so the picker stays empty. Type the other Mac's name or address instead — pairing and every session afterwards work the same over it.
Developer mode
Settings has a third tab, Developer, holding one switch. Turn it on and Deep Happy writes a step-by-step trace of pairing and of the remote session to the system log. It is off by default because it is chatty — a line per frame on a session that runs for hours.
Failures in the remote layer are logged whether the switch is on or off, so turning it on is only worth doing before you deliberately reproduce something. The tab also hands you two ready-made Terminal commands, each with a copy button — one watches the log live, one reads the last half hour — and explains how to narrow either to one half of the remote layer or to the player's own lines.
The version line
A small line at the bottom of the player, and in Settings, names the exact build you are running; click it to copy that identity, which is what makes a bug report reproducible.
What it doesn't do
- NOAn account or a sign-up. Nothing to register, nothing to log into, no licence key to type.
- NOAnalytics, telemetry, ads or third-party SDKs. There are no third-party dependencies in the app at all.
- NOA station of its own. Deep Happy is not any broadcaster's app and is not affiliated with one. It plays the stream you point it at.
- NOA network listener you did not ask for. Remote control is off until you switch it on, and pairing needs a PIN typed by a person.
- NOGapless recovery. Coming back from a failure means a new connection, and you may hear a short gap while it happens.
What it requires
- Requires
- macOS 26 or later
- Stations
- Any HTTP or HTTPS stream
- Remote
- Local network, up to 3 controllers
- Sandbox
- Apple's App Sandbox
- Account
- None
Not on the Mac App Store yet. Deep Happy builds and runs today, ahead of a first submission. There is no download link on this site, and anything elsewhere claiming to be Deep Happy is not ours.