diff --git a/doc/detailed.md b/doc/detailed.md index c03df9a4..f24d25bf 100644 --- a/doc/detailed.md +++ b/doc/detailed.md @@ -231,7 +231,7 @@ $ sudo systemctl restart mopidy_1 #### Configure HydraPlay Finally we need to tell HydraPlay where it can find all the configured stuff. -Simply open the file ```environments/environment.ts``` in your HydraPlayer folder. +Simply open the file ```assets/config/config.production.ts``` in your HydraPlayer folder. Change the ports and ip addressed to your needs. Thats all. HydraPlay needs to be build from source. diff --git a/hydraplay/package-lock.json b/hydraplay/package-lock.json index d9065f56..abc971f1 100644 --- a/hydraplay/package-lock.json +++ b/hydraplay/package-lock.json @@ -523,6 +523,14 @@ "tslib": "^1.9.0" } }, + "@angular/http": { + "version": "7.2.15", + "resolved": "https://registry.npmjs.org/@angular/http/-/http-7.2.15.tgz", + "integrity": "sha512-TR7PEdmLWNIre3Zn8lvyb4lSrvPUJhKLystLnp4hBMcWsJqq5iK8S3bnlR4viZ9HMlf7bW7+Hm4SI6aB3tdUtw==", + "requires": { + "tslib": "^1.9.0" + } + }, "@angular/language-service": { "version": "7.2.15", "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-7.2.15.tgz", diff --git a/hydraplay/package.json b/hydraplay/package.json index 6b0607cd..433df965 100644 --- a/hydraplay/package.json +++ b/hydraplay/package.json @@ -21,6 +21,7 @@ "@angular/platform-browser": "^7.2.15", "@angular/platform-browser-dynamic": "^7.2.15", "@angular/router": "^7.2.15", + "@angular/http": "^7.2.15", "core-js": "^2.6.10", "crypto": "^1.0.1", "hide-virtual-keyboard": "^1.0.1", diff --git a/hydraplay/src/app/app.module.ts b/hydraplay/src/app/app.module.ts index cd900309..351e3df3 100644 --- a/hydraplay/src/app/app.module.ts +++ b/hydraplay/src/app/app.module.ts @@ -11,6 +11,14 @@ import { NoopAnimationsModule} from '@angular/platform-browser/animations'; import { PlaylistComponent } from './components/playlist/playlist.component'; import { FlexLayoutModule } from '@angular/flex-layout'; +import { APP_INITIALIZER } from '@angular/core'; +import {AppConfig} from './services/config.service'; +import {HttpModule} from '@angular/http'; + +export function initConfig(config: AppConfig) { + return () => config.load(); +} + @NgModule({ declarations: [ AppComponent, @@ -24,10 +32,17 @@ import { FlexLayoutModule } from '@angular/flex-layout'; HttpClientModule, AppRoutingModule, NoopAnimationsModule, - FlexLayoutModule + FlexLayoutModule, + HttpModule ], providers: [ - + AppConfig, + { + provide: APP_INITIALIZER, + useFactory: initConfig, + deps: [AppConfig], + multi: true + } ], bootstrap: [AppComponent] }) diff --git a/hydraplay/src/app/components/player/player.component.ts b/hydraplay/src/app/components/player/player.component.ts index 559554e8..8204dd13 100644 --- a/hydraplay/src/app/components/player/player.component.ts +++ b/hydraplay/src/app/components/player/player.component.ts @@ -21,9 +21,9 @@ export class PlayerComponent implements OnInit { @Input() showDialog: boolean; @Output() onCallMediaModal = new EventEmitter(); - private currentAlbumCover: string; - private currentArtist: string; - private currentTitle: string; + public currentAlbumCover: string; + public currentArtist: string; + public currentTitle: string; constructor(private messageService: MessageService, private mopidyService: MopidyService, private snapcastService: SnapcastService, private media: MediaComponent) { this.currentAlbumCover = '../../assets/images/cover_placeholder.jpg'; @@ -116,13 +116,12 @@ export class PlayerComponent implements OnInit { public updateTrackInfo() { return this.mopidy.getCurrentTrack().then(track => { - /* this.mopidy.getCover(track.uri).then(imageUri => { this.currentAlbumCover = imageUri; this.currentArtist = track.album.name; this.currentTitle = track.name; }); - */ + }).catch(err => { console.error(err); }); diff --git a/hydraplay/src/app/components/stream/stream.component.ts b/hydraplay/src/app/components/stream/stream.component.ts index f1a5f899..1b95c45f 100644 --- a/hydraplay/src/app/components/stream/stream.component.ts +++ b/hydraplay/src/app/components/stream/stream.component.ts @@ -11,8 +11,8 @@ export class StreamComponent implements OnInit { @Input() group: any; @Input() stream: any; - private cover: string; - private name: string; + public cover: string; + public name: string; constructor(private mopidyService: MopidyService, private snapcastservice: SnapcastService) { } diff --git a/hydraplay/src/app/services/config.service.ts b/hydraplay/src/app/services/config.service.ts new file mode 100644 index 00000000..8c61b746 --- /dev/null +++ b/hydraplay/src/app/services/config.service.ts @@ -0,0 +1,80 @@ +import { Inject, Injectable } from '@angular/core'; +import {Http,Response} from '@angular/http' +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { catchError } from 'rxjs/operators'; + +@Injectable() +export class AppConfig { + + private config: Object = null; + private env: Object = null; + + constructor(private http: Http) { + } + + /** + * Use to get the data found in the second file (config file) + */ + public getConfig(key: any) { + return this.config[key]; + } + + /** + * Use to get the data found in the first file (env file) + */ + public getEnv(key: any) { + return this.env[key]; + } + + /** + * This method: + * a) Loads "env.json" to get the current working environment (e.g.: 'production', 'development') + * b) Loads "config.[env].json" to get all env's variables (e.g.: 'config.development.json') + */ + public load() { + return new Promise((resolve, reject) => { + this.http.get('./assets/config/env.json') + .pipe(map( res => res.json())) + .pipe( catchError(err => { + console.log('Handling error locally and rethrowing it...', err); + return Observable.throw(err.json().error || 'Server error'); + })).subscribe( (envResponse) => { + this.env = envResponse; + let request: any = null; + + switch (envResponse.env) { + case 'production': { + request = this.http.get('./assets/config/config.' + envResponse.env + '.json'); + } break; + + case 'development': { + request = this.http.get('./assets/config/config.' + envResponse.env + '.json'); + console.log('calling config dev'); + } break; + + case 'default': { + console.error('Environment file is not set or invalid'); + resolve(true); + } break; + } + + if (request) { + request.pipe( + map((res: Response) => ( + res.json() + ))) + .subscribe((responseData: any) => { + this.config = responseData; + console.log(responseData); + resolve(true); + }); + } else { + console.error('Env config file "env.json" is not valid'); + resolve(true); + } + }); + + }); + } +} \ No newline at end of file diff --git a/hydraplay/src/app/services/mopidy.service.ts b/hydraplay/src/app/services/mopidy.service.ts index 07df926b..e33f113c 100644 --- a/hydraplay/src/app/services/mopidy.service.ts +++ b/hydraplay/src/app/services/mopidy.service.ts @@ -2,6 +2,7 @@ import { Injectable, EventEmitter } from '@angular/core'; import Mopidy from 'mopidy'; import { environment } from './../../environments/environment'; import {MessageService} from './message.service'; +import {AppConfig} from './config.service'; class MopidyEvent { constructor(public streamId: string, public label: string, public data: any) {} @@ -19,7 +20,9 @@ class MopidyPlayer { constructor(instance: any, private messageService: MessageService) { + this.setWebsocketProtocol(); + this.id = instance.id; this.socket = new Mopidy({webSocketUrl: `ws://${instance.ip}:${instance.port}/mopidy/ws/`}); this.isPlaying = false; @@ -164,10 +167,13 @@ class MopidyPlayer { export class MopidyService { public mopidies: MopidyPlayer[]; + private mopidyConfig: any; - constructor(private messageService: MessageService) { + constructor(private messageService: MessageService, private config: AppConfig) { this.mopidies = []; - environment.mopidy.forEach(mpInstance => { + this.mopidyConfig = this.config.getConfig('mopidy'); + + this.mopidyConfig.forEach(mpInstance => { let _mopidy = new MopidyPlayer(mpInstance, this.messageService) this.mopidies.push(_mopidy); }); diff --git a/hydraplay/src/app/services/snapcast.service.ts b/hydraplay/src/app/services/snapcast.service.ts index 3b5a1db9..9aad1861 100644 --- a/hydraplay/src/app/services/snapcast.service.ts +++ b/hydraplay/src/app/services/snapcast.service.ts @@ -1,10 +1,11 @@ import { ErrorHandler, Injectable, EventEmitter } from '@angular/core'; import { Observable, Subject, throwError } from 'rxjs'; import { HttpClient } from '@angular/common/http'; -import { map, tap, catchError } from 'rxjs/operators'; import { environment } from './../../environments/environment'; import {MessageService} from './message.service'; -//import { webSocket } from 'rxjs/webSocket'; // for RxJS 6, for v5 use Observable.webSocket + +import {AppConfig} from './config.service'; +import {logger} from "codelyzer/util/logger"; export interface Message { method: string; @@ -20,14 +21,15 @@ export class SnapcastService { public socket: any; public streams: any; + public snapcastConfig: any; + - public snapcastURL = `ws://${environment.snapcast.ip}:${environment.snapcast.port}/jsonrpc`; + constructor(private http: HttpClient, private messageService: MessageService, private config: AppConfig) { - constructor(private http: HttpClient, private messageService: MessageService) { + this.snapcastConfig = this.config.getConfig('snapcast'); + this.socket = new WebSocket(`ws://${this.snapcastConfig.ip}:${this.snapcastConfig.port}/jsonrpc`); - this.socket = new WebSocket(this.snapcastURL); - //this.socket.binaryType = 'arraybuffer'; let that = this; this.socket.onopen = function() { @@ -35,11 +37,7 @@ export class SnapcastService { } this.socket.onmessage = function(buf) { - console.log(buf.data); - //let recv = String.fromCharCode.apply(null, new Uint8Array(buf.data)); let jsonrpc = JSON.parse(buf.data); - - if (!jsonrpc.hasOwnProperty('error')) { if (!jsonrpc.hasOwnProperty('method') && jsonrpc.result.hasOwnProperty('server')) { @@ -90,7 +88,6 @@ export class SnapcastService { } else { message = JSON.stringify({id: this.uuidv4(), jsonrpc: '2.0', method: method}); } - console.log(message); return message; } @@ -103,7 +100,7 @@ export class SnapcastService { public sendAsync(method, params): Observable { let message = this.toJsonRPC(method, params); - return this.http.post(`http://${environment.snapcast.ip}:${environment.snapcast.port}/jsonrpc`, message); + return this.http.post(`http://${this.snapcastConfig.ip}:${this.snapcastConfig.port}/jsonrpc`, message); } handleError(error) { diff --git a/hydraplay/src/assets/config/config.development.json b/hydraplay/src/assets/config/config.development.json new file mode 100644 index 00000000..454f5587 --- /dev/null +++ b/hydraplay/src/assets/config/config.development.json @@ -0,0 +1,18 @@ +{ + snapcast: { + ip: '127.0.0.1', + port: 1780 + }, + mopidy: [ + { + ip: '127.0.0.1', + port: 6681, + id: 'STREAM1' + }, + { + ip: '127.0.0.1', + port: 6682, + id: 'STREAM2' + } + ] +} \ No newline at end of file diff --git a/hydraplay/src/assets/config/config.production.json b/hydraplay/src/assets/config/config.production.json new file mode 100644 index 00000000..454f5587 --- /dev/null +++ b/hydraplay/src/assets/config/config.production.json @@ -0,0 +1,18 @@ +{ + snapcast: { + ip: '127.0.0.1', + port: 1780 + }, + mopidy: [ + { + ip: '127.0.0.1', + port: 6681, + id: 'STREAM1' + }, + { + ip: '127.0.0.1', + port: 6682, + id: 'STREAM2' + } + ] +} \ No newline at end of file diff --git a/hydraplay/src/assets/config/env.json b/hydraplay/src/assets/config/env.json new file mode 100644 index 00000000..1f14b56c --- /dev/null +++ b/hydraplay/src/assets/config/env.json @@ -0,0 +1,3 @@ +{ + "env": "development" +} \ No newline at end of file diff --git a/hydraplay/src/environments/environment.ts b/hydraplay/src/environments/environment.ts index f06edc39..99c3763c 100644 --- a/hydraplay/src/environments/environment.ts +++ b/hydraplay/src/environments/environment.ts @@ -4,22 +4,6 @@ export const environment = { production: false, - snapcast: { - ip: '127.0.0.1', - port: 1780 - }, - mopidy: [ - { - ip: '127.0.0.1', - port: 6681, - id: 'STREAM1' - }, - { - ip: '127.0.0.1', - port: 6682, - id: 'STREAM2' - } - ] }; /*