Skip to content

Commit

Permalink
reorganise settings view, add ikurabot scrobbling (nobody will use this)
Browse files Browse the repository at this point in the history
  • Loading branch information
zhiayang committed Feb 12, 2022
1 parent ec44c4e commit e83580a
Show file tree
Hide file tree
Showing 8 changed files with 483 additions and 198 deletions.
16 changes: 14 additions & 2 deletions MoeStreamer.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
2BA283FC23F14607008E0DEB /* ViewWrappers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BA283FB23F14607008E0DEB /* ViewWrappers.swift */; };
2BA9071923F0731300782C94 /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BA9071823F0731300782C94 /* Settings.swift */; };
2BA9071B23F07DF200782C94 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BA9071A23F07DF200782C94 /* SettingsView.swift */; };
2BCC565427B8355E00FA797A /* Scrobbler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BCC565327B8355E00FA797A /* Scrobbler.swift */; };
2BCEB21925EE16A400F731DD /* AudioDevices.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BCEB21825EE16A400F731DD /* AudioDevices.swift */; };
2BCEB21B25EE16BD00F731DD /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2BCEB21A25EE16BD00F731DD /* CoreAudio.framework */; };
2BCEB21E25EE24E700F731DD /* CoreAudioWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BCEB21D25EE24E700F731DD /* CoreAudioWrapper.swift */; };
Expand Down Expand Up @@ -108,6 +109,7 @@
2BA283FB23F14607008E0DEB /* ViewWrappers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewWrappers.swift; sourceTree = "<group>"; };
2BA9071823F0731300782C94 /* Settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Settings.swift; sourceTree = "<group>"; };
2BA9071A23F07DF200782C94 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
2BCC565327B8355E00FA797A /* Scrobbler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Scrobbler.swift; sourceTree = "<group>"; };
2BCEB21825EE16A400F731DD /* AudioDevices.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioDevices.swift; sourceTree = "<group>"; };
2BCEB21A25EE16BD00F731DD /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; };
2BCEB21D25EE24E700F731DD /* CoreAudioWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreAudioWrapper.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -250,6 +252,7 @@
2B79C81623F1FD72001C87CD /* src */ = {
isa = PBXGroup;
children = (
2BCC565227B8355200FA797A /* ikurabot */,
2B4077E4256D70CC0054F4DC /* discord */,
2B79C81423F1FD19001C87CD /* ui */,
2BE995EE23FBA0A50092023C /* audio */,
Expand All @@ -265,6 +268,14 @@
path = src;
sourceTree = "<group>";
};
2BCC565227B8355200FA797A /* ikurabot */ = {
isa = PBXGroup;
children = (
2BCC565327B8355E00FA797A /* Scrobbler.swift */,
);
path = ikurabot;
sourceTree = "<group>";
};
2BCEB21C25EE24CE00F731DD /* coreaudio */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -465,6 +476,7 @@
2BD486C423EFE3030066F1C4 /* MainView.swift in Sources */,
2BCFF60223F1DF9700A58EFE /* Logger.swift in Sources */,
2B4077E6256D74810054F4DC /* Client.swift in Sources */,
2BCC565427B8355E00FA797A /* Scrobbler.swift in Sources */,
2B2D2C7D256E9F1700ED6DB5 /* RateLimiter.swift in Sources */,
2BA9071B23F07DF200782C94 /* SettingsView.swift in Sources */,
2B743D9D25EE737D00CC7D1D /* AudioEngine.swift in Sources */,
Expand Down Expand Up @@ -653,7 +665,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 0.17.4;
MARKETING_VERSION = 0.17.5;
PRODUCT_BUNDLE_IDENTIFIER = com.zhiayang.MoeStreamer;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "";
Expand Down Expand Up @@ -688,7 +700,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 0.17.4;
MARKETING_VERSION = 0.17.5;
PRODUCT_BUNDLE_IDENTIFIER = com.zhiayang.MoeStreamer;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "";
Expand Down
2 changes: 1 addition & 1 deletion MoeStreamer/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,6 @@
<key>NSSupportsAutomaticTermination</key>
<true/>
<key>NSSupportsSuddenTermination</key>
<true/>
<false/>
</dict>
</plist>
1 change: 1 addition & 0 deletions MoeStreamer/src/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,6 @@ class AppDelegate : NSObject, NSApplicationDelegate
func applicationWillTerminate(_ aNotification: Notification)
{
globalMediaKeyHandler.enable(false, musicCon: self.controller.getModel().controller())
self.controller.shutdown()
}
}
21 changes: 17 additions & 4 deletions MoeStreamer/src/Settings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ enum SettingKey : Hashable
{
case shouldAutoRefresh(key: String = "refreshMetadataOnOpen", default: Bool = true)
case shouldNotifySongChange(key: String = "notifyOnSongChange", default: Bool = false)
case shouldUseKeyboardShortcuts(key: String = "useKeyboardShortcuts", default: Bool = false)
case shouldUseMediaKeys(key: String = "useMediaKeys", default: Bool = false)
case shouldResumeOnWake(key: String = "resumeOnWake", default: Bool = false)
case shouldUpdateNowPlaying(key: String = "updateNowPlaying", default: Bool = false)
Expand All @@ -33,18 +32,23 @@ enum SettingKey : Hashable
case streamBufferMs(key: String = "streamBufferMilliseconds", default: Int = 2000)
case logLinesRetain(key: String = "logLinesRetain", default: Int = 200)

case musicBackend(key: String = "musicBackend", default: MusicBackend = .ListenMoe())
case musicBackend(key: String = "musicBackend", default: MusicBackend = .LocalMusic())
case settingsSection(key: String = "settingsSection", default: SettingsSection = .LocalMusic)

case discordAppId(key: String = "discordAppId", default: String = "")
case discordUserToken(key: String = "discordUserToken", default: String = "")
case discordAutoFetchToken(key: String = "discordAutoFetchToken", default: Bool = true)

case ikuraEnabled(key: String = "ikuraEnabled", default: Bool = false)
case ikuraConsoleIp(key: String = "ikuraConsoleIp", default: String = "")
case ikuraConsolePort(key: String = "ikuraConsolePort", default: Int = 6969)
case ikuraConsolePassword(key: String = "ikuraConsolePassword", default: String = "")

var key: String {
switch self
{
case .shouldAutoRefresh(let key, _): return key
case .shouldNotifySongChange(let key, _): return key
case .shouldUseKeyboardShortcuts(let key, _): return key
case .shouldUseMediaKeys(let key, _): return key
case .shouldResumeOnWake(let key, _): return key
case .shouldUpdateNowPlaying(let key, _): return key
Expand All @@ -62,9 +66,14 @@ enum SettingKey : Hashable
case .streamBufferMs(let key, _): return key
case .logLinesRetain(let key, _): return key
case .musicBackend(let key, _): return key
case .settingsSection(let key, _): return key
case .discordUserToken(let key, _): return key
case .discordAppId(let key, _): return key
case .discordAutoFetchToken(let key, _): return key
case .ikuraEnabled(let key, _): return key
case .ikuraConsoleIp(let key, _): return key
case .ikuraConsolePort(let key, _): return key
case .ikuraConsolePassword(let key, _): return key
}
}

Expand All @@ -73,7 +82,6 @@ enum SettingKey : Hashable
{
case .shouldAutoRefresh(_, let def): return def
case .shouldNotifySongChange(_, let def): return def
case .shouldUseKeyboardShortcuts(_, let def): return def
case .shouldUseMediaKeys(_, let def): return def
case .shouldResumeOnWake(_, let def): return def
case .shouldUpdateNowPlaying(_, let def): return def
Expand All @@ -91,9 +99,14 @@ enum SettingKey : Hashable
case .streamBufferMs(_, let def): return def
case .logLinesRetain(_, let def): return def
case .musicBackend(_, let def): return def
case .settingsSection(_, let def): return def
case .discordUserToken(_, let def): return def
case .discordAppId(_, let def): return def
case .discordAutoFetchToken(_, let def): return def
case .ikuraEnabled(_, let def): return def
case .ikuraConsoleIp(_, let def): return def
case .ikuraConsolePort(_, let def): return def
case .ikuraConsolePassword(_, let def): return def
}
}

Expand Down
1 change: 1 addition & 0 deletions MoeStreamer/src/audio/StreamAudioController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ class StreamAudioController : NSObject, AudioController, VLCMediaPlayerDelegate

func setPlaybackMirrorDevice(to: AudioDevice)
{
// TODO: listen.moe mirroring!
}

func getPlaybackMirrorDevice() -> AudioDevice
Expand Down
100 changes: 100 additions & 0 deletions MoeStreamer/src/ikurabot/Scrobbler.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
//
// Scrobbler.swift
// MoeStreamer
//
// Created by zhiayang on 13/2/22.
// Copyright © 2022 zhiayang. All rights reserved.
//

import Socket
import SwiftyJSON
import Foundation

class IkuraRPC
{
private var socket: Socket? = nil

init?(model: MainModel)
{
model.subscribe(with: { song, state in
if let song = song {
self.updateSong(song)
}
})
}

deinit
{
self.disconnect()
}

private func updateSong(_ song: Song)
{
let json = JSON([
"title": song.title,
"artist": song.artists.joined(separator: ", ")
])

do
{
// note: no options = not pretty printed!
guard let ser = json.rawString(options: []) else {
return
}

try self.socket?.write(from: "/scrobble_song \(ser)\n")
}
catch
{
Logger.log("ikura", msg: "write failed: \(error)")
}
}

func connect() -> Bool
{
self.socket = try? Socket.create()
guard self.socket != nil else {
return false
}

let ip: String = Settings.get(.ikuraConsoleIp())
let port: Int = Settings.get(.ikuraConsolePort())
let password: String = Settings.getKeychain(.ikuraConsolePassword())

do
{
try self.socket?.connect(to: ip, port: Int32(port))
}
catch
{
Logger.log("ikura", msg: "failed to connect: \(error)")
return false
}

guard let foo = try? self.socket?.readString(), foo.starts(with: "csrf: ") else {
Logger.log("ikura", msg: "could not read CSRF")
return false
}

let csrf = foo.components(separatedBy: .newlines)[0].dropFirst("csrf: ".count)
print("csrf = \(csrf)")

do
{
try self.socket?.write(from: csrf + "\n")
try self.socket?.write(from: password + "\n")
}
catch
{
Logger.log("ikura", msg: "write failed: \(error)")
return false
}

return true
}

func disconnect()
{
_ = try? self.socket?.write(from: "/q\n")
}
}
Loading

0 comments on commit e83580a

Please sign in to comment.