diff --git a/package.json b/package.json
index 70e22263..6cad8ece 100644
--- a/package.json
+++ b/package.json
@@ -39,7 +39,7 @@
"@sentry/electron": "^3.0.7",
"@sentry/integrations": "^6.19.6",
"adm-zip": "0.4.10",
- "airtunes2": "git+https://github.com/vapormusic/node_airtunes2.git",
+ "airtunes2": "git+https://github.com/vapormusic/node_airtunes2.git#hap",
"castv2-client": "^1.2.0",
"chokidar": "^3.5.3",
"discord-rpc": "^4.0.1",
diff --git a/src/main/base/browserwindow.ts b/src/main/base/browserwindow.ts
index afb38607..2089686c 100644
--- a/src/main/base/browserwindow.ts
+++ b/src/main/base/browserwindow.ts
@@ -95,6 +95,7 @@ export class BrowserWindow {
"components/fullscreen",
"components/miniplayer",
"components/castmenu",
+ "components/airplay-modal",
"components/artist-chip",
"components/hello-world",
"components/inline-collection-list",
@@ -897,6 +898,10 @@ export class BrowserWindow {
event.returnValue = process.platform;
});
+ ipcMain.on("get-port", (event) => {
+ event.returnValue = this.clientPort;
+ });
+
ipcMain.on("is-dev", (event) => {
event.returnValue = this.devMode;
});
diff --git a/src/main/plugins/chromecast.ts b/src/main/plugins/chromecast.ts
index 5702fefc..0cac3506 100644
--- a/src/main/plugins/chromecast.ts
+++ b/src/main/plugins/chromecast.ts
@@ -28,7 +28,7 @@ export default class ChromecastPlugin {
// private GCstream = new Stream.PassThrough(),
private connectedHosts: any = {};
private connectedPlayer: any;
- // private port = false;
+ private ciderPort :any = 9000;
// private server = false;
// private bufcount = 0;
// private bufcount2 = 0;
@@ -148,7 +148,7 @@ export default class ChromecastPlugin {
}
let media = {
// Here you can plug an URL to any mp4, webm, mp3 or jpg file with the proper contentType.
- contentId: 'http://' + this.getIp() + ':9000/audio.wav',
+ contentId: 'http://' + this.getIp() + ':'+ this.ciderPort +'/audio.wav',
contentType: 'audio/wav',
streamType: 'LIVE', // or LIVE
@@ -361,4 +361,12 @@ export default class ChromecastPlugin {
}
+ onRendererReady(): void {
+ this._win.webContents.executeJavaScript(
+ `ipcRenderer.sendSync('get-port')`
+ ).then((result: any) => {
+ this.ciderPort = result;
+ });
+ }
+
}
\ No newline at end of file
diff --git a/src/main/plugins/raop.ts b/src/main/plugins/raop.ts
index e6908375..77f9f8d1 100644
--- a/src/main/plugins/raop.ts
+++ b/src/main/plugins/raop.ts
@@ -147,14 +147,28 @@ export default class RAOP {
browser.on('ready', browser.discover);
browser.on('update', (service: any) => {
- if (service.addresses && service.fullname && (service.fullname.includes('_raop._tcp') || service.fullname.includes('_airplay._tcp'))) {
+ if (service.addresses && service.fullname && (service.fullname.includes('_raop._tcp') || service.fullname.includes('_airplay._tcp'))) {
// console.log(service.txt)
this._win.webContents.executeJavaScript(`console.log(
"${service.name} ${service.host}:${service.port} ${service.addresses}"
)`);
- this.ondeviceup(service.name, service.host, service.port, service.addresses, service.txt);}
+ this.ondeviceup(service.name, service.host, service.port, service.addresses, service.txt);
+ }
});
+
+ // const browser2 = this.mdns.createBrowser(this.mdns.tcp('airplay'));
+ // browser2.on('ready', browser2.discover);
+ // browser2.on('update', (service: any) => {
+ // if (service.addresses && service.fullname && (service.fullname.includes('_raop._tcp') || service.fullname.includes('_airplay._tcp'))) {
+ // // console.log(service.txt)
+ // this._win.webContents.executeJavaScript(`console.log(
+ // "${service.name} ${service.host}:${service.port} ${service.addresses}"
+ // )`);
+ // this.ondeviceup(service.name, service.host, service.port, service.addresses, service.txt);
+ // }
+ // });
+
});
@@ -178,6 +192,12 @@ export default class RAOP {
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()`)
+ }
+ if (status == "pair_success"){
+ this._win.webContents.executeJavaScript(`app.sendAirPlaySuccess()`)
+ }
if (status == 'stopped') {
this.airtunes.stopAll(() => {
console.log('end');
@@ -210,6 +230,12 @@ export default class RAOP {
});
+ electron.ipcMain.on('setAirPlayPasscode', (event, passcode) => {
+ if (this.device){
+ this.device.setPasscode(passcode)
+ }
+ })
+
electron.ipcMain.on('writeWAV', (event, leftbuffer, rightbuffer) => {
if (this.airtunes != null) {
if (this.worker == null) {
diff --git a/src/renderer/less/helpers.less b/src/renderer/less/helpers.less
index db659232..245cce92 100644
--- a/src/renderer/less/helpers.less
+++ b/src/renderer/less/helpers.less
@@ -70,10 +70,11 @@
.spatialproperties-panel {
.modal-window {
+ &:not(.airplay-modal){
height : 700px;
max-height: 700px;
width : 800px;
- max-width : 800px;
+ max-width : 800px;}
overflow : hidden;
.info-header {
diff --git a/src/renderer/main/vueapp.js b/src/renderer/main/vueapp.js
index a00c345d..1811fa3d 100644
--- a/src/renderer/main/vueapp.js
+++ b/src/renderer/main/vueapp.js
@@ -207,6 +207,7 @@ const app = new Vue({
showPlaylist: false,
castMenu: false,
moreInfo: false,
+ airplayPW: false,
},
socialBadges: {
badgeMap: {},
@@ -3830,6 +3831,12 @@ const app = new Vue({
// tracks are found in relationship.data
},
+ setAirPlayCodeUI() {
+ this.modals.airplayPW = true
+ },
+ sendAirPlaySuccess(){
+ notyf.success('Device paired successfully!');
+ },
windowFocus(val) {
if (val) {
document.querySelectorAll(".animated-artwork-video").forEach(el => {
diff --git a/src/renderer/views/app/panels.ejs b/src/renderer/views/app/panels.ejs
index 69a6f18e..eaccb5f2 100644
--- a/src/renderer/views/app/panels.ejs
+++ b/src/renderer/views/app/panels.ejs
@@ -28,6 +28,9 @@
+
+
+
diff --git a/src/renderer/views/components/airplay-modal.ejs b/src/renderer/views/components/airplay-modal.ejs
new file mode 100644
index 00000000..16ab91a4
--- /dev/null
+++ b/src/renderer/views/components/airplay-modal.ejs
@@ -0,0 +1,42 @@
+
+
\ No newline at end of file