Some airplay improvements
This commit is contained in:
parent
0a51a3a7f0
commit
aabb950fdb
4 changed files with 187 additions and 64 deletions
|
@ -23,7 +23,7 @@ export default class RAOP {
|
|||
private portairplay: any = "";
|
||||
|
||||
private airtunes: any;
|
||||
private device: any;
|
||||
// private device: any;
|
||||
private mdns = require("mdns-js");
|
||||
private ok: any = 1;
|
||||
private devices: any = [];
|
||||
|
@ -100,7 +100,7 @@ export default class RAOP {
|
|||
shown_name = (manufacturer.length > 0 ? manufacturer[0].substring(13) : "") + " " + (model.length > 0 ? model[0].substring(6) : "");
|
||||
shown_name = shown_name.trim().length > 1 ? shown_name : (host ?? "Unknown").replace(".local", "");
|
||||
}
|
||||
} catch (e) {}
|
||||
} catch (e) { }
|
||||
let host_name = addresses != null && typeof addresses == "object" && addresses.length > 0 ? addresses[0] : typeof addresses == "string" ? addresses : "";
|
||||
|
||||
if (
|
||||
|
@ -203,43 +203,62 @@ export default class RAOP {
|
|||
// });
|
||||
});
|
||||
|
||||
electron.ipcMain.on("performAirplayPCM", (event, ipv4, ipport, sepassword, title, artist, album, artworkURL, txt, airplay2dv) => {
|
||||
electron.ipcMain.on("performAirplayPCM", (event, ipv4, ipport, sepassword, title, artist, album, artworkURL, txt, airplay2dv, silent) => {
|
||||
if (ipv4 != this.ipairplay || ipport != this.portairplay) {
|
||||
if (this.airtunes == null) {
|
||||
this.airtunes = new this.u();
|
||||
}
|
||||
this.ipairplay = ipv4;
|
||||
this.portairplay = ipport;
|
||||
this.device = this.airtunes.add(ipv4, {
|
||||
port: ipport,
|
||||
volume: airplay2dv ? 30 : 50,
|
||||
password: sepassword,
|
||||
txt: txt,
|
||||
airplay2: airplay2dv,
|
||||
debug: null,
|
||||
forceAlac: false,
|
||||
});
|
||||
// console.log('lol',txt)
|
||||
this.device.on("status", (status: any) => {
|
||||
let identifier = ipv4 + ":" + ipport + "ap";
|
||||
let idx = this.devices.findIndex(((a: any) => { return a.id == identifier }))
|
||||
if (idx != -1) {
|
||||
delete this.devices[idx]
|
||||
this.devices = this.devices.filter((n: any) => n) // remove old controller
|
||||
}
|
||||
this.devices.push(
|
||||
{
|
||||
id: identifier,
|
||||
ip: ipv4,
|
||||
port: ipport,
|
||||
state: 0,
|
||||
controller: this.airtunes.add(ipv4, {
|
||||
port: ipport,
|
||||
volume: airplay2dv ? 30 : 50,
|
||||
password: sepassword,
|
||||
txt: txt,
|
||||
airplay2: airplay2dv,
|
||||
debug: null,
|
||||
forceAlac: false,
|
||||
})
|
||||
}
|
||||
);
|
||||
|
||||
idx = this.devices.findIndex(((a: any) => { return a.id == identifier }))
|
||||
|
||||
// console.log('lol', this.devices)
|
||||
this.devices[idx].controller.on("status", (status: any) => {
|
||||
console.log("device status", status);
|
||||
if (status == "ready") {
|
||||
this._win.webContents.setAudioMuted(true);
|
||||
this._win.webContents.executeJavaScript(`CiderAudio.sendAudio()`).catch((err: any) => console.error(err));
|
||||
}
|
||||
if (status == "need_password") {
|
||||
this._win.webContents.executeJavaScript(`app.setAirPlayCodeUI()`);
|
||||
this._win.webContents.executeJavaScript(`app.setAirPlayCodeUI('${this.devices[idx].id}')`);
|
||||
}
|
||||
if (status == "pair_success") {
|
||||
this._win.webContents.executeJavaScript(`app.sendAirPlaySuccess()`);
|
||||
this._win.webContents.executeJavaScript(`app.sendAirPlaySuccess(${silent},'${this.devices[idx].id}')`);
|
||||
}
|
||||
if (status == "pair_failed") {
|
||||
this._win.webContents.executeJavaScript(`app.sendAirPlayFailed()`);
|
||||
this.disconnectAirplay(this.devices[idx].id)
|
||||
}
|
||||
if (status == "stopped") {
|
||||
// this.airtunes.stopAll(() => {
|
||||
// console.log("end");
|
||||
// });
|
||||
// this._win.webContents.executeJavaScript(`app.airplayDisconnect(true, ${[ipv4, ipport, sepassword, title, artist, album, artworkURL, txt, airplay2dv]})`).catch((err: any) => console.error(err));
|
||||
if (this.devices[idx]?.state != null && this.devices[idx].state != -1)
|
||||
this._win.webContents.executeJavaScript(`app.airplayDisconnect(true, ${JSON.stringify([ipv4, ipport, sepassword, title, artist, album, artworkURL, txt, airplay2dv])})`).catch((err: any) => console.error(err));
|
||||
// this.airtunes = null;
|
||||
// this.device = null;
|
||||
// this.ipairplay = "";
|
||||
|
@ -248,8 +267,8 @@ export default class RAOP {
|
|||
} else {
|
||||
setTimeout(() => {
|
||||
if (this.ok == 1) {
|
||||
console.log(this.device.key, title ?? "", artist ?? "", album ?? "");
|
||||
this.airtunes.setTrackInfo(this.device.key, title ?? "", artist ?? "", album ?? "");
|
||||
console.log(this.devices[idx].controller.key, title ?? "", artist ?? "", album ?? "");
|
||||
this.airtunes.setTrackInfo(this.devices[idx].controller.key, title ?? "", artist ?? "", album ?? "");
|
||||
this.uploadImageAirplay(artworkURL);
|
||||
console.log("done");
|
||||
this.ok == 2;
|
||||
|
@ -260,15 +279,21 @@ export default class RAOP {
|
|||
}
|
||||
});
|
||||
|
||||
electron.ipcMain.on("setAirPlayPasscode", (event, passcode) => {
|
||||
if (this.device) {
|
||||
this.device.setPasscode(passcode);
|
||||
electron.ipcMain.on("setAirPlayPasscode", (event, passcode, identifier) => {
|
||||
if (this.devices.length > 0) {
|
||||
let idx = this.devices.findIndex(((a: any) => { return a.id == identifier }))
|
||||
if (idx != -1) {
|
||||
this.devices[idx].controller.setPasscode(passcode);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
electron.ipcMain.on("setAirPlayVolume", (event, volume) => {
|
||||
if (this.device) {
|
||||
this.device.setVolume(volume);
|
||||
electron.ipcMain.on("setAirPlayVolume", (event, volume, identifier) => {
|
||||
if (this.devices.length > 0) {
|
||||
let idx = this.devices.findIndex(((a: any) => { return a.id == identifier }))
|
||||
if (idx != -1) {
|
||||
this.devices[idx].controller.setVolume(volume);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -321,24 +346,17 @@ export default class RAOP {
|
|||
}
|
||||
});
|
||||
|
||||
electron.ipcMain.on("disconnectAirplay", (event) => {
|
||||
this._win.webContents.setAudioMuted(false);
|
||||
this.airtunes.stopAll(function () {
|
||||
console.log("end");
|
||||
});
|
||||
this._win.webContents.executeJavaScript("app.airplayDisconnect(false)").catch((err: any) => console.error(err));
|
||||
this.airtunes = null;
|
||||
this.device = null;
|
||||
this.ipairplay = "";
|
||||
this.portairplay = "";
|
||||
this.ok = 1;
|
||||
this.i = false;
|
||||
electron.ipcMain.on("disconnectAirplay", (event, identifier = "") => {
|
||||
console.log('iden', identifier)
|
||||
this.disconnectAirplay(identifier)
|
||||
});
|
||||
|
||||
electron.ipcMain.on("updateAirplayInfo", (event, title, artist, album, artworkURL) => {
|
||||
if (this.airtunes && this.device) {
|
||||
console.log(this.device.key, title, artist, album);
|
||||
this.airtunes.setTrackInfo(this.device.key, title, artist, album);
|
||||
if (this.airtunes && this.devices.length > 0) {
|
||||
for (let i in this.devices) {
|
||||
console.log(this.devices[i].controller.key, title, artist, album);
|
||||
this.airtunes.setTrackInfo(this.devices[i].controller.key, title, artist, album);
|
||||
}
|
||||
this.uploadImageAirplay(artworkURL);
|
||||
}
|
||||
});
|
||||
|
@ -347,7 +365,47 @@ export default class RAOP {
|
|||
this.uploadImageAirplay(imageurl);
|
||||
});
|
||||
}
|
||||
private disconnectAirplay(identifier: any = "") {
|
||||
console.log("awdas")
|
||||
this._win.webContents.executeJavaScript(`app.airplayDisconnect(false, [], '${identifier}')`).then(() => {
|
||||
if (identifier == "") {
|
||||
if (this.airtunes) {
|
||||
for (let i in this.devices){
|
||||
this.devices[i].state = -1
|
||||
}
|
||||
this.airtunes.stopAll(() => {
|
||||
console.log("endAll");
|
||||
this.airtunes = null;
|
||||
this.devices = []
|
||||
});
|
||||
} else {
|
||||
this.devices = [];
|
||||
}
|
||||
} else {
|
||||
let idx = this.devices.findIndex(((a: any) => { return a.id == identifier }))
|
||||
if (idx != -1) {
|
||||
this.devices[idx].state = -1
|
||||
this.devices[idx].controller.stop(() =>{
|
||||
console.log(this.devices[idx].id , "stopped")
|
||||
});
|
||||
|
||||
delete this.devices[idx]
|
||||
this.devices = this.devices.filter((n: any) => n)
|
||||
}
|
||||
}
|
||||
if (this.devices.length == 0) {
|
||||
console.log('cleanup airtunes')
|
||||
this._win.webContents.setAudioMuted(false);
|
||||
this.airtunes = null;
|
||||
|
||||
this.ipairplay = "";
|
||||
this.portairplay = "";
|
||||
this.ok = 1;
|
||||
this.i = false;
|
||||
}
|
||||
}).catch((err: any) => console.error("lsdsd", err));
|
||||
|
||||
}
|
||||
private uploadImageAirplay = (url: any) => {
|
||||
try {
|
||||
if (url != null && url != "") {
|
||||
|
@ -355,7 +413,11 @@ export default class RAOP {
|
|||
fetch(url)
|
||||
.then((res) => res.buffer())
|
||||
.then((buffer) => {
|
||||
this.airtunes.setArtwork(this.device.key, buffer, "image/png");
|
||||
if (this.airtunes && this.devices.length > 0) {
|
||||
for (let i in this.devices) {
|
||||
this.airtunes.setArtwork(this.devices[i].controller.key, buffer, "image/png");
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
|
@ -369,7 +431,7 @@ export default class RAOP {
|
|||
/**
|
||||
* Runs on app stop
|
||||
*/
|
||||
onBeforeQuit(): void {}
|
||||
onBeforeQuit(): void { }
|
||||
|
||||
// /**
|
||||
// * Runs on song change
|
||||
|
@ -393,16 +455,20 @@ export default class RAOP {
|
|||
* @param attributes Music Attributes (attributes.status = current state)
|
||||
*/
|
||||
onPlaybackStateDidChange(attributes: any): void {
|
||||
if (this.airtunes && this.device) {
|
||||
if (this.airtunes && this.devices.length > 0) {
|
||||
|
||||
let title = attributes?.name ?? "";
|
||||
let artist = attributes?.artistName ?? "";
|
||||
let album = attributes?.albumName ?? "";
|
||||
let artworkURL = attributes?.artwork?.url ?? null;
|
||||
console.log(this.device.key, title, artist, album);
|
||||
this.airtunes.setTrackInfo(this.device.key, title, artist, album);
|
||||
if (artworkURL != null) {
|
||||
for (let i in this.devices) {
|
||||
console.log(this.devices[i].controller.key, title, artist, album);
|
||||
this.airtunes.setTrackInfo(this.devices[i].controller.key, title, artist, album);
|
||||
}
|
||||
let artworkURL = attributes?.artwork?.url ?? null;
|
||||
|
||||
if (artworkURL != null) {
|
||||
this.uploadImageAirplay(artworkURL.replace("{w}", "1024").replace("{h}", "1024"));
|
||||
}
|
||||
this.uploadImageAirplay(artworkURL.replace("{w}", "1024").replace("{h}", "1024"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -248,6 +248,8 @@ const app = new Vue({
|
|||
idleTimer: null,
|
||||
idleState: false,
|
||||
appVisible: true,
|
||||
currentAirPlayCodeID: "",
|
||||
airplayTrys: []
|
||||
},
|
||||
watch: {
|
||||
cfg: {
|
||||
|
@ -4369,24 +4371,56 @@ const app = new Vue({
|
|||
|
||||
// tracks are found in relationship.data
|
||||
},
|
||||
setAirPlayCodeUI() {
|
||||
setAirPlayCodeUI(identifier) {
|
||||
this.modals.airplayPW = true;
|
||||
this.currentAirPlayCodeID = identifier
|
||||
},
|
||||
sendAirPlaySuccess() {
|
||||
notyf.success("Device paired successfully!");
|
||||
sendAirPlaySuccess(silent = false, identifier = "") {
|
||||
if (!silent){
|
||||
notyf.success("Device paired successfully!");}
|
||||
console.log("delete idx-pre", identifier)
|
||||
let idx = this.airplayTrys.findIndex(((a) => {return a.id == identifier}))
|
||||
console.log("delete idx", idx)
|
||||
if (idx != -1)
|
||||
delete this.airplayTrys[idx]
|
||||
this.airplayTrys = this.airplayTrys.filter(n => n)
|
||||
},
|
||||
sendAirPlayFailed() {
|
||||
notyf.success("Device paring failed!");
|
||||
},
|
||||
airplayDisconnect(dropped, array = []) {
|
||||
console.log("airplay dropped", dropped, array);
|
||||
// if (dropped) {
|
||||
// let [ipv4, ipport, sepassword, title, artist, album, artworkURL, txt, airplay2dv] = array;
|
||||
// ipcRenderer.send("performAirplayPCM", ipv4, ipport, sepassword, title, artist, album, artworkURL, txt, airplay2dv);
|
||||
// } else {
|
||||
// app.activeCasts = [];
|
||||
// notyf.error("Devices disconnected!");
|
||||
// }
|
||||
airplayDisconnect(dropped, array = [], identifier = "") {
|
||||
console.log("airplay dropped", dropped, array, identifier);
|
||||
if (dropped) {
|
||||
let [ipv4, ipport, sepassword, title, artist, album, artworkURL, txt, airplay2dv] = array;
|
||||
console.log(ipv4, ipport, sepassword, title, artist, album, artworkURL, txt, airplay2dv)
|
||||
let idx = this.airplayTrys.findIndex(((a) => {return a.id == ipv4+":"+ipport+"ap"}))
|
||||
if (idx == -1) {
|
||||
this.airplayTrys.push({
|
||||
id : ipv4+":"+ipport+"ap",
|
||||
attempts : 1
|
||||
})
|
||||
}
|
||||
idx = this.airplayTrys.findIndex(((a) => {return a.id == ipv4+":"+ipport+"ap"}))
|
||||
if (this.airplayTrys[idx].attempts > 3){
|
||||
delete this.airplayTrys[idx]
|
||||
this.airplayTrys = this.airplayTrys.filter(n => n)
|
||||
console.log("delete idx", idx)
|
||||
return;
|
||||
} else {
|
||||
this.airplayTrys[idx].attempts = this.airplayTrys[idx].attempts + 1
|
||||
setTimeout(() => {
|
||||
ipcRenderer.send("performAirplayPCM", ipv4, ipport, sepassword, title, artist, album, artworkURL, txt, airplay2dv, true);}, 1000)
|
||||
}
|
||||
|
||||
} else {
|
||||
if (identifier == "") {
|
||||
app.activeCasts = [];
|
||||
notyf.error("Devices disconnected!");
|
||||
} else {
|
||||
app.activeCasts;
|
||||
notyf.error("Device disconnected!");
|
||||
}
|
||||
}
|
||||
},
|
||||
windowFocus(val) {
|
||||
if (val) {
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
},
|
||||
enterPassword() {
|
||||
console.log('Entered passCode: ', this.passcode)
|
||||
ipcRenderer.send("setAirPlayPasscode", this.passcode)
|
||||
ipcRenderer.send("setAirPlayPasscode", this.passcode, this.$root.currentAirPlayCodeID)
|
||||
this.close()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,9 +54,13 @@
|
|||
<small>{{ device.host }}</small>
|
||||
</div>
|
||||
<div class="md-option-segment_auto"
|
||||
style="display: flex;justify-content: center;align-items: center"
|
||||
style="display: flex;justify-content: center;align-items: center" @click="disconnectAirPlayCast(device)"
|
||||
v-if="activeCasts.some(item => { return item.host == device.host && item.name == device.name && item.port == device.port})">
|
||||
Connected
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="20px" height="20px" viewBox="0 0 20 20" version="1.1">
|
||||
<g id="surface1">
|
||||
<path style="stroke:none;fill-rule:evenodd;fill:#fff;fill-opacity:1;" d="M 10 0 C 15.523438 0 20 4.476562 20 10 C 20 15.523438 15.523438 20 10 20 C 4.476562 20 0 15.523438 0 10 C 0 4.476562 4.476562 0 10 0 Z M 12.136719 5.988281 C 12.421875 5.703125 12.597656 5.472656 12.953125 5.828125 L 14.089844 6.988281 C 14.464844 7.355469 14.445312 7.570312 14.089844 7.914062 L 11.933594 10.0625 L 14.011719 12.136719 C 14.296875 12.421875 14.527344 12.597656 14.171875 12.953125 L 13.011719 14.089844 C 12.644531 14.464844 12.429688 14.445312 12.089844 14.089844 L 10 12 L 7.914062 14.082031 C 7.574219 14.433594 7.359375 14.453125 6.992188 14.082031 L 5.828125 12.945312 C 5.472656 12.59375 5.703125 12.417969 5.992188 12.128906 L 8.066406 10.0625 L 5.917969 7.917969 C 5.566406 7.574219 5.546875 7.359375 5.917969 6.992188 L 7.054688 5.828125 C 7.40625 5.472656 7.582031 5.703125 7.871094 5.992188 L 10 8.128906 Z M 12.136719 5.988281 "/>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="md-option-segment_auto" v-else
|
||||
style="display: flex;justify-content: center;align-items: center">
|
||||
|
@ -135,8 +139,27 @@
|
|||
ipcRenderer.send('performGCCast', device, "Cider", "Playing ...", "Test build", '');
|
||||
},
|
||||
setAirPlayCast(device) {
|
||||
if (!this.activeCasts.some(item => { return item.host == device.host && item.name == device.name && item.port == device.port})) {
|
||||
this.activeCasts.push(device);
|
||||
ipcRenderer.send("performAirplayPCM", device.host, device.port, null, "", "", "", "", device.txt, device.airplay2)
|
||||
ipcRenderer.send("performAirplayPCM", device.host, device.port, null, "", "", "", "", device.txt, device.airplay2, false)}
|
||||
},
|
||||
disconnectAirPlayCast(device) {
|
||||
app.confirm("Do you want to disconnect this device?",(res) => {
|
||||
if (res){
|
||||
ipcRenderer.send('disconnectAirplay', device.host +":"+ device.port+"ap");
|
||||
console.log('disconnectAirplay', device.host +":"+ device.port+"ap")
|
||||
let idx = this.activeCasts.findIndex(((a) => {return a.host == device.host && a.port == device.port}))
|
||||
console.log(idx)
|
||||
if (idx != -1) {
|
||||
delete this.activeCasts[idx]
|
||||
delete this.$root.activeCasts[idx]
|
||||
this.activeCasts = this.activeCasts.filter(a => {return !(a.host == device.host && a.port == device.port)})
|
||||
console.log(this.activeCasts)
|
||||
if (this.activeCasts.length == 0){
|
||||
this.stopCasting()
|
||||
}
|
||||
}}
|
||||
})
|
||||
},
|
||||
stopCasting() {
|
||||
CiderAudio.stopAudio();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue