├── app ├── dist │ └── .gitkeep ├── src │ ├── lib │ │ ├── player.js │ │ └── Database.js │ ├── components │ │ ├── PlayerView │ │ │ ├── assets │ │ │ │ └── logo.png │ │ │ ├── Versions.vue │ │ │ ├── Bezel.vue │ │ │ ├── Infopane.vue │ │ │ ├── Visualizer.vue │ │ │ ├── AudioElement.vue │ │ │ └── Controls.vue │ │ ├── PlayerView.vue │ │ ├── ListView.vue │ │ ├── ListView │ │ │ └── StationList.vue │ │ └── WindowControls │ │ │ └── WindowControls.vue │ ├── assets │ │ └── images │ │ │ ├── show-icon.svg │ │ │ ├── volume-icon.svg │ │ │ ├── feed-icon.svg │ │ │ ├── fire-icon.svg │ │ │ ├── download-icon.svg │ │ │ ├── quality-icon.svg │ │ │ ├── play-icon.svg │ │ │ └── pause-icon.svg │ ├── main.js │ ├── scss │ │ └── settings.scss │ ├── App.vue │ └── store │ │ └── store.js ├── icons │ ├── icon.icns │ └── icon.ico ├── index.ejs ├── package.json └── electron.js ├── .babelrc ├── screenshots └── player-screen.png ├── .gitignore ├── tasks ├── vuex │ ├── module.template.txt │ └── module.js ├── release.js └── runner.js ├── .snyk ├── README.md ├── config.js ├── package.json └── webpack.config.js /app/dist/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/src/lib/player.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/icons/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pixelspring/RadioSpring/HEAD/app/icons/icon.icns -------------------------------------------------------------------------------- /app/icons/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pixelspring/RadioSpring/HEAD/app/icons/icon.ico -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-0"], 3 | "plugins": ["transform-runtime"] 4 | } 5 | -------------------------------------------------------------------------------- /screenshots/player-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pixelspring/RadioSpring/HEAD/screenshots/player-screen.png -------------------------------------------------------------------------------- /app/src/components/PlayerView/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pixelspring/RadioSpring/HEAD/app/src/components/PlayerView/assets/logo.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | app/dist/index.html 3 | app/dist/build.js 4 | builds/* 5 | node_modules 6 | npm-debug.log 7 | npm-debug.log.* 8 | thumbs.db 9 | !.gitkeep 10 | -------------------------------------------------------------------------------- /tasks/vuex/module.template.txt: -------------------------------------------------------------------------------- 1 | import {} from '../mutation-types' 2 | 3 | const state = { 4 | all: [] 5 | } 6 | 7 | const mutations = { 8 | 9 | } 10 | 11 | export default { 12 | state, 13 | mutations 14 | } 15 | -------------------------------------------------------------------------------- /app/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | <%= htmlWebpackPlugin.options.title %> 6 | 7 | 8 |
9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/assets/images/show-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/assets/images/volume-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/assets/images/feed-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/assets/images/fire-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/assets/images/download-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/assets/images/quality-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.snyk: -------------------------------------------------------------------------------- 1 | # Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. 2 | version: v1.12.0 3 | ignore: {} 4 | # patches apply the minimum changes required to fix a vulnerability 5 | patch: 6 | 'npm:lodash:20180130': 7 | - node-internet-radio > lodash: 8 | patched: '2018-07-03T03:10:43.806Z' 9 | -------------------------------------------------------------------------------- /app/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Electron from 'vue-electron' 3 | import Resource from 'vue-resource' 4 | 5 | Vue.use(Electron) 6 | Vue.use(Resource) 7 | Vue.config.debug = true 8 | 9 | import App from './App' 10 | import store from './store/store' 11 | 12 | /* eslint-disable no-new */ 13 | new Vue({ 14 | ...App 15 | }).$mount('#app') 16 | -------------------------------------------------------------------------------- /app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "radiospring", 3 | "version": "0.0.0", 4 | "description": "Internet radio player app", 5 | "main": "electron.js", 6 | "dependencies": { 7 | "vue": "^2.0.1", 8 | "vue-electron": "^1.0.0", 9 | "vue-resource": "^1.0.3", 10 | "vuex": "^2.0.0" 11 | }, 12 | "devDependencies": {}, 13 | "author": "Mike Seaby " 14 | } 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RadioSpring 2 | 3 | ![RadioSpring](http://i.imgur.com/yJVXs6r.png) 4 | 5 | > Internet radio player app, built with Vue and Electron 6 | 7 | ## Build Setup 8 | 9 | ``` bash 10 | # install dependencies 11 | npm install 12 | 13 | # serve with hot reload at localhost:9080 14 | npm run dev 15 | 16 | # build electron app for production 17 | npm run build 18 | 19 | # run webpack in production 20 | npm run pack 21 | ``` -------------------------------------------------------------------------------- /app/src/components/PlayerView/Versions.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 19 | -------------------------------------------------------------------------------- /tasks/vuex/module.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const fs = require('fs') 4 | const path = require('path') 5 | 6 | let moduleName = process.argv[2] 7 | let template = fs.readFileSync( 8 | path.join(__dirname, 'module.template.txt'), 9 | 'utf8' 10 | ) 11 | 12 | fs.writeFileSync( 13 | path.join(__dirname, `../../app/src/vuex/modules/${moduleName}.js`), 14 | template 15 | ) 16 | 17 | console.log(`\n\x1b[33m[vuex]\x1b[0m module "${moduleName}" has been created`) 18 | console.log(path.join(__dirname, `../../app/src/vuex/modules/${moduleName}.js`)) 19 | -------------------------------------------------------------------------------- /app/src/lib/Database.js: -------------------------------------------------------------------------------- 1 | 2 | var Dexie = require('dexie'); 3 | var db = new Dexie('radiospringdb'); 4 | 5 | db.version(1).stores({ 6 | stations: "++id,title,genre,desc,streamurl,bitrate" 7 | }); 8 | 9 | // 10 | // Manipulate and Query Database 11 | // 12 | /* 13 | db.stations.add({title: "Sample Station", genre: "PsyTrance", streamurl: "http://teststream.com"}).then(function() { 14 | return db.stations.where("age").below(25).toArray(); 15 | }).then(function (youngFriends) { 16 | alert ("My young friends: " + JSON.stringify(youngFriends)); 17 | }).catch(function (e) { 18 | alert ("Error: " + (e.stack || e)); 19 | }); 20 | */ 21 | 22 | db.stations.add({title: "Sample Station", genre: "PsyTrance", streamurl: "http://teststream.com"}) -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const path = require('path') 4 | 5 | let config = { 6 | // Name of electron app 7 | // Will be used in production builds 8 | name: 'RadioSpring', 9 | 10 | // webpack-dev-server port 11 | port: 9080, 12 | 13 | // electron-packager options 14 | // Docs: https://simulatedgreg.gitbooks.io/electron-vue/content/docs/building_your_app.html 15 | building: { 16 | arch: 'x64', 17 | asar: true, 18 | dir: path.join(__dirname, 'app'), 19 | icon: path.join(__dirname, 'app/icons/icon'), 20 | ignore: /\b(node_modules|src|index\.ejs|icons)\b/, 21 | out: path.join(__dirname, 'builds'), 22 | overwrite: true, 23 | platform: process.env.PLATFORM_TARGET || 'all' 24 | } 25 | } 26 | 27 | config.building.name = config.name 28 | 29 | module.exports = config 30 | -------------------------------------------------------------------------------- /app/src/scss/settings.scss: -------------------------------------------------------------------------------- 1 | 2 | // Vars: 3 | $body-text-color: #B1BCCF; 4 | $bg-color: #292E33; 5 | 6 | $active-color: #1eaedb; 7 | 8 | // Dimensions: 9 | $bezel-height: 44px; 10 | 11 | // Bezel: 12 | $bezel-text-color: #60A5DF; //#74A9FC; 13 | 14 | 15 | // Buttons/Controls: 16 | $control-bg-color: black; 17 | $control-color: white; 18 | $control-radius: 4px; 19 | 20 | 21 | // Scrollbars: 22 | $scrollbar-width: 4px; 23 | $scrollbar-bg: black; 24 | $scrollbar-color: #1eaedb; 25 | 26 | 27 | // ListView: 28 | $listcontainer-bg: #4A4A4A; 29 | 30 | 31 | @mixin hideOverflowText { 32 | white-space: nowrap; 33 | overflow: hidden; 34 | text-overflow: ellipsis; 35 | } 36 | 37 | @mixin fadeTransition { 38 | .fade-enter-active, .fade-leave-active { 39 | transition: opacity .5s 40 | } 41 | .fade-enter, .fade-leave-active { 42 | opacity: 0 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/components/PlayerView.vue: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 24 | 25 | 26 | 27 | 39 | -------------------------------------------------------------------------------- /app/src/components/PlayerView/Bezel.vue: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 26 | 27 | -------------------------------------------------------------------------------- /tasks/release.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const exec = require('child_process').exec 4 | const packager = require('electron-packager') 5 | 6 | if (process.env.PLATFORM_TARGET === 'clean') { 7 | require('del').sync(['builds/*', '!.gitkeep']) 8 | console.log('\x1b[33m`builds` directory cleaned.\n\x1b[0m') 9 | } else pack() 10 | 11 | /** 12 | * Build webpack in production 13 | */ 14 | function pack () { 15 | console.log('\x1b[33mBuilding webpack in production mode...\n\x1b[0m') 16 | let pack = exec('npm run pack') 17 | 18 | pack.stdout.on('data', data => console.log(data)) 19 | pack.stderr.on('data', data => console.error(data)) 20 | pack.on('exit', code => build()) 21 | } 22 | 23 | /** 24 | * Use electron-packager to build electron app 25 | */ 26 | function build () { 27 | let options = require('../config').building 28 | 29 | console.log('\x1b[34mBuilding electron app(s)...\n\x1b[0m') 30 | packager(options, (err, appPaths) => { 31 | if (err) { 32 | console.error('\x1b[31mError from `electron-packager` when building app...\x1b[0m') 33 | console.error(err) 34 | } else { 35 | console.log('Build(s) successful!') 36 | console.log(appPaths) 37 | 38 | console.log('\n\x1b[34mDONE\n\x1b[0m') 39 | } 40 | }) 41 | } 42 | -------------------------------------------------------------------------------- /app/src/assets/images/play-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/assets/images/pause-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/components/ListView.vue: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 25 | 26 | 27 | 28 | 70 | -------------------------------------------------------------------------------- /app/electron.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const electron = require('electron') 4 | const path = require('path') 5 | const app = electron.app 6 | const BrowserWindow = electron.BrowserWindow 7 | 8 | let mainWindow 9 | let config = {} 10 | 11 | if (process.env.NODE_ENV === 'development') { 12 | config = require('../config') 13 | config.url = `http://localhost:${config.port}` 14 | } else { 15 | config.devtron = false 16 | config.url = `file://${__dirname}/dist/index.html` 17 | } 18 | 19 | function createWindow () { 20 | /** 21 | * Initial window options 22 | */ 23 | mainWindow = new BrowserWindow({ 24 | width: 400, 25 | height: 53, 26 | minHeight: 53, 27 | minWidth: 370, 28 | fullscreenable: false, 29 | maximizable: false, 30 | backgroundColor: '#292E33', 31 | //titleBarStyle: "hidden", 32 | frame: false, 33 | title: "RadioSpring", 34 | "web-preferences": { 35 | //"web-security": false 36 | scrollBounce: true 37 | } 38 | }) 39 | 40 | mainWindow.loadURL(config.url) 41 | 42 | if (process.env.NODE_ENV === 'development') { 43 | BrowserWindow.addDevToolsExtension(path.join(__dirname, '../node_modules/devtron')) 44 | 45 | let installExtension = require('electron-devtools-installer') 46 | 47 | installExtension.default(installExtension.VUEJS_DEVTOOLS) 48 | //.then((name) => mainWindow.webContents.openDevTools()) 49 | .catch((err) => console.log('An error occurred: ', err)) 50 | } 51 | 52 | mainWindow.on('closed', () => { 53 | mainWindow = null 54 | }) 55 | 56 | console.log('mainWindow opened') 57 | } 58 | 59 | app.on('ready', createWindow) 60 | 61 | app.on('window-all-closed', () => { 62 | if (process.platform !== 'darwin') { 63 | app.quit() 64 | } 65 | }) 66 | 67 | app.on('activate', () => { 68 | if (mainWindow === null) { 69 | createWindow() 70 | } 71 | }) 72 | -------------------------------------------------------------------------------- /tasks/runner.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Credits to https://github.com/bradstewart/electron-boilerplate-vue/blob/master/build/dev-runner.js 3 | */ 4 | 'use strict' 5 | 6 | const config = require('../config') 7 | const exec = require('child_process').exec 8 | const treeKill = require('tree-kill') 9 | 10 | let YELLOW = '\x1b[33m' 11 | let BLUE = '\x1b[34m' 12 | let END = '\x1b[0m' 13 | 14 | let isElectronOpen = false 15 | 16 | function format (command, data, color) { 17 | return color + command + END + 18 | ' ' + // Two space offset 19 | data.toString().trim().replace(/\n/g, '\n' + repeat(' ', command.length + 2)) + 20 | '\n' 21 | } 22 | 23 | function repeat (str, times) { 24 | return (new Array(times + 1)).join(str) 25 | } 26 | 27 | let children = [] 28 | 29 | function run (command, color, name) { 30 | let child = exec(command) 31 | 32 | child.stdout.on('data', data => { 33 | console.log(format(name, data, color)) 34 | 35 | /** 36 | * Start electron after VALID build 37 | * (prevents electron from opening a blank window that requires refreshing) 38 | * 39 | * NOTE: needs more testing for stability 40 | */ 41 | if (/VALID/g.test(data.toString().trim().replace(/\n/g, '\n' + repeat(' ', command.length + 2))) && !isElectronOpen) { 42 | console.log(`${BLUE}Starting electron...\n${END}`) 43 | run('cross-env NODE_ENV=development electron app/electron.js', BLUE, 'electron') 44 | isElectronOpen = true 45 | } 46 | }) 47 | 48 | child.stderr.on('data', data => console.error(format(name, data, color))) 49 | child.on('exit', code => exit(code)) 50 | 51 | children.push(child) 52 | } 53 | 54 | function exit (code) { 55 | children.forEach(child => { 56 | treeKill(child.pid) 57 | }) 58 | } 59 | 60 | console.log(`${YELLOW}Starting webpack-dev-server...\n${END}`) 61 | run(`webpack-dev-server --inline --hot --colors --port ${config.port} --content-base app/dist`, YELLOW, 'webpack') 62 | -------------------------------------------------------------------------------- /app/src/App.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "radiospring", 3 | "version": "0.0.1", 4 | "description": "Internet radio player app", 5 | "scripts": { 6 | "build": "node tasks/release.js", 7 | "build:clean": "cross-env PLATFORM_TARGET=clean node tasks/release.js", 8 | "build:darwin": "cross-env PLATFORM_TARGET=darwin node tasks/release.js", 9 | "build:linux": "cross-env PLATFORM_TARGET=linux node tasks/release.js", 10 | "build:mas": "cross-env PLATFORM_TARGET=mas node tasks/release.js", 11 | "build:win32": "cross-env PLATFORM_TARGET=win32 node tasks/release.js", 12 | "dev": "node tasks/runner.js", 13 | "pack": "cross-env NODE_ENV=production webpack -p --progress --colors", 14 | "vuex:module": "node tasks/vuex/module.js", 15 | "postinstall": "cd app && npm install", 16 | "snyk-protect": "snyk protect", 17 | "prepare": "npm run snyk-protect" 18 | }, 19 | "author": "Mike Seaby ", 20 | "license": "MIT", 21 | "devDependencies": { 22 | "babel-core": "^6.8.0", 23 | "babel-loader": "^6.2.4", 24 | "babel-plugin-transform-runtime": "^6.8.0", 25 | "babel-preset-es2015": "^6.6.0", 26 | "babel-preset-stage-0": "^6.5.0", 27 | "babel-runtime": "^6.6.1", 28 | "cross-env": "^1.0.7", 29 | "css-loader": "^0.23.1", 30 | "del": "^2.2.1", 31 | "devtron": "^1.1.0", 32 | "electron": "^1.3.1", 33 | "electron-devtools-installer": "^1.1.4", 34 | "electron-packager": "^8.0.0", 35 | "electron-rebuild": "^1.1.3", 36 | "extract-text-webpack-plugin": "^1.0.1", 37 | "file-loader": "^0.8.5", 38 | "html-webpack-plugin": "^2.16.1", 39 | "json-loader": "^0.5.4", 40 | "node-sass": "^3.11.2", 41 | "sass-loader": "^4.0.2", 42 | "style-loader": "^0.13.1", 43 | "tree-kill": "^1.1.0", 44 | "url-loader": "^0.5.7", 45 | "vue-hot-reload-api": "^1.3.2", 46 | "vue-html-loader": "^1.2.2", 47 | "vue-loader": "^9.5.1", 48 | "vue-style-loader": "^1.0.0", 49 | "webpack": "^1.13.0", 50 | "webpack-dev-server": "^1.14.1" 51 | }, 52 | "dependencies": { 53 | "dexie": "^1.5.1", 54 | "node-internet-radio": "^0.1.4", 55 | "snyk": "^1.88.0" 56 | }, 57 | "snyk": true 58 | } 59 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const path = require('path') 4 | const pkg = require('./app/package.json') 5 | const settings = require('./config.js') 6 | const webpack = require('webpack') 7 | 8 | const ExtractTextPlugin = require('extract-text-webpack-plugin') 9 | const HtmlWebpackPlugin = require('html-webpack-plugin') 10 | 11 | let config = { 12 | devtool: '#eval-source-map', 13 | entry: { 14 | build: path.join(__dirname, 'app/src/main.js') 15 | }, 16 | module: { 17 | loaders: [ 18 | { 19 | test: /\.css$/, 20 | loader: ExtractTextPlugin.extract('style-loader', 'css-loader') 21 | }, 22 | { 23 | test: /\.html$/, 24 | loader: 'vue-html-loader' 25 | }, 26 | { 27 | test: /\.js$/, 28 | loader: 'babel-loader', 29 | exclude: /node_modules/ 30 | }, 31 | { 32 | test: /\.json$/, 33 | loader: 'json-loader' 34 | }, 35 | { 36 | test: /\.vue$/, 37 | loader: 'vue-loader' 38 | }, 39 | { 40 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 41 | loader: 'url-loader', 42 | query: { 43 | limit: 10000, 44 | name: 'imgs/[name].[hash:7].[ext]' 45 | } 46 | }, 47 | { 48 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 49 | loader: 'url-loader', 50 | query: { 51 | limit: 10000, 52 | name: 'fonts/[name].[hash:7].[ext]' 53 | } 54 | } 55 | ] 56 | }, 57 | plugins: [ 58 | new ExtractTextPlugin('styles.css'), 59 | new HtmlWebpackPlugin({ 60 | filename: 'index.html', 61 | template: './app/index.ejs', 62 | title: settings.name 63 | }), 64 | new webpack.NoErrorsPlugin() 65 | ], 66 | output: { 67 | filename: '[name].js', 68 | path: path.join(__dirname, 'app/dist') 69 | }, 70 | resolve: { 71 | alias: { 72 | 'components': path.join(__dirname, 'app/src/components'), 73 | 'src': path.join(__dirname, 'app/src') 74 | }, 75 | extensions: ['', '.js', '.vue', '.json', '.css'], 76 | fallback: [path.join(__dirname, 'app/node_modules')] 77 | }, 78 | resolveLoader: { 79 | root: path.join(__dirname, 'node_modules') 80 | }, 81 | target: 'electron-renderer', 82 | vue: { 83 | loaders: { 84 | sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax=1', 85 | scss: 'vue-style-loader!css-loader!sass-loader' 86 | } 87 | } 88 | } 89 | 90 | /** 91 | * Adjust config for production settings 92 | */ 93 | if (process.env.NODE_ENV === 'production') { 94 | config.devtool = '' 95 | 96 | config.plugins.push( 97 | new webpack.DefinePlugin({ 98 | 'process.env.NODE_ENV': '"production"' 99 | }), 100 | new webpack.optimize.OccurenceOrderPlugin(), 101 | new webpack.optimize.UglifyJsPlugin({ 102 | compress: { 103 | warnings: false 104 | } 105 | }) 106 | ) 107 | } 108 | 109 | module.exports = config 110 | -------------------------------------------------------------------------------- /app/src/components/PlayerView/Infopane.vue: -------------------------------------------------------------------------------- 1 | 2 | 23 | 24 | 62 | 63 | -------------------------------------------------------------------------------- /app/src/store/store.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | 4 | Vue.use(Vuex) 5 | 6 | export default new Vuex.Store({ 7 | 8 | state: { 9 | streams: [ 10 | { 11 | name: 'Philosomatika', 12 | url: 'http://streaming.radionomy.com/-PHILOSOMATIKA-', 13 | web: 'http://philosomatika.com/', 14 | }, 15 | 16 | { 17 | name: 'Philosomatika Progressive', 18 | url: 'http://streaming.radionomy.com/PHILOSOMATIKA-PROGRESSIVE', 19 | web: 'http://philosomatika.com/', 20 | }, 21 | 22 | { 23 | name: 'Radio Bloodstream', 24 | url: 'http://uk1.internet-radio.com:8294/live', 25 | web: 'http://website.com/', 26 | }, 27 | 28 | { 29 | name: 'Rockhard Lossless', 30 | url: 'http://95.211.162.73:8000/;', 31 | web: 'http://website.com/', 32 | }, 33 | 34 | { 35 | name: 'CLASSIC METAL RADIO', 36 | url: 'http://192.99.62.212:9904/stream', 37 | web: 'http://website.com/', 38 | }, 39 | 40 | { 41 | name: 'NSB RADIO', 42 | url: 'http://65.23.157.233:7904/;', 43 | web: 'http://website.com/', 44 | }, 45 | 46 | { 47 | name: 'RockLive Radio', 48 | url: 'http://46.4.77.21:27815/;', 49 | web: 'http://website.com/', 50 | }, 51 | 52 | { 53 | name: 'Drum Basement', 54 | url: 'http://188.165.232.7:8789/;', 55 | web: 'http://website.com/', 56 | }, 57 | 58 | { 59 | name: 'Pure FM Prog', 60 | url: 'http://212.7.196.96:8000/;', 61 | web: 'http://website.com/', 62 | } 63 | 64 | ], 65 | //volumeSlider:'1', 66 | currentvolume: '1', 67 | playToggleText: '▶', 68 | playstatus: 0, 69 | bufferstatus: 0, 70 | 71 | currentstreamurl: '', 72 | currentstation: 'Pick a station', 73 | currentstationdesc: undefined, 74 | currenttrack: 'Not Playing', 75 | currentbitrate: undefined, 76 | }, 77 | 78 | mutations: { 79 | //updatecurrentstation: state => state.stationname, 80 | 81 | //updatecurrenttrack: state => state.currenttrack, 82 | 83 | updatecurrentstreamurl (state, payload) { 84 | state.currentstreamurl = payload.newstreamurl 85 | }, 86 | 87 | updatecurrentstation (state, payload) { 88 | state.currentstation = payload.newstation 89 | }, 90 | 91 | updatecurrentstationdesc (state, payload) { 92 | state.currentstationdesc = payload.newstationdesc 93 | }, 94 | 95 | updatecurrenttrack (state, payload) { 96 | state.currenttrack = payload.newtrack 97 | }, 98 | 99 | updatecurrentbitrate(state, payload) { 100 | state.currentbitrate = payload.newbitrate 101 | }, 102 | 103 | updatevolume (state, payload) { 104 | state.currentvolume = payload.newvolume 105 | }, 106 | 107 | updateplaystatus (state, payload) { 108 | state.playstatus = payload.newplaystatus 109 | }, 110 | 111 | updatebufferstatus (state, payload) { 112 | state.bufferstatus = payload.newbufferstatus 113 | } 114 | }, 115 | 116 | actions: { 117 | // 118 | }, 119 | 120 | getters: { 121 | // 122 | } 123 | 124 | }) 125 | -------------------------------------------------------------------------------- /app/src/components/PlayerView/Visualizer.vue: -------------------------------------------------------------------------------- 1 | 2 | 26 | 27 | 47 | 48 | -------------------------------------------------------------------------------- /app/src/components/ListView/StationList.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 86 | 87 | 88 | 89 | 165 | -------------------------------------------------------------------------------- /app/src/components/PlayerView/AudioElement.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 147 | 148 | 157 | -------------------------------------------------------------------------------- /app/src/components/WindowControls/WindowControls.vue: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 50 | 51 | 193 | -------------------------------------------------------------------------------- /app/src/components/PlayerView/Controls.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 | 110 | 111 | --------------------------------------------------------------------------------