diff --git a/de.json b/de.json index 2433e4c..0388395 100644 --- a/de.json +++ b/de.json @@ -42,6 +42,10 @@ "Name": "Shuffle", "Tooltip": "Shuffle" }, + "fun.shiro.ytmdc.repeat": { + "Name": "Wiederholungsmodus", + "Tooltip": "Wechselt den Wiederholungsmodus" + }, "Localization": { "PI": { "HOST": "Host", diff --git a/en.json b/en.json index a0e6efc..54667e6 100644 --- a/en.json +++ b/en.json @@ -42,6 +42,10 @@ "Name": "Shuffle", "Tooltip": "Shuffle" }, + "fun.shiro.ytmdc.repeat": { + "Name": "Repeat mode", + "Tooltip": "Change repeat mode" + }, "Localization": { "PI": { "HOST": "Host", diff --git a/property-inspector.html b/property-inspector.html index 9913211..8fafdcc 100644 --- a/property-inspector.html +++ b/property-inspector.html @@ -34,7 +34,7 @@

Something went wrong

Action
- diff --git a/scripts/build.js b/scripts/build.js index 83b9f24..9d52d92 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -65,6 +65,9 @@ browserify({entries: ['src/ytmd-pi.ts'], plugin: [tsify]}).bundle((err, buf) => fs.copyFileSync('manifest.json', 'build/fun.shiro.ytmd.sdPlugin/manifest.json'); fs.copyFileSync('property-inspector.html', 'build/fun.shiro.ytmd.sdPlugin/property-inspector.html'); fs.copyFileSync('action.html', 'build/fun.shiro.ytmd.sdPlugin/action.html'); + fs.copyFileSync('de.json', 'build/fun.shiro.ytmd.sdPlugin/de.json'); + fs.copyFileSync('en.json', 'build/fun.shiro.ytmd.sdPlugin/en.json'); + fs.copyFileSync('fr.json', 'build/fun.shiro.ytmd.sdPlugin/fr.json'); fs.cpSync('icons', 'build/fun.shiro.ytmd.sdPlugin/icons', {recursive: true}); // Run distribution tool diff --git a/src/actions/default.action.ts b/src/actions/default.action.ts index e82dd6b..365c457 100644 --- a/src/actions/default.action.ts +++ b/src/actions/default.action.ts @@ -20,6 +20,7 @@ export abstract class DefaultAction extends StreamDeckAction< this.socket = YTMD.COMPANION.socketClient; this.rest = YTMD.COMPANION.restClient; console.info(`Initialized ${actionName}`); + plugin.logMessage(`Initialized ${actionName}`); } abstract onContextAppear(event: WillAppearEvent): void; diff --git a/src/actions/like-dislike.action.ts b/src/actions/like-dislike.action.ts index 29e9aec..af3a0ed 100644 --- a/src/actions/like-dislike.action.ts +++ b/src/actions/like-dislike.action.ts @@ -46,10 +46,12 @@ export class LikeDislikeAction extends DefaultAction { onKeypressUp(event: KeyUpEvent): void { if (this.likeStatus === LikeStatus.LIKE) this.rest.toggleLike().catch(reason => { console.error(reason); + this.plugin.logMessage(`Error while like toggle. like status: ${this.likeStatus}, event: ${JSON.stringify(event)}, error: ${JSON.stringify(reason)}`); this.plugin.showAlert(event.context) }); else if (this.likeStatus === LikeStatus.DISLIKE) this.rest.toggleDislike().catch(reason => { console.error(reason); + this.plugin.logMessage(`Error while dislike toggle. like status: ${this.likeStatus}, event: ${JSON.stringify(event)}, error: ${JSON.stringify(reason)}`); this.plugin.showAlert(event.context) }); } diff --git a/src/actions/mute.action.ts b/src/actions/mute.action.ts index fb71cd7..f5f56ff 100644 --- a/src/actions/mute.action.ts +++ b/src/actions/mute.action.ts @@ -1,11 +1,13 @@ -import {KeyUpEvent, SDOnActionEvent, WillAppearEvent, WillDisappearEvent,} from 'streamdeck-typescript'; +import {KeyUpEvent, SDOnActionEvent, StateType, WillAppearEvent, WillDisappearEvent,} from 'streamdeck-typescript'; import {YTMD} from '../ytmd'; import {DefaultAction} from './default.action'; import {StateOutput} from "ytmdesktop-ts-companion"; export class MuteAction extends DefaultAction { private events: { context: string, method: (state: StateOutput) => void }[] = []; - private muted: boolean = false; + private initialized = false; + private volume = 0; + private lastVolume = 0; constructor(private plugin: YTMD, actionName: string) { super(plugin, actionName); @@ -20,7 +22,19 @@ export class MuteAction extends DefaultAction { found = { context: context, - method: (state: StateOutput) => this.muted = state.player.volume === 0 + method: (state: StateOutput) => { + if (!this.initialized) { + this.initialized = true; + this.volume = state.player.volume; + this.lastVolume = this.volume; + } + this.volume = state.player.volume; + if (this.volume > 0) { + this.lastVolume = this.volume; + } + + this.plugin.setState(this.volume > 0 ? StateType.ON : StateType.OFF, context); + } }; this.events.push(found); @@ -41,12 +55,24 @@ export class MuteAction extends DefaultAction { @SDOnActionEvent('keyUp') onKeypressUp(event: KeyUpEvent) { - this.muted = !this.muted; - this.muted ? this.rest.mute().catch(reason => { - console.error(reason); - this.plugin.showAlert(event.context) - }) : this.rest.unmute().catch(reason => { + if (this.volume <= 0) { + this.volume = this.lastVolume; + + this.rest.setVolume(this.volume).catch(reason => { + console.error(reason); + this.plugin.logMessage(`Error while setting volume. volume: ${this.volume}, event: ${JSON.stringify(event)}, error: ${JSON.stringify(reason)}`); + this.plugin.showAlert(event.context) + }); + + return; + } + + this.lastVolume = this.volume; + this.volume = 0; + + this.rest.setVolume(this.volume).catch(reason => { console.error(reason); + this.plugin.logMessage(`Error while setting volume. volume: ${this.volume}, event: ${JSON.stringify(event)}, error: ${JSON.stringify(reason)}`); this.plugin.showAlert(event.context) }); } diff --git a/src/actions/next-prev-action.ts b/src/actions/next-prev-action.ts index d8b62ef..3ff6756 100644 --- a/src/actions/next-prev-action.ts +++ b/src/actions/next-prev-action.ts @@ -23,10 +23,12 @@ export class NextPrevAction extends DefaultAction { onKeypressUp(event: KeyUpEvent) { if (this.nextOrPrev === 'NEXT') this.rest.next().catch(reason => { console.error(reason); + this.plugin.logMessage(`Error while next. event: ${JSON.stringify(event)}, error: ${JSON.stringify(reason)}`); this.plugin.showAlert(event.context) }); else this.rest.previous().catch(reason => { console.error(reason); + this.plugin.logMessage(`Error while previous. event: ${JSON.stringify(event)}, error: ${JSON.stringify(reason)}`); this.plugin.showAlert(event.context) }) } diff --git a/src/actions/play-pause.action.ts b/src/actions/play-pause.action.ts index c001acb..b8d8353 100644 --- a/src/actions/play-pause.action.ts +++ b/src/actions/play-pause.action.ts @@ -15,7 +15,7 @@ export class PlayPauseAction extends DefaultAction { private trackState: TrackState = TrackState.UNKNOWN; private currentTitle: string; private firstTimes = 10; - private format = '{current}'; + private contextFormat: { [key: string]: string } = {}; private events: { context: string, onTick: (state: StateOutput) => void, @@ -113,6 +113,7 @@ export class PlayPauseAction extends DefaultAction { if (!settings?.action) { this.rest.playPause().catch(reason => { console.error(reason); + this.plugin.logMessage(`Error while playPause toggle. context: ${JSON.stringify(context)}, error: ${JSON.stringify(reason)}`); this.plugin.showAlert(context) }) return; @@ -121,18 +122,21 @@ export class PlayPauseAction extends DefaultAction { case 'PLAY': this.rest.play().catch(reason => { console.error(reason); + this.plugin.logMessage(`Error while play. context: ${JSON.stringify(context)}, error: ${JSON.stringify(reason)}`); this.plugin.showAlert(context) }); break; case 'PAUSE': this.rest.pause().catch(reason => { console.error(reason); + this.plugin.logMessage(`Error while pause. context: ${JSON.stringify(context)}, error: ${JSON.stringify(reason)}`); this.plugin.showAlert(context) }); break; default: this.rest.playPause().catch(reason => { console.error(reason); + this.plugin.logMessage(`Error while playPause toggle. context: ${JSON.stringify(context)}, error: ${JSON.stringify(reason)}`); this.plugin.showAlert(context) }); break; @@ -142,7 +146,7 @@ export class PlayPauseAction extends DefaultAction { } handlePlayerData( - {context}: WillAppearEvent, + {context, payload: {settings}}: WillAppearEvent, data: StateOutput ) { if (Object.keys(data).length === 0) { @@ -151,9 +155,9 @@ export class PlayPauseAction extends DefaultAction { } let current = Math.floor(data.player.videoProgress); let duration = Math.floor(data.video?.durationSeconds ?? 0); - let remaining = Math.floor(data.player.videoProgress - (data.video?.durationSeconds ?? 0)); + let remaining = duration - current; - const title = this.formatTitle(current, duration, remaining); + const title = this.formatTitle(current, duration, remaining, context, settings); if (this.currentTitle !== title || this.firstTimes >= 1) { this.firstTimes--; @@ -170,24 +174,27 @@ export class PlayPauseAction extends DefaultAction { } } - private formatTitle(current: number, duration: number, remaining: number): string { + private formatTitle(current: number, duration: number, remaining: number, context: string, settings: PlayPauseSettings): string { current = current ?? 0; duration = duration ?? 0; remaining = remaining ?? 0; const varMapping: { [key: string]: string } = { 'current': PlayPauseAction.formatTime(current), + 'current:H': PlayPauseAction.formatTime(current), 'current:S': current.toString(), 'duration': PlayPauseAction.formatTime(duration), + 'duration:H': PlayPauseAction.formatTime(duration), 'duration:S': duration.toString(), 'remaining': PlayPauseAction.formatTime(remaining), + 'remaining:H': PlayPauseAction.formatTime(remaining), 'remaining:S': remaining.toString() }; - let result = this.format; + let result = this.contextFormat[context] ?? settings.displayFormat ?? '{current}'; for (let varMappingKey in varMapping) { const value = varMapping[varMappingKey]; - result = result.replace(new RegExp(`\{${varMappingKey}\}`, 'g'), value); + result = result.replace(new RegExp(`\{${varMappingKey}\}`, 'gi'), value); } return result; @@ -195,6 +202,6 @@ export class PlayPauseAction extends DefaultAction { @SDOnActionEvent('didReceiveSettings') private handleSettings(e: DidReceiveSettingsEvent) { - this.format = e?.payload?.settings?.displayFormat ?? this.format; + this.contextFormat[e.context] = e.payload.settings?.displayFormat ?? this.contextFormat[e.context]; } } diff --git a/src/actions/repeat.action.ts b/src/actions/repeat.action.ts index 0850b0d..e0e1053 100644 --- a/src/actions/repeat.action.ts +++ b/src/actions/repeat.action.ts @@ -23,19 +23,6 @@ export class RepeatAction extends DefaultAction { @SDOnActionEvent('willAppear') onContextAppear(event: WillAppearEvent): void { - // this.socket.onTick$ - // .pipe( - // map((data) => data.player.repeatType), - // distinctUntilChanged(), - // takeUntil(this.destroy$) - // ) - // .subscribe((repeatType) => { - // this.plugin.setImage( - // `data:image/png;base64,${this.icons[repeatType]}`, - // event.context - // ); - // }); - let found = this.events.find(e => e.context === event.context); if (found) { return; @@ -44,11 +31,11 @@ export class RepeatAction extends DefaultAction { found = { context: event.context, method: (state: StateOutput) => { - if (!state.player.queue?.repeatMode) { + if (state.player.queue?.repeatMode === undefined || state.player.queue.repeatMode === null || state.player.queue.repeatMode === this.currentMode) { return; } - const currentMode = state.player.queue.repeatMode; + this.currentMode = state.player.queue.repeatMode; let mode: "NONE" | "ONE" | "ALL" = "NONE"; switch (this.currentMode) { @@ -89,7 +76,7 @@ export class RepeatAction extends DefaultAction { @SDOnActionEvent('keyUp') onKeypressUp(event: KeyUpEvent): void { - let mode: RepeatMode = this.currentMode; + let mode: RepeatMode; switch (this.currentMode) { case RepeatMode.ALL: mode = RepeatMode.NONE; @@ -101,9 +88,9 @@ export class RepeatAction extends DefaultAction { mode = RepeatMode.ONE; break; } - this.rest.repeatMode(mode).catch(reason => { console.error(reason); + this.plugin.logMessage(`Error while setting repeat mode. mode: ${mode}, event: ${JSON.stringify(event)}, error: ${JSON.stringify(reason)}`); this.plugin.showAlert(event.context) }) } diff --git a/src/actions/shuffle.action.ts b/src/actions/shuffle.action.ts index 88934bf..1d0c893 100644 --- a/src/actions/shuffle.action.ts +++ b/src/actions/shuffle.action.ts @@ -17,6 +17,7 @@ export class ShuffleAction extends DefaultAction { .then(() => this.plugin.showOk(event.context)) .catch(reason => { console.error(reason); + this.plugin.logMessage(`Error while shuffle. event: ${JSON.stringify(event)}, error: ${JSON.stringify(reason)}`); this.plugin.showAlert(event.context) }); } diff --git a/src/actions/song-info.action.ts b/src/actions/song-info.action.ts index 87b105d..ea69930 100644 --- a/src/actions/song-info.action.ts +++ b/src/actions/song-info.action.ts @@ -13,7 +13,7 @@ export class SongInfoAction extends DefaultAction { private albumIndex = 0; private currentAlbum: string; private currentThumbnail: string; - private lastChange: Date; + private lastChange: {context: string, date:Date }[] = []; constructor(private plugin: YTMD, actionName: string) { super(plugin, actionName); @@ -36,6 +36,7 @@ export class SongInfoAction extends DefaultAction { context: event.context, method: (state: StateOutput) => this.handleSongInfo(event, state).catch(reason => { console.error(reason); + this.plugin.logMessage(`Error while executing handleSongInfo. state: ${JSON.stringify(state)}, event: ${JSON.stringify(event)}, error: ${JSON.stringify(reason)}`); this.plugin.showAlert(event.context) }) }; @@ -70,6 +71,7 @@ export class SongInfoAction extends DefaultAction { public onKeypressUp(event: KeyUpEvent): void { this.rest.playPause().catch(reason => { console.error(reason); + this.plugin.logMessage(`Error while playPause toggle (song info). event: ${JSON.stringify(event)}, error: ${JSON.stringify(reason)}`); this.plugin.showAlert(event.context) }); } @@ -109,8 +111,11 @@ export class SongInfoAction extends DefaultAction { } private async handleSongInfo(event: WillAppearEvent, state: StateOutput) { - if (this.lastChange && new Date().getTime() - this.lastChange.getTime() < 250) return; - this.lastChange = new Date(); + const lastChange = this.lastChange.find(l => l.context === event.context); + if (lastChange && new Date().getTime() - lastChange.date.getTime() < 450) return; + this.lastChange = this.lastChange.filter(l => l.context !== event.context); + this.lastChange.push({context: event.context, date: new Date()}); + const {title, album, author, cover} = this.getSongData(state); if (this.currentTitle !== title) this.titleIndex = 0; diff --git a/src/actions/vol-change.action.ts b/src/actions/vol-change.action.ts index c5ab4a7..ea0bf27 100644 --- a/src/actions/vol-change.action.ts +++ b/src/actions/vol-change.action.ts @@ -62,6 +62,7 @@ export class VolChangeAction extends DefaultAction { this.currentVolume = newVolume; this.rest.setVolume(newVolume <= 0 ? 0 : newVolume >= 100 ? 100 : newVolume).catch(reason => { console.error(reason); + this.plugin.logMessage(`Error while setting volume. volume: ${newVolume}, context: ${JSON.stringify(context)}, error: ${JSON.stringify(reason)}`); this.plugin.showAlert(context) }); await this.wait(500); diff --git a/src/pis/play-pause.pi.ts b/src/pis/play-pause.pi.ts index f7817b4..0b8bb75 100644 --- a/src/pis/play-pause.pi.ts +++ b/src/pis/play-pause.pi.ts @@ -15,7 +15,7 @@ export class PlayPausePi extends PisAbstract { this.pi.authButtonElement.onclick = () => { if (this.pi.authButtonElement.disabled) return; try { - this.setAuthStatusMessage(this.pi.localization.AUTH_STATUS_CONNECTING, 'yellow', true); + this.setAuthStatusMessage(this.pi.getLangString("AUTH_STATUS_CONNECTING"), 'yellow', true); const host = this.pi.hostElement.value, port = this.pi.portElement.value; @@ -29,18 +29,18 @@ export class PlayPausePi extends PisAbstract { }); connector.restClient.getAuthCode().then((res) => { - this.setAuthStatusMessage(this.pi.localization.AUTH_STATUS_AUTHORIZING, 'yellow', true); + this.setAuthStatusMessage(this.pi.getLangString("AUTH_STATUS_AUTHORIZING"), 'yellow', true); if (!res.code) { - this.setAuthStatusMessage(this.pi.localization.AUTH_STATUS_ERROR, 'red', false); + this.setAuthStatusMessage(this.pi.getLangString("AUTH_STATUS_ERROR"), 'red', false); return; } - this.pi.authStatusElement.innerText = `AUTH CODE: ${res.code}\n\n${this.pi.localization.AUTH_CODE_COMPARE}`; + this.pi.authStatusElement.innerText = `AUTH CODE: ${res.code}\n\n${this.pi.getLangString("AUTH_CODE_COMPARE")}`; connector.restClient.getAuthToken(res.code).then((res) => { if (res.token) { this.authToken = res.token; - this.setAuthStatusMessage(this.pi.localization.AUTH_STATUS_CONNECTED, 'green', false); + this.setAuthStatusMessage(this.pi.getLangString("AUTH_STATUS_CONNECTED"), 'green', false); this.saveSettings(); } else { this.authErrorCatched(res); @@ -85,6 +85,7 @@ export class PlayPausePi extends PisAbstract { } private authErrorCatched(err: any) { + this.pi.logMessage(`Auth error: ${JSON.stringify(err)}`); let msg = ""; if (err satisfies ErrorOutput) { msg = err.message; @@ -92,10 +93,10 @@ export class PlayPausePi extends PisAbstract { msg = JSON.stringify(err); } if (!this.pi.authStatusElement) { - alert(`${this.pi.localization.AUTH_STATUS_ERROR}\n${msg}`); + alert(`${this.pi.getLangString("AUTH_STATUS_ERROR")}\n${msg}`); return; } - this.setAuthStatusMessage(`${this.pi.localization.AUTH_STATUS_ERROR}\n${msg}`, 'red', false); + this.setAuthStatusMessage(`${this.pi.getLangString("AUTH_STATUS_ERROR")}\n${msg}`, 'red', false); } private saveSettings() { diff --git a/src/ytmd-pi.ts b/src/ytmd-pi.ts index 579e059..f100dc0 100644 --- a/src/ytmd-pi.ts +++ b/src/ytmd-pi.ts @@ -6,7 +6,6 @@ import {PlayPausePi} from './pis/play-pause.pi'; import {VolumeChangePi} from './pis/volume-change.pi'; export class YTMDPi extends StreamDeckPropertyInspectorHandler { - public localization: LocalizationInterface['PI']; // Play / Pause Settings public playPauseSettings: HTMLElement; public hostElement: HTMLInputElement; @@ -20,6 +19,7 @@ export class YTMDPi extends StreamDeckPropertyInspectorHandler { // Volume Settings public volumeSettings: HTMLElement; public volumeInput: HTMLInputElement; + private localization: LocalizationInterface['PI']; // Error messages private errorsElement: HTMLElement; private errorTemplateElement: HTMLElement; @@ -31,7 +31,7 @@ export class YTMDPi extends StreamDeckPropertyInspectorHandler { } // Load the localizations - public getLocalization( + public fetchLocalizationFile( inLanguage: string, inCallback: (b: boolean, s: string | LocalizationInterface) => void ) { @@ -98,11 +98,7 @@ export class YTMDPi extends StreamDeckPropertyInspectorHandler { @SDOnPiEvent('setupReady') private documentLoaded() { - this.getLocalization(this.info.application.language ?? 'en', (b, s) => { - this.localization = (s as LocalizationInterface).PI; - this.setupLocalization(b, this.localization); - } - ); + this.setupLocalization(); this.setupElements(); const _action: ActionTypes = this.actionInfo.action as ActionTypes; switch (_action) { @@ -128,25 +124,50 @@ export class YTMDPi extends StreamDeckPropertyInspectorHandler { } } - private setupLocalization(succeed: boolean, status: LocalizationInterface['PI']) { - if (!succeed) return; - - this.setInnerHtmlByClass('host-label', status.HOST); - this.setInnerHtmlByClass('port-label', status.PORT); - this.setInnerHtmlByClass('display-label', status.DISPLAY_FORMAT); - this.setInnerHtmlByClass('save-label', status.SAVE); - this.setInnerHtmlByClass('volume-steps-label', status.VOLUME_STEPS); - this.setInnerHtmlByClass('automatic-save-label', status.AUTOMATIC_SAVE); - this.setInnerHtmlByClass('auth-button-label', status.AUTH_BUTTON); - this.setInnerHtmlByClass('auth-label', status.AUTH_STATUS); - this.setInnerHtmlByClass('auth-status-label', status.AUTH_STATUS_NOT_CONNECTED); - this.setInnerHtmlByClass('support-feedback-title-label', status.SUPPORT_FEEDBACK_TITLE); - this.setInnerHtmlByClass('support-feedback-text-label', status.SUPPORT_FEEDBACK_TEXT); - this.setInnerHtmlByClass('var-usage-label', status.VAR_USAGE); - this.setInnerHtmlByClass('action-label', status.ACTION); - this.setInnerHtmlByClass('toggle-label', status.TOGGLE); - this.setInnerHtmlByClass('pause-label', status.PAUSE); - this.setInnerHtmlByClass('play-label', status.PLAY); + public getLangString(key: keyof LocalizationInterface['PI'], defaultValue: string = 'NOT TRANSLATED') { + try { + return this.localization[key] ?? defaultValue; + } catch (e) { + return defaultValue; + } + } + + private setupLocalization() { + this.fetchLocalizationFile(this.info.application.language ?? 'en', (b, s) => { + if (!b) { + this.logMessage(`Failed to load the localization file. Reason: ${s}. Using default language.`); + // try to load the default language + this.fetchLocalizationFile('en', (b2, s2) => { + if (!b2) { + this.logMessage(`Failed to load the default localization file. Reason: ${s2}.`); + } + this.localization = (s2 as LocalizationInterface).PI; + this.translateHtml(); + }); + return; + } + this.localization = (s as LocalizationInterface).PI; + this.translateHtml(); + }); + } + + private translateHtml() { + this.setInnerHtmlByClass('host-label', this.getLangString("HOST")); + this.setInnerHtmlByClass('port-label', this.getLangString("PORT")); + this.setInnerHtmlByClass('display-label', this.getLangString("DISPLAY_FORMAT")); + this.setInnerHtmlByClass('save-label', this.getLangString("SAVE")); + this.setInnerHtmlByClass('volume-steps-label', this.getLangString("VOLUME_STEPS")); + this.setInnerHtmlByClass('automatic-save-label', this.getLangString("AUTOMATIC_SAVE")); + this.setInnerHtmlByClass('auth-button-label', this.getLangString("AUTH_BUTTON")); + this.setInnerHtmlByClass('auth-label', this.getLangString("AUTH_STATUS")); + this.setInnerHtmlByClass('auth-status-label', this.getLangString("AUTH_STATUS_NOT_CONNECTED")); + this.setInnerHtmlByClass('support-feedback-title-label', this.getLangString("SUPPORT_FEEDBACK_TITLE")); + this.setInnerHtmlByClass('support-feedback-text-label', this.getLangString("SUPPORT_FEEDBACK_TEXT")); + this.setInnerHtmlByClass('var-usage-label', this.getLangString("VAR_USAGE")); + this.setInnerHtmlByClass('action-label', this.getLangString("ACTION")); + this.setInnerHtmlByClass('toggle-label', this.getLangString("TOGGLE")); + this.setInnerHtmlByClass('pause-label', this.getLangString("PAUSE")); + this.setInnerHtmlByClass('play-label', this.getLangString("PLAY")); } @SDOnPiEvent('didReceiveGlobalSettings') diff --git a/src/ytmd.ts b/src/ytmd.ts index 08a3321..4033200 100644 --- a/src/ytmd.ts +++ b/src/ytmd.ts @@ -29,6 +29,7 @@ export class YTMD extends StreamDeckPluginHandler { YTMD._COMPANION.socketClient.connect(); } catch (e) { console.error(e); + this.logMessage(`Error while connecting. error: ${JSON.stringify(e)}`); } new PlayPauseAction(this, ActionTypes.PLAY_PAUSE); new NextPrevAction(this, ActionTypes.NEXT_TRACK, 'NEXT');