Posts tagged with “mac”

Fixing macOS' defective sleep mode with a Hammer (...Spoon)

This is kind of a followup post to Using a Mac Mini as a bedroom PC for Kodi, Moonlight and YouTube.

It's been nearly a year since I set up a Mac Mini as my one-stop-shop for all multimedia related tasks in the bedroom. It's generally worked well, and both streaming media, games, general web browsing and PC usage has been smooth. You're rolling around in bed, playing video games, watching YouTube, or maybe the freshest episode of Smiling Friends. But then you fall asleep, and the fun abruptly stops.

"I'm gonna wreck it!" - Apple, probably

Sometimes, the computer will still be on and fully active in the morning after falling asleep using it, soaking up all those precious jiggawatts, directly out of your wallet.

Why, I hear you ask? Maybe there is a mouse connected that causes jiggle when you shuffle around in your sleep?

No, only a USB remote and a keyboard + touchpad combo device (the Logitech K400 Plus, which is absolute fucking garbage[1]) are connected.

How can this be, when the system is set to sleep after 1 hour of inactivity? Surely, Thou Be Trippin'?

Well, as many things Apple, it is a defect by design: Apple lets software overrule this user setting, without notifying the user, and without letting the user change this behaviour. This means that since EmulationStation - the launcher I'm using - is running in the background, and is considered a game, it inhibits system sleep. I've looked all over, and there is no way in current-day macOS to let me, the user, owner, administrator and fucking Dom Top of this machine, ignore what the system thinks, and just Go The Fuck To Sleep after 1 hour, no matter what. That's a huge defect, but dealing with huge defects is the bread and butter of a technical person trying to make an Apple product cooperate.

"I'm gonna fix it!" - Me

I'm not gonna spin a yarn and complain any more about Apple today, even if I could fill pages with that kind of content. I'm a Solutions™ kinda guy, not an Apple Sux™ kinda guy.

Here's how to fix it: Using HammerSpoon, an application for automating macOS, along with a simple Lua script. I have never used HammerSpoon before this, but I've written a ton of Lua (for video games), so getting started was easy enough.

Install HammerSpoon, start it, give it the appropriate permissions, set it to run at boot, and edit your ~/.hammerspoon/init.lua to contain the following:

local function handlePowerEvent(event)
    if event == powerWatcher.systemDidWake or event == powerWatcher.screensDidWake then
      print("System woke up, restarting idle monitoring")
      idleTimer:start()
    elseif event == powerWatcher.systemWillSleep or event == powerWatcher.screensDidSleep then
      print("System going to sleep, suspending monitoring.")
      idleTimer:stop()
    end
end

local function checkSleep()
    local idleTime = hs.host.idleTime()
    if idleTime < sleepThreshold then
        print("Idle for " .. idleTime .. " secs")
    else
        print("Idle time exceeded threshold, going to sleep")
        hs.caffeinate.systemSleep()
    end
end

sleepThreshold = 3600 --seconds
powerWatcher = hs.caffeinate.watcher
powerWatcher.new(handlePowerEvent):start()
idleTimer = hs.timer.new(60, checkSleep)
idleTimer:start()

Save the file, click the HammerSpoon icon on your menu bar, then "Reload Config", and boom, you're in business.

The script is extremely simple. It sets a timer that monitors how long the system has been idle for, which runs every 60 seconds. If the timer sees that the idle time is over the set threshold (set to 3600 seconds here - 1 hour), it tells the computer to go to sleep immediately — come hell or high water. The script additionally monitors the sleep and wake up events, in order to stop and start the timer, so it doesn't run while the computer is asleep (yeah, that can happen). It also prints some log messages to the HammerSpoon console, which you can see by clicking the HammerSpoon icon and clicking "Console".

And that's all there is to it. Apple has a long way to go when it comes to user friendliness, and definitely needs to provide an option for "going to sleep no matter what the system or any piece of software has to say about the present state of things". I'm not going to be in charge of wording the toggle, though.


[1] The Logitech K400 Plus, also known as The Frustrationator 400, is e-waste that they charge money for. The touch pad comes with an infuriating acceleration that can't be turned off, which makes navigating the user interface of the computer an exercise that all but ensures that you go to bed angry. They told me I shouldn't do that, but here we are. It also looks dumb, feels cheap, and makes me nostalgic for the simpler times when I didn't own the Logitech K400 Plus.


Using a Mac Mini as a bedroom PC for Kodi, Moonlight and YouTube

Issues in the bedroom

I have a wall-mounted TV in my bedroom. This TV has a PS4 and a PC hooked up to it. I use the PS4 to remote play my PS5 (which is situated in the living room), and in the past, have used the PC for Kodi/Jellyfin and YouTube in bed, using a USB remote control with support for moving the mouse cursor. Unfortunately, it doesn't do that very well, as the Wi-Fi adapter I have for it keeps presenting issues under Linux. No matter how much I re-compile and reenable the drivers, it just won't work properly, and will randomly cut out after a while. This also happens with several different adapters, so I've kinda just left it there, and used the PS4 to access the web UI of Jellyfin. This is not ideal, and I don't want to spend any more hours fighting with it.

Free fruit

I don't usually use Apple products, but I had a Mac Mini lying around as surplus after having replaced all Macs at my place of work with Windows computers. It's a shame to let it just lie around, collecting dust, so why not use it for something useful, and also solve my bedroom problems (heh) in one fell swoop?

My criteria were as follows:

Absolutely crucial

  • Support for my USB remote (it identifies itself as a keyboard and mouse so almost anything would fill this criteria)
  • Support for a wireless game controller (DS4)
  • Be able to run Kodi and Jellyfin for Kodi
  • Be able to run Moonlight, for remote playing PC games
  • Be able to watch YouTube with uBlock Origin and SponsorBlock
  • Be able to control the whole machine using just my remote and my gamepad

Nice to have

  • Be able to emulate some games natively, and use the gamepad to do so

Collection and assimilation

After stumbling upon Retro Game Corps' video on Retro Gaming on a Mac Mini, I figured that the Mac Mini I had lying around would be perfect for this, as long as the usual "Whoops! Can't do that on a Mac!" problems didn't stand in the way. I would use EmulationStation Desktop Edition (ES-DE) as the shell to launch Kodi, Moonlight and YouTube from.

I already had the Mac and the USB remote, but not an extra controller. As luck would have it, my step-brother's girlfriend had one she didn't need, so I inherited her bright blue DualShock 4, which is perfect. The other DS4 in the bedroom is black, and will continue to be hooked up to the PS4, while the blue one will be used with the Mac. Unlike in my experience on Windows, pairing and using the DS4 Just Werks™, and was ready to use right away after pairing.

Software setup

After installing the apps I wanted (Dolphin, RPCS3, RetroArch, Kodi, Moonlight), and ES-DE, I was ready to get going. I also installed NoMachine for remote access, in case I want to do maintenance on this machine without having to lie in bed to do so. It took a bit of web searching to find documentation for how to launch arbitrary apps from EmulationStation, but it wasn't really difficult.

By default, when you start ES-DE for the first time, it will ask you to create game folders for different systems, then exit so you can populate those folders with actual games. Do this, then additionally, create a folder called "Apps" in the folder you chose (typically ~/ROMs).

You can now make a custom system in ES-DE, by creating the following file:

~/.emulationstation/custom_systems/es_systems.xml:

<systemList>
    <system>
        <fullname>Apps</fullname>
        <name>Apps</name>
        <path>~/ROMs/Apps</path>
        <extension>.sh .SH .py .PY</extension>
        <command>open -a "%ROM%"</command>
        <platform>apps</platform>
        <theme>esconfig</theme>
    </system>
</systemList>

As you can see, this is pretty straight-forward. This will make a custom system named "Apps" in ES-DE, which gets its games from ~/ROMs/Apps, and will look for files with .sh or .py file extensions. Save the file, and you can now make the simple scripts that go into this folder.

For each app you want to launch from within ES-DE, create a .sh file in ~/ROMs/Apps and make them executable (chmod u+x script.sh. Here are mine:

Kodi.sh:

#!/usr/bin/env sh
open -a "Kodi"

Moonlight.sh:

#!/usr/bin/env sh
open -a "Moonlight"

YouTube.sh:

#!/usr/bin/env sh
open "https://www.youtube.com/feed/subscriptions?"

As you can see, these are simple as. The YouTube script opens your default browser to your subscriptions page on YouTube, but you can just as easily configure it to launch in a specified one, by using open -a "Firefox" "https://www.youtube.com/" if you want.

Save all files, restart ES-DE, and you should have a new category named Apps, containing your scripts. Launching the menu item will launch and give input focus to the app in question. Then use your gamepad/USB remote/whatever to navigate the given app. ES-DE and Moonlight works with gamepad navigation, but I've found that Kodi on macOS is hit or miss when it comes to this. It's worked a few times, but then stopped working, so I just use my remote for that.

Closing thoughts

A USB remote is usually a simple and cheap device, and can be found on eBay or AliExpress simply by searching for "usb pc remote control". Here is the one I use, which works great and costs next to nothing. This one has a button to switch between mouse mode and remote mode, which is important as you can't always navigate around macOS using the remote functionality alone.

There's lots of fun to be had in bed.... ;) Making Apple products an integral part of my bedroom experience isn't something I thought I would do, but it works surprisingly well. Now I have an all-in-one solution for gaming, movies, TV shows and YouTube content, all in one box, complete with uBlock to block YouTube ads, and SponsorBlock to skip sponsor segments!

For an extra smooth experience, you can configure macOS to open ES-DE when you log in by right clicking its dock icon and choosing Options > Open at login, and also making sure to uncheck "Restore windows [...]" whenever you log out/shut down the computer. I've also set both Kodi and the Mac to go to sleep after an hour of inactivity, so if I fall asleep, it won't run and use power needlessly throughout the night.