def create_config_entries(config):
''' get the config entries for this module (list with key/value pairs)'''
config_entries = [
- (CONF_ENABLED, False, CONF_ENABLED),
- ('url', 'localhost', 'URL to homeassistant (e.g. https://homeassistant:8123)'),
- ('token', '<password>', 'Long Lived Access Token'),
- ('publish_players', True, 'Publish players to Home Assistant')
+ (CONF_ENABLED, False, 'enabled'),
+ ('url', 'localhost', 'hass_url'),
+ ('token', '<password>', 'hass_token'),
+ ('publish_players', True, 'hass_publish')
]
if not config['base'].get('homeassistant'):
config['base']['homeassistant'] = {}
config['base']['homeassistant'][key] = def_value
# append hass player config settings
if config['base']['homeassistant'][CONF_ENABLED]:
- hass_player_conf = [("hass_power_entity", "", "Attach player power to homeassistant entity"),
- ("hass_power_entity_source", "", "Source on the homeassistant entity (optional)"),
- ("hass_volume_entity", "", "Attach player volume to homeassistant entity")]
+ hass_player_conf = [("hass_power_entity", "", "hass_player_power"),
+ ("hass_power_entity_source", "", "hass_player_source"),
+ ("hass_volume_entity", "", "hass_player_volume")]
for key, default, desc in hass_player_conf:
entry_found = False
for value in config['player_settings']['__desc__']:
''' get the config entries for this provider (list with key/value pairs)'''
return [
(CONF_ENABLED, False, CONF_ENABLED),
- ("music_dir", "", "Path to music files"),
- ("playlists_dir", "", "Path to playlists")
+ ("music_dir", "", "file_prov_music_path"),
+ ("playlists_dir", "", "file_prov_playlists_path")
]
class FileProvider(MusicProvider):
def create_config_entries(config):
''' get the config entries for this module (list with key/value pairs)'''
config_entries = [
- ('ssl_certificate', '', 'Path to ssl certificate file'),
- ('ssl_key', '', 'Path to ssl keyfile'),
- ('hostname', '', 'Hostname (FQDN used in the certificate)')
+ ('ssl_certificate', '', 'web_ssl_cert'),
+ ('ssl_key', '', 'web_ssl_key'),
+ ('hostname', '', 'web_ssl_host')
]
if not config['base'].get('web'):
config['base']['web'] = {}
def create_config_entries(self):
''' sets the config entries for this module (list with key/value pairs)'''
self.mass.config['player_settings']['__desc__'] = [
- ("enabled", False, "Enable player"),
- ("name", "", "Custom name for this player"),
- ("group_parent", "<player>", "Group this player to another player"),
- ("mute_as_power", False, "Use muting as power control"),
- ("disable_volume", False, "Disable volume controls"),
- ("apply_group_volume", False, "Apply group volume to childs (for group players only)"),
- ("apply_group_power", False, "Apply group power based on childs (for group players only)"),
- ("play_power_on", False, "Issue play command on power on")
+ ("enabled", False, "player_enabled"),
+ ("name", "", "player_name"),
+ ("group_parent", "<player>", "player_group_with"),
+ ("mute_as_power", False, "player_mute_power"),
+ ("disable_volume", False, "player_disable_vol"),
+ ("apply_group_volume", False, "player_group_vol"),
+ ("apply_group_power", False, "player_group_pow"),
+ ("play_power_on", False, "player_power_play")
]
async def players(self):
''' handle hass integration in player command '''
if not self.mass.hass:
return
- if cmd == 'power' and cmd_args == 'on' and player.settings.get('hass_power_entity') and player.settings.get('hass_power_entity_source'):
- service_data = { 'entity_id': player.settings['hass_power_entity'], 'source':player.settings['hass_power_entity_source'] }
- await self.mass.hass.call_service('media_player', 'select_source', service_data)
+ if cmd == 'power' and player.settings.get('hass_power_entity') and player.settings.get('hass_power_entity_source'):
+ cur_source = await self.mass.hass.get_state(player.settings['hass_power_entity'], attribute='source')
+ if cmd_args == 'on' and not cur_source:
+ service_data = { 'entity_id': player.settings['hass_power_entity'], 'source':player.settings['hass_power_entity_source'] }
+ await self.mass.hass.call_service('media_player', 'select_source', service_data)
+ elif cmd_args == 'off' and cur_source == player.settings['hass_power_entity_source']:
+ service_data = { 'entity_id': player.settings['hass_power_entity'] }
+ await self.mass.hass.call_service('media_player', 'turn_off', service_data)
+ else:
+ LOGGER.warning('Ignoring power command as required source is not active')
elif cmd == 'power' and player.settings.get('hass_power_entity'):
domain = player.settings['hass_power_entity'].split('.')[0]
service_data = { 'entity_id': player.settings['hass_power_entity']}
</v-list>
</v-navigation-drawer>
- <v-toolbar fixed flat dense dark color="transparent" scroll-off-screen >
+
+ <v-toolbar app flat dense dark v-if="$globals.windowtitle" >
<v-layout align-center>
<v-btn icon v-on:click="menu=!menu">
<v-icon>menu</v-icon>
<v-icon>arrow_back</v-icon>
</v-btn>
<v-spacer></v-spacer>
+ <v-card-title class="title justify-center">
+ {{ $globals.windowtitle }}
+ </v-card-title>
<v-spacer></v-spacer>
- <v-btn icon v-on:click="$router.push('/search')">
+ <v-btn icon v-on:click="$globals.showsearchbox = true">
+ <v-icon>search</v-icon>
+ </v-btn>
+ </v-layout>
+ </v-toolbar>
+ <v-toolbar flat fixed dense dark scroll-off-screen color="transparent" v-if="!$globals.windowtitle" >
+ <v-layout align-center>
+ <v-btn icon v-on:click="menu=!menu">
+ <v-icon>menu</v-icon>
+ </v-btn>
+ <v-btn @click="$router.go(-1)" icon>
+ <v-icon>arrow_back</v-icon>
+ </v-btn>
+ <v-spacer></v-spacer>
+ <v-spacer></v-spacer>
+ <v-btn icon v-on:click="$globals.showsearchbox = true">
<v-icon>search</v-icon>
</v-btn>
</v-layout>
return {
menu: false,
items: [
- { title: "Home", icon: "home", path: "/" },
- { title: "Artists", icon: "person", path: "/artists" },
- { title: "Albums", icon: "album", path: "/albums" },
- { title: "Tracks", icon: "audiotrack", path: "/tracks" },
- { title: "Playlists", icon: "playlist_play", path: "/playlists" },
- { title: "Search", icon: "search", path: "/search" },
- { title: "Config", icon: "settings", path: "/config" }
+ { title: this.$t('home'), icon: "home", path: "/" },
+ { title: this.$t('artists'), icon: "person", path: "/artists" },
+ { title: this.$t('albums'), icon: "album", path: "/albums" },
+ { title: this.$t('tracks'), icon: "audiotrack", path: "/tracks" },
+ { title: this.$t('playlists'), icon: "playlist_play", path: "/playlists" },
+ { title: this.$t('search'), icon: "search", path: "/search" },
+ { title: this.$t('settings'), icon: "settings", path: "/config" }
]
}
},
<v-btn flat icon @click="$router.push('/queue/' + active_player_id)">
<v-flex xs12 class="vertical-btn">
<v-icon large>queue_music</v-icon>
- <span class="caption">Queue</span>
+ <span class="caption">{{ $t('queue') }}</span>
</v-flex>
</v-btn>
</v-list-tile-action>
<volumecontrol v-bind:players="players" v-bind:player_id="player.player_id" v-on:setPlayerVolume="setPlayerVolume" v-on:togglePlayerPower="togglePlayerPower"/>
</v-menu>
</v-list-tile-action>
-
-
-
</v-list-tile>
<v-divider></v-divider>
</div>
+++ /dev/null
-Vue.component("searchbar", {
- template: `
- <section class="section searchbar">
- <div class="container">
- <b-field>
- <b-autocomplete size="is-medium"
- expanded
- v-model="searchQuery"
- :data="filteredDataArray"
- placeholder="e.g. Eminem"
- icon="magnify"
- @select="option => selected = option"
- @keyup.enter="onClickSearch"
- ></b-autocomplete>
- <p class="control" v-if="searchQuery">
- <button @click="onClickClearSearch" class="button is-medium "><i class="fas fa-times"></i></button>
- </p>
- </b-field>
- </div>
- </section>
- `,
- data () {
- return {
- data: [],
- searchQuery: '',
- selected: null
- }
- },
- props: {
- recentSearch: {
- type: Array,
- required: true
- },
- newSearchQuery: {
- type: String,
- required: true
- },
- settings: {
- type: Object,
- required: true
- }
- },
- mounted () {
- this.searchQuery = this.settings.initialSearchQuery
- this.onClickSearch()
- },
- watch: {
- searchQuery: {
- handler: _.debounce(function (val) {
- if (val === '') {
- this.$store.commit('CLEAR_SEARCH')
- } else {
- if (val !== this.newSearchQuery) {
- this.onClickSearch()
- }
- }
- }, 1000)
- },
- newSearchQuery (val) {
- this.searchQuery = val
- }
- },
- computed: {
- filteredDataArray () {
- return this.recentSearch.filter(option => {
- return (
- option
- .toString()
- .toLowerCase()
- .indexOf(this.searchQuery.toLowerCase()) >= 0
- )
- })
- }
- },
- methods: {
- onClickSearch () {
- this.$emit('clickSearch', this.searchQuery)
- },
- onClickClearSearch () {
- this.searchQuery = ''
- this.$emit('clickClearSearch')
- }
- }
-})
-/* <style>
-.searchbar {
- padding: 1rem 1.5rem!important;
- width: 100%;
- box-shadow: 0 0 70px 0 rgba(0, 0, 0, 0.3);
- background: #fff;
-}
-</style> */
\ No newline at end of file
--- /dev/null
+Vue.component("searchbox", {
+ template: `
+ <v-dialog :value="$globals.showsearchbox" @input="$emit('input', $event)" max-width="500px">
+ <v-text-field
+ solo
+ clearable
+ :label="$t('type_to_search')"
+ prepend-inner-icon="search"
+ v-model="searchQuery">
+ </v-text-field>
+ </v-dialog>
+ `,
+ data () {
+ return {
+ searchQuery: "",
+ }
+ },
+ props: ['value'],
+ mounted () {
+ this.searchQuery = "" // TODO: set to last searchquery ?
+ },
+ watch: {
+ searchQuery: {
+ handler: _.debounce(function (val) {
+ this.onSearch();
+ // if (this.searchQuery)
+ // this.$globals.showsearchbox = false;
+ }, 1000)
+ },
+ newSearchQuery (val) {
+ this.searchQuery = val
+ }
+ },
+ computed: {},
+ methods: {
+ onSearch () {
+ //this.$emit('clickSearch', this.searchQuery)
+ console.log(this.searchQuery);
+ router.push({ path: '/search', query: {searchQuery: this.searchQuery}});
+ },
+ }
+})
+/* <style>
+.searchbar {
+ padding: 1rem 1.5rem!important;
+ width: 100%;
+ box-shadow: 0 0 70px 0 rgba(0, 0, 0, 0.3);
+ background: #fff;
+}
+</style> */
\ No newline at end of file
<v-content>
<headermenu></headermenu>
<player></player>
- <router-view :key="$route.path"></router-view>
+ <router-view app :key="$route.path"></router-view>
+ <searchbox/>
</v-content>
<v-dialog
v-model="$globals.loading"
</v-card-text>
</v-card>
</v-dialog>
-
</v-app>
</div>
- <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
+ <!-- <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script> -->
+ <script src="https://unpkg.com/vue/dist/vue.js"></script>
+ <script src="https://unpkg.com/vue-i18n/dist/vue-i18n.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.10/lodash.min.js"></script>
<script src='./pages/playlistdetails.vue.js'></script>
<script src='./pages/search.vue.js'></script>
<script src='./pages/queue.vue.js'></script>
+ <script src='./pages/config.vue.js'></script>
<script src='./components/headermenu.vue.js'></script>
<script src='./components/volumecontrol.vue.js'></script>
<script src='./components/infoheader.vue.js'></script>
<script src='./components/qualityicon.vue.js'></script>
- <script src='./pages/config.vue.js'></script>
+ <script src='./components/searchbox.vue.js'></script>
+
+ <script src='./strings.js'></script>
<script>
Vue.use(VueRouter);
Vue.use(VeeValidate);
Vue.use(Vuetify);
+ Vue.use(VueI18n);
const routes = [
windowtitle: 'Home',
loading: false,
showplaymenu: false,
+ showsearchbox: false,
playmenuitem: null
}
})
Vue.prototype.toggleLibrary = toggleLibrary;
Vue.prototype.showPlayMenu = showPlayMenu;
Vue.prototype.clickItem= clickItem;
+
+ const i18n = new VueI18n({
+ locale: navigator.language.split('-')[0],
+ fallbackLocale: 'en',
+ enableInSFC: true,
+ messages
+ })
var app = new Vue({
+ i18n,
el: '#app',
watch: {},
mounted() {
-
},
data: { },
methods: {},
}
},
created() {
- this.$globals.windowtitle = "Album info"
+ this.$globals.windowtitle = ""
this.getInfo();
this.getAlbumTracks();
},
}
},
created() {
- this.$globals.windowtitle = "Artist info"
+ this.$globals.windowtitle = ""
this.getInfo();
},
methods: {
var Browse = Vue.component('Browse', {
template: `
<section>
- <v-flex xs12>
- <v-card class="flex" tile style="background-color:rgba(0,0,0,.54);color:#ffffff;">
- <v-card-title class="title justify-center">
- {{ $globals.windowtitle }}
- </v-card-title>
- </v-card>
- </v-flex>
<v-list two-line>
<listviewItem
v-for="(item, index) in items"
created() {
this.showavatar = true;
mediatitle =
- this.$globals.windowtitle = this.mediatype.charAt(0).toUpperCase() + this.mediatype.slice(1);
+ this.$globals.windowtitle = this.$t(this.mediatype)
this.scroll(this.Browse);
this.getItems();
},
var Config = Vue.component('Config', {
template: `
<section>
- <v-flex xs12>
- <v-card class="flex" tile style="background-color:rgba(0,0,0,.54);color:#ffffff;">
- <v-card-title class="title justify-center">
- {{ $globals.windowtitle }}
- </v-card-title>
- </v-card>
- </v-flex>
<v-list two-line>
<template v-slot:activator>
<v-list-tile>
<v-list-tile-content>
- <v-list-tile-title>Generic settings</v-list-tile-title>
+ <v-list-tile-title>{{ $t('generic_settings') }}</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</template>
<div v-for="conf_item_key in conf.base[conf_key].__desc__">
<v-list-tile>
- <v-switch v-if="typeof(conf_item_key[1]) == 'boolean'" v-model="conf.base[conf_key][conf_item_key[0]]" :label="conf_item_key[2]"></v-switch>
- <v-text-field v-else-if="conf_item_key[1] == '<password>'" v-model="conf.base[conf_key][conf_item_key[0]]" :label="conf_item_key[2]" box type="password"></v-text-field>
- <v-select v-else-if="conf_item_key[1] == '<player>'" v-model="conf.base[conf_key][conf_item_key[0]]" :label="conf_item_key[2]" box type="password"></v-select>
- <v-text-field v-else v-model="conf.base[conf_key][conf_item_key[0]]" :label="conf_item_key[2]" box></v-text-field>
+ <v-switch v-if="typeof(conf_item_key[1]) == 'boolean'" v-model="conf.base[conf_key][conf_item_key[0]]" :label="$t(conf_item_key[2])"></v-switch>
+ <v-text-field v-else-if="conf_item_key[1] == '<password>'" v-model="conf.base[conf_key][conf_item_key[0]]" :label="$t(conf_item_key[2])" box type="password"></v-text-field>
+ <v-select v-else-if="conf_item_key[1] == '<player>'" v-model="conf.base[conf_key][conf_item_key[0]]" :label="$t(conf_item_key[2])" box type="password"></v-select>
+ <v-text-field v-else v-model="conf.base[conf_key][conf_item_key[0]]" :label="$t(conf_item_key[2])" box></v-text-field>
</v-list-tile>
</div>
<v-divider></v-divider>
<template v-slot:activator>
<v-list-tile>
<v-list-tile-content>
- <v-list-tile-title>Music Providers</v-list-tile-title>
+ <v-list-tile-title>{{ $t('music_providers') }}</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</template>
<div v-for="conf_item_key in conf.musicproviders[conf_key].__desc__">
<v-list-tile>
- <v-switch v-if="typeof(conf_item_key[1]) == 'boolean'" v-model="conf.musicproviders[conf_key][conf_item_key[0]]" :label="conf_item_key[2]"></v-switch>
- <v-text-field v-else-if="conf_item_key[1] == '<password>'" v-model="conf.musicproviders[conf_key][conf_item_key[0]]" :label="conf_item_key[2]" box type="password"></v-text-field>
- <v-select v-else-if="conf_item_key[1] == '<player>'" v-model="conf.musicproviders[conf_key][conf_item_key[0]]" :label="conf_item_key[2]" box type="password"></v-select>
- <v-text-field v-else v-model="conf.musicproviders[conf_key][conf_item_key[0]]" :label="conf_item_key[2]" box></v-text-field>
+ <v-switch v-if="typeof(conf_item_key[1]) == 'boolean'" v-model="conf.musicproviders[conf_key][conf_item_key[0]]" :label="$t(conf_item_key[2])"></v-switch>
+ <v-text-field v-else-if="conf_item_key[1] == '<password>'" v-model="conf.musicproviders[conf_key][conf_item_key[0]]" :label="$t(conf_item_key[2])" box type="password"></v-text-field>
+ <v-select v-else-if="conf_item_key[1] == '<player>'" v-model="conf.musicproviders[conf_key][conf_item_key[0]]" :label="$t(conf_item_key[2])" box type="password"></v-select>
+ <v-text-field v-else v-model="conf.musicproviders[conf_key][conf_item_key[0]]" :label="$t(conf_item_key[2])" box></v-text-field>
</v-list-tile>
</div>
<v-divider></v-divider>
<template v-slot:activator>
<v-list-tile>
<v-list-tile-content>
- <v-list-tile-title>Player Providers</v-list-tile-title>
+ <v-list-tile-title>{{ $t('player_providers') }}</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</template>
<div v-for="conf_item_key in conf.playerproviders[conf_key].__desc__">
<v-list-tile>
- <v-switch v-if="typeof(conf_item_key[1]) == 'boolean'" v-model="conf.playerproviders[conf_key][conf_item_key[0]]" :label="conf_item_key[2]"></v-switch>
- <v-text-field v-else-if="conf_item_key[1] == '<password>'" v-model="conf.playerproviders[conf_key][conf_item_key[0]]" :label="conf_item_key[2]" box type="password"></v-text-field>
- <v-select v-else-if="conf_item_key[1] == '<player>'" v-model="conf.playerproviders[conf_key][conf_item_key[0]]" :label="conf_item_key[2]" box type="password"></v-select>
- <v-text-field v-else v-model="conf.playerproviders[conf_key][conf_item_key[0]]" :label="conf_item_key[2]" box></v-text-field>
+ <v-switch v-if="typeof(conf_item_key[1]) == 'boolean'" v-model="conf.playerproviders[conf_key][conf_item_key[0]]" :label="$t(conf_item_key[2])"></v-switch>
+ <v-text-field v-else-if="conf_item_key[1] == '<password>'" v-model="conf.playerproviders[conf_key][conf_item_key[0]]" :label="$t(conf_item_key[2])" box type="password"></v-text-field>
+ <v-select v-else-if="conf_item_key[1] == '<player>'" v-model="conf.playerproviders[conf_key][conf_item_key[0]]" :label="$t(conf_item_key[2])" box type="password"></v-select>
+ <v-text-field v-else v-model="conf.playerproviders[conf_key][conf_item_key[0]]" :label="$t(conf_item_key[2])" box></v-text-field>
</v-list-tile>
</div>
<v-divider></v-divider>
<template v-slot:activator>
<v-list-tile>
<v-list-tile-content>
- <v-list-tile-title>Player settings</v-list-tile-title>
+ <v-list-tile-title>{{ $t('player_settings') }}</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</template>
<div v-for="conf_item_key in conf.player_settings.__desc__" v-if="conf.player_settings[key].enabled">
<v-list-tile>
- <v-switch v-if="typeof(conf_item_key[1]) == 'boolean'" v-model="conf.player_settings[key][conf_item_key[0]]" :label="conf_item_key[2]"></v-switch>
- <v-text-field v-else-if="conf_item_key[1] == '<password>'" v-model="conf.player_settings[key][conf_item_key[0]]" :label="conf_item_key[2]" box type="password"></v-text-field>
- <v-select v-else-if="conf_item_key[1] == '<player>'" v-model="conf.player_settings[key][conf_item_key[0]]" :label="conf_item_key[2]"
+ <v-switch v-if="typeof(conf_item_key[1]) == 'boolean'" v-model="conf.player_settings[key][conf_item_key[0]]" :label="$t(conf_item_key[2])"></v-switch>
+ <v-text-field v-else-if="conf_item_key[1] == '<password>'" v-model="conf.player_settings[key][conf_item_key[0]]" :label="$t(conf_item_key[2])" box type="password"></v-text-field>
+ <v-select v-else-if="conf_item_key[1] == '<player>'" v-model="conf.player_settings[key][conf_item_key[0]]" :label="$t(conf_item_key[2])"
:items="playersLst"
item-text="name"
item-value="id" box>
</v-select>
- <v-text-field v-else v-model="conf.player_settings[key][conf_item_key[0]]" :label="conf_item_key[2]" box></v-text-field>
+ <v-text-field v-else v-model="conf.player_settings[key][conf_item_key[0]]" :label="$t(conf_item_key[2])" box></v-text-field>
</v-list-tile>
<v-list-tile v-if="!conf.player_settings[key].enabled">
- <v-switch v-model="conf.player_settings[key].enabled" label="Enabled"></v-switch>
+ <v-switch v-model="conf.player_settings[key].enabled" :label="$t('enabled')"></v-switch>
</v-list-tile>
</div>
<div v-if="!conf.player_settings[key].enabled">
<v-list-tile>
- <v-switch v-model="conf.player_settings[key].enabled" label="Enabled"></v-switch>
+ <v-switch v-model="conf.player_settings[key].enabled" :label="$t('enabled')"></v-switch>
</v-list-tile>
</div>
<v-divider></v-divider>
},
created() {
- this.$globals.windowtitle = "Configuration";
+ this.$globals.windowtitle = this.$t('settings');
this.getPlayers();
this.getConfig();
console.log(this.$globals.all_players);
var home = Vue.component("Home", {
template: `
<section>
- <v-flex xs12 justify-center>
- <v-card color="cyan darken-2" class="white--text" img="../images/info_gradient.jpg">
-
- <div class="text-xs-center" style="height:40px" id="whitespace_top"/>
- <v-card-title class="display-1 justify-center" style="text-shadow: 1px 1px #000000;">
- Music Assistant
- </v-card-title>
- </v-card>
- </v-flex>
<v-list>
<v-list-tile
v-for="item in items" :key="item.title" @click="$router.push(item.path)">
};
},
created() {
- this.$globals.windowtitle = "Home"
+ this.$globals.windowtitle = this.$t('home');
this.items= [
- { title: "Artists", icon: "person", path: "/artists" },
- { title: "Albums", icon: "album", path: "/albums" },
- { title: "Tracks", icon: "audiotrack", path: "/tracks" },
- { title: "Playlists", icon: "playlist_play", path: "/playlists" },
- { title: "Search", icon: "search", path: "/search" }
+ { title: this.$t('artists'), icon: "person", path: "/artists" },
+ { title: this.$t('albums'), icon: "album", path: "/albums" },
+ { title: this.$t('tracks'), icon: "audiotrack", path: "/tracks" },
+ { title: this.$t('playlists'), icon: "playlist_play", path: "/playlists" },
+ { title: this.$t('search'), icon: "search", path: "/search" }
]
},
methods: {
}
},
created() {
- this.$globals.windowtitle = "Playlist info"
+ this.$globals.windowtitle = ""
this.getInfo();
this.getPlaylistTracks();
this.scroll(this.Browse);
var Queue = Vue.component('Queue', {
template: `
<section>
- <infoheader v-bind:info="info"/>
- <v-tabs
- v-model="active"
- color="transparent"
- light
- slider-color="black"
- >
- <v-tab ripple>Queue</v-tab>
- <v-tab-item>
- <v-card flat>
- <v-list two-line>
- <listviewItem
- v-for="(item, index) in items"
- v-bind:item="item"
- :key="item.db_id"
- :hideavatar="isMobile()"
- :hidetracknum="true"
- :hideproviders="isMobile()"
- :hidelibrary="isMobile()">
- </listviewItem>
- </v-list>
- </v-card>
- </v-tab-item>
- </v-tabs>
+ <v-list two-line>
+ <listviewItem
+ v-for="(item, index) in items"
+ v-bind:item="item"
+ :key="item.db_id"
+ :hideavatar="isMobile()"
+ :hidetracknum="true"
+ :hideproviders="isMobile()"
+ :hidelibrary="isMobile()">
+ </listviewItem>
+ </v-list>
</section>`,
props: ['player_id'],
data() {
}
},
created() {
- this.$globals.windowtitle = "Queue"
- //this.getInfo();
+ this.$globals.windowtitle = this.$t('queue')
this.getQueueTracks();
this.scroll(this.Queue);
},
var Search = Vue.component('Search', {
template: `
<section>
- <v-flex xs12 justify-center>
- <v-card color="cyan darken-2" class="white--text" img="../images/info_gradient.jpg">
-
- <div class="text-xs-center" style="height:40px" id="whitespace_top"/>
- <v-card-title class="display-1 justify-center" style="text-shadow: 1px 1px #000000;">
- {{ $globals.windowtitle }}
- </v-card-title>
- </v-card>
- </v-flex>
- <v-text-field
+
+ <v-text-field
solo
clearable
- label="Type here to search..."
+ :label="$t('type_to_search')"
prepend-inner-icon="search"
- v-on:input="onSearchBoxInput"
- v-model="searchquery">
+ v-model="searchQuery">
</v-text-field>
<v-tabs
slider-color="black"
>
- <v-tab ripple v-if="tracks.length">Tracks</v-tab>
+ <v-tab ripple v-if="tracks.length">{{ $t('tracks') }}</v-tab>
<v-tab-item v-if="tracks.length">
<v-card flat>
<v-list two-line style="margin-left:15px; margin-right:15px">
</v-card>
</v-tab-item>
- <v-tab ripple v-if="artists.length">Artists</v-tab>
+ <v-tab ripple v-if="artists.length">{{ $t('artists') }}</v-tab>
<v-tab-item v-if="artists.length">
<v-card flat>
<v-list two-line>
</v-card>
</v-tab-item>
- <v-tab ripple v-if="albums.length">Albums</v-tab>
+ <v-tab ripple v-if="albums.length">{{ $t('albums') }}</v-tab>
<v-tab-item v-if="albums.length">
<v-card flat>
<v-list two-line>
</v-card>
</v-tab-item>
- <v-tab ripple v-if="playlists.length">Playlists</v-tab>
+ <v-tab ripple v-if="playlists.length">{{ $t('playlists') }}</v-tab>
<v-tab-item v-if="playlists.length">
<v-card flat>
<v-list two-line>
</v-tabs>
</section>`,
- props: [],
+ props: ['searchQuery'],
data() {
return {
selected: [2],
tracks: [],
playlists: [],
timeout: null,
- searchquery: ''
}
},
created() {
- this.$globals.windowtitle = "Search";
+ this.$globals.windowtitle = this.$t('search');
+ this.Search();
+ },
+ watch: {
+ searchQuery () {
+ this.Search();
+ }
},
methods: {
toggle (index) {
console.log("selected: "+ this.items[index].name);
}
},
- onSearchBoxInput (index) {
- clearTimeout(this.timeout);
- this.timeout = setTimeout(this.Search, 600);
- },
Search () {
- if (!this.searchquery) {
- this.artists = [];
- this.albums = [];
- this.tracks = [];
- this.playlists = [];
- }
- else {
+ this.artists = [];
+ this.albums = [];
+ this.tracks = [];
+ this.playlists = [];
+ if (this.searchQuery) {
this.$globals.loading = true;
- console.log(this.searchquery);
+ console.log(this.searchQuery);
const api_url = '/api/search'
console.log('loading ' + api_url);
axios
.get(api_url, {
params: {
- query: this.searchquery,
+ query: this.searchQuery,
online: true,
limit: 3
}
--- /dev/null
+const messages = {
+
+
+ en: {
+ // generic strings
+ musicassistant: "Music Assistant",
+ home: "Home",
+ artists: "Artists",
+ albums: "Albums",
+ tracks: "Tracks",
+ playlists: "Playlists",
+ search: "Search",
+ settings: "Settings",
+ queue: "Queue",
+ generic_settings: "Generic settings",
+ music_providers: "Music providers",
+ player_providers: "Player providers",
+ player_settings: "Player settings",
+ type_to_search: "Type here to search...",
+ enabled: "Enabled",
+ // settings strings
+ username: "Username",
+ password: "Password",
+ hostname: "Hostname (or IP)",
+ port: "Port",
+ hass_url: "URL to homeassistant (e.g. https://homeassistant:8123)",
+ hass_token: "Long Lived Access Token",
+ hass_publish: "Publish players to Home Assistant",
+ hass_player_power: "Attach player power to homeassistant entity",
+ hass_player_source: "Source on the homeassistant entity (optional)",
+ hass_player_volume: "Attach player volume to homeassistant entity",
+ web_ssl_cert: "Path to ssl certificate file",
+ web_ssl_key: "Path to ssl keyfile",
+ web_ssl_host: "Hostname (FQDN used in the certificate)",
+ player_enabled: "Enable player",
+ player_name: "Custom name for this player",
+ player_group_with: "Group this player to another (parent)player",
+ player_mute_power: "Use muting as power control",
+ player_disable_vol: "Disable volume controls",
+ player_group_vol: "Apply group volume to childs (for group players only)",
+ player_group_pow: "Apply group power based on childs (for group players only)",
+ player_power_play: "Issue play command on power on",
+ file_prov_music_path: "Path to music files",
+ file_prov_playlists_path: "Path to playlists (.m3u)",
+
+ },
+
+ nl: {
+ // generic strings
+ musicassistant: "Music Assistant",
+ home: "Home",
+ artists: "Artiesten",
+ albums: "Albums",
+ tracks: "Nummers",
+ playlists: "Afspeellijsten",
+ search: "Zoeken",
+ settings: "Instellingen",
+ queue: "Wachtrij",
+ generic_settings: "Algemene instellingen",
+ music_providers: "Muziek providers",
+ player_providers: "Speler providers",
+ player_settings: "Speler instellingen",
+ enabled: "Ingeschakeld",
+ type_to_search: "Type hier om te zoeken...",
+ // settings strings
+ username: "Gebruikersnaam",
+ password: "Wachtwoord",
+ hostname: "Hostnaam (of IP)",
+ port: "Poort",
+ hass_url: "URL naar homeassistant (b.v. https://homeassistant:8123)",
+ hass_token: "Token met lange levensduur",
+ hass_publish: "Publiceer spelers naar Home Assistant",
+ hass_player_power: "Verbind speler aan/uit met homeassistant entity",
+ hass_player_source: "Benodigde bron op de verbonden homeassistant entity (optioneel)",
+ hass_player_volume: "Verbind volume van speler aan een homeassistant entity",
+ web_ssl_cert: "Pad naar ssl certificaat bestand",
+ web_ssl_key: "Pad naar ssl certificaat key bestand",
+ web_ssl_host: "Hostname (FQDN van certificaat)",
+ player_enabled: "Speler inschakelen",
+ player_name: "Aangepaste naam voor deze speler",
+ player_group_with: "Groupeer deze speler met een andere (hoofd)speler",
+ player_mute_power: "Gebruik mute als aan/uit",
+ player_disable_vol: "Schakel volume bediening helemaal uit",
+ player_group_vol: "Pas groep volume toe op onderliggende spelers (alleen groep spelers)",
+ player_group_pow: "Pas groep aan/uit toe op onderliggende spelers (alleen groep spelers)",
+ player_power_play: "Automatisch afspelen bij inschakelen",
+ file_prov_music_path: "Pad naar muziek bestanden",
+ file_prov_playlists_path: "Pad naar playlist bestanden (.m3u)",
+ }
+}
\ No newline at end of file