Skip to content

Commit

Permalink
Using Spotify on different device no longer changes output to Safari,…
Browse files Browse the repository at this point in the history
… general fixes
  • Loading branch information
DervexDev committed Sep 24, 2023
1 parent 86f1780 commit 4f0929e
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 30 deletions.

This file was deleted.

Binary file modified App/ssa-core
Binary file not shown.
28 changes: 22 additions & 6 deletions CLI/Source/SpotifySpatialAudio/App/AppleScript.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@
import Foundation

struct AppleScript {
static func initSafari() {
static func openSafari() {
let script = """
tell application "Safari"
make new document with properties {URL:"https://open.spotify.com/"}
delay \(SAFARI_HIDE_DELAY)
set miniaturized of window 1 to true
open location "https://open.spotify.com/"
activate
end tell
"""

Expand All @@ -22,16 +21,33 @@ struct AppleScript {
}
}

static func clearSafari() {
static func hideSafari() {
let script = """
tell application "Safari"
close (every window whose name contains "Spotify")
set miniaturized of window 1 to true
end tell
"""

var error: NSDictionary?
if let scriptObject = NSAppleScript(source: script) {
scriptObject.executeAndReturnError(&error)
}
}

static func fakeSpace() {
let script = """
tell application "System Events"
key code 49
end tell
"""

var error: NSDictionary?
if let scriptObject = NSAppleScript(source: script) {
scriptObject.executeAndReturnError(&error)
}

if error != nil {
print("ERROR: missing privileges!")
}
}
}
26 changes: 26 additions & 0 deletions CLI/Source/SpotifySpatialAudio/App/Bluetooth.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//
// Bluetooth.swift
//
// Created by Dervex with <3 on 12/09/2023.
//

import Foundation
import IOBluetooth

struct Bluetooth {
static func isUsingSupportedDevice() -> Bool {
guard let devices = IOBluetoothDevice.pairedDevices() else {
return false
}

for item in devices {
if let device = item as? IOBluetoothDevice {
if device.isConnected() && SUPPORTED_DEVICES.contains(device.name) {
return true
}
}
}

return false
}
}
7 changes: 6 additions & 1 deletion CLI/Source/SpotifySpatialAudio/App/Events.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,19 @@ struct Events {
NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "kMRMediaRemoteNowPlayingInfoDidChangeNotification"), object: nil, queue: nil) { _ in
nowPlayingInfo(DispatchQueue.main, { information in
let isPlaying = type(of: information["kMRMediaRemoteNowPlayingInfoPlaybackRate"] ?? 0) != Int.self
let album = information["kMRMediaRemoteNowPlayingInfoAlbum"] ?? ""

if isPlaying != lastValue && isPlaying {
if isPlaying && isPlaying != lastValue {
let now = NSDate().timeIntervalSince1970.rounded()

if now - lastUsed == 1 {
return
}

if album as! String == "" {
return
}

lastUsed = now
callback()
}
Expand Down
25 changes: 20 additions & 5 deletions CLI/Source/SpotifySpatialAudio/App/Main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,32 @@ struct App {
}

var id = Requests.getSafariId(accessToken: data.accessToken)
var attempts = 0

if id == "null" {
AppleScript.clearSafari()
AppleScript.initSafari()
} else if id == "active" {
if id == "none" {
AppleScript.openSafari()
} else if id == "active" || id == "inactive" {
return
}

id = Requests.getSafariId(accessToken: data.accessToken)
while id == "none" && attempts < OPEN_SAFARI_MAX_ATTEMPTS {
sleep(1)
id = Requests.getSafariId(accessToken: data.accessToken)
attempts += 1
}

if id == "none" {
print("ERROR: Safari cannot be opened!")
return
}

Requests.changeOutput(accessToken: data.accessToken, id: id)

sleep(1)
AppleScript.fakeSpace()
//Requests.resumePlayback(accessToken: data.accessToken)
sleep(1)
AppleScript.hideSafari()
}
}

Expand Down
37 changes: 30 additions & 7 deletions CLI/Source/SpotifySpatialAudio/App/Requests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ struct Requests {
]

let id = UnsafeMutablePointer<String>.allocate(capacity: 1)
id.pointee = "null"
id.pointee = "none"

let group = DispatchGroup()
group.enter()
Expand All @@ -28,17 +28,29 @@ struct Requests {

do {
let decoded = try JSONSerialization.jsonObject(with: data) as! [String: Array<[String: Any]>]
var isActive = false

for device in decoded["devices"]! {
if device["name"] as! String == "Web Player (Safari)" {
if device["is_active"] as! Bool {
id.pointee = "active"
} else {
id.pointee = device["id"] as! String
}
if device["name"] as! String == Host.current().localizedName! && device["is_active"] as! Bool {
isActive = true
break
}
}

if isActive {
for device in decoded["devices"]! {
if device["name"] as! String == "Web Player (Safari)" {
if device["is_active"] as! Bool {
id.pointee = "active"
} else {
id.pointee = device["id"] as! String
}
break
}
}
} else {
id.pointee = "inactive"
}
} catch {
group.leave()
return
Expand Down Expand Up @@ -111,4 +123,15 @@ struct Requests {

URLSession.shared.dataTask(with: request).resume()
}

static func resumePlayback(accessToken: String) {
var request = URLRequest(url: URL(string: "https://api.spotify.com/v1/me/player/play")!)
request.httpMethod = "PUT"
request.allHTTPHeaderFields = [
"Authorization": "Bearer " + accessToken,
"Content-Type": "application/json"
]

URLSession.shared.dataTask(with: request).resume()
}
}
11 changes: 10 additions & 1 deletion CLI/Source/SpotifySpatialAudio/Config.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
let SERVER_HOST: String = "localhost"
let SERVER_PORT: Int = 8888

let SAFARI_HIDE_DELAY = 3
let DATA_FILE_NAME: String = ".ssa.json"
let OPEN_SAFARI_MAX_ATTEMPTS = 10

let CLIENT_ID: String = "" // Add your client id here
let CLIENT_SECRET: String = "" // Add you client secret here
Expand All @@ -19,3 +20,11 @@ let SCOPES: Array<String> = [
"user-read-playback-state",
"user-modify-playback-state"
]

let SUPPORTED_DEVICES = [
"AirPods Pro",
"AirPods Max",
"AirPods",
"Beats Fit Pro",
"Beats Studio Pro"
]
6 changes: 2 additions & 4 deletions CLI/Source/SpotifySpatialAudio/FileSystem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,13 @@

import Foundation

let FILE_NAME: String = ".ssa.json"

struct FileSystem {
static func loadJSON() throws -> Any? {
let fileManager = FileManager.default
let urls = fileManager.urls(for: .documentDirectory, in: .userDomainMask)

if let url = urls.first {
let file = url.appendingPathComponent(FILE_NAME)
let file = url.appendingPathComponent(DATA_FILE_NAME)

if !fileManager.fileExists(atPath: file.path()) {
return nil
Expand All @@ -35,7 +33,7 @@ struct FileSystem {
let urls = fileManager.urls(for: .documentDirectory, in: .userDomainMask)

if let url = urls.first {
let file = url.appendingPathComponent(FILE_NAME)
let file = url.appendingPathComponent(DATA_FILE_NAME)
let data = try JSONSerialization.data(withJSONObject: json, options: [.prettyPrinted])
try data.write(to: file, options: [.atomicWrite])

Expand Down

0 comments on commit 4f0929e

Please sign in to comment.