Skip to content

Commit

Permalink
feat(error-watcher): Show an error message when libndi is not install…
Browse files Browse the repository at this point in the history
…ed. (#564)

* feat(error-watcher): Show an error message when libndi is not installed.

* feat(errorwatcher): handles external links and multiple errors

Adds ElectronLink component for opening a link in the default OS browser. Updates ErrorWatcher to
clear errors once dismissed and to handle multiple errors gracefully.

* refactor: removes local impot of global component

Co-authored-by: Sam Wray <sam@wray.pro>
  • Loading branch information
TimPietrusky and 2xAA authored Mar 11, 2021
1 parent 134fffd commit 697dd79
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 18 deletions.
6 changes: 5 additions & 1 deletion src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@
<Search />

<FrameRateDialog />

<ErrorWatcher />
</main>
</template>

Expand All @@ -98,6 +100,7 @@ import ModuleInspector from "@/components/ModuleInspector";
import InfoView from "@/components/InfoView";
import Search from "@/components/Search";
import FrameRateDialog from "@/components/dialogs/FrameRateDialog";
import ErrorWatcher from "@/components/ErrorWatcher";
import getNextName from "@/application/utils/get-next-name";
import constants from "@/application/constants";
Expand All @@ -121,7 +124,8 @@ export default {
InfoView,
ModuleInspector,
Search,
FrameRateDialog
FrameRateDialog,
ErrorWatcher
},
data() {
Expand Down
37 changes: 37 additions & 0 deletions src/application/setup-grandiose.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/* globals __dirname */

import store from "./worker/store/index";

let grandiose = undefined;

export default function setupGrandiose() {
if (grandiose === undefined) {
/* eslint-disable */
__dirname = `${__dirname}/node_modules/grandiose`;
__dirname = __dirname.replace("app.asar", "app.asar.unpacked");
/* eslint-enable */

try {
grandiose = require("grandiose");
} catch (error) {
if (error.message.includes("libndi.so")) {
store.dispatch("errors/createMessage", {
message:
"libndi is not installed, please see \"Ubuntu/Debian\" in the modV <ElectronLink to='https://github.com/vcync/modV#ubuntudebian'>README</ElectronLink>."
});
} else {
console.error(error);
}
}

// eslint-disable-next-line
__dirname = __dirname.replace("/node_modules/grandiose", "");
}

// Make sure to set grandiose to undefined as it will be an empty object otherwise
if (!grandiose.isSupportedCPU) {
grandiose = undefined;
}

return grandiose;
}
37 changes: 37 additions & 0 deletions src/application/worker/store/modules/errors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import Vue from "vue";
import uuidv4 from "uuid/v4";

const state = {
messages: {}
};

const actions = {
createMessage({ commit }, { message }) {
if (!message) {
throw new Error("No message given");
}

commit("CREATE_MESSAGE", { message, id: uuidv4() });
},

deleteMessage({ commit }, { id }) {
commit("REMOVE_MESSAGE", { id });
}
};

const mutations = {
CREATE_MESSAGE(state, { message, id }) {
Vue.set(state.messages, id, message);
},

REMOVE_MESSAGE(state, { id }) {
Vue.delete(state.messages, id);
}
};

export default {
namespaced: true,
state,
mutations,
actions
};
23 changes: 6 additions & 17 deletions src/application/worker/store/modules/ndi.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,7 @@
/* globals __dirname */

import uuidv4 from "uuid/v4";
import Vue from "vue";
import store from "../";

/* eslint-disable */
__dirname = `${__dirname}/node_modules/grandiose`;
__dirname = __dirname.replace("app.asar", "app.asar.unpacked");
/* eslint-enable */

const grandiose = require("grandiose");

// eslint-disable-next-line
__dirname = __dirname.replace("/node_modules/grandiose", "");
import grandiose from "../../../setup-grandiose";

const state = {
discovering: false,
Expand Down Expand Up @@ -44,7 +33,7 @@ const state = {
};

function checkCpu() {
if (!grandiose.isSupportedCPU()) {
if (!grandiose().isSupportedCPU()) {
throw new Error("Your CPU is not supported for NDI");
}
}
Expand Down Expand Up @@ -97,7 +86,7 @@ const actions = {
commit("SET_DISCOVERING", true);

try {
const sources = await grandiose.find(
const sources = await grandiose().find(
state.discoveryOptions,
state.timeout
);
Expand All @@ -114,10 +103,10 @@ const actions = {
},

async createReceiver({ commit }, receiverOptions) {
receiverOptions.colorFormat = grandiose.COLOR_FORMAT_RGBX_RGBA;
receiverOptions.bandwidth = grandiose.BANDWIDTH_LOWEST;
receiverOptions.colorFormat = grandiose().COLOR_FORMAT_RGBX_RGBA;
receiverOptions.bandwidth = grandiose().BANDWIDTH_LOWEST;

const receiver = await grandiose.receive(receiverOptions);
const receiver = await grandiose().receive(receiverOptions);

const outputContext = await store.dispatch("outputs/getAuxillaryOutput", {
name: receiverOptions.source.name,
Expand Down
29 changes: 29 additions & 0 deletions src/components/ElectronLink.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<template>
<a @click.prevent="openUrl"><slot /></a>
</template>

<script>
import { shell } from "electron";
export default {
props: {
to: {
type: String,
required: true
}
},
methods: {
openUrl() {
shell.openExternal(this.to);
}
}
};
</script>

<style scoped>
a {
cursor: pointer;
text-decoration: underline;
}
</style>
42 changes: 42 additions & 0 deletions src/components/ErrorWatcher.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<template>
<!-- key is used to trigger re-mount of component when the next error message is available -->
<Dialog
v-if="message"
:key="messageId"
@close="dialogClosed"
title="Error"
style="max-width: 420px"
>
<component
:is="{
template: `<span>${this.message}</span>`
}"
></component>
</Dialog>
</template>

<script>
import Dialog from "./Dialog";
export default {
components: {
Dialog
},
computed: {
message() {
return Object.values(this.$modV.store.state.errors.messages)[0];
},
messageId() {
return Object.keys(this.$modV.store.state.errors.messages)[0];
}
},
methods: {
dialogClosed() {
this.$modV.store.dispatch("errors/deleteMessage", { id: this.messageId });
}
}
};
</script>
2 changes: 2 additions & 0 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Vue from "vue";
import vgl from "vue-golden-layout";
import Fragment from "vue-fragment";
import "./components/inputs";
import ElectronLink from "./components/ElectronLink";
import "./components/directives/InfoView";
import "./components/directives/Search";
import "./components/directives/ValueTooltip";
Expand All @@ -15,6 +16,7 @@ Vue.config.ignoredElements = ["grid", "c"];
Vue.config.productionTip = false;
Vue.use(vgl);
Vue.use(Fragment.Plugin);
Vue.component("ElectronLink", ElectronLink);

const modV = new ModV();
window.modV = modV;
Expand Down
2 changes: 2 additions & 0 deletions vue.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ const publishingOptions = {
};

module.exports = {
runtimeCompiler: true,

// https://cli.vuejs.org/config/#pages
pages: {
index: "src/main.js",
Expand Down

0 comments on commit 697dd79

Please sign in to comment.