├── .gitignore ├── LICENSE ├── README.md ├── assets ├── assets.js ├── assets.min.js └── style.css ├── go-player.exe ├── go-player.go ├── index.html └── screenshot.png /.gitignore: -------------------------------------------------------------------------------- 1 | *.mp3 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Patrick D. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | GO-PLAYER 2 | ========= 3 | 4 | a web-based html5 music player 5 | 6 | [](https://circleci.com/gh/patdhlk/go-player) 7 | 8 | go-player serves the all files in the music directory. It's not recommended to use it outside 9 | your local network because there is currently no security and authentication implemented. 10 | 11 | build 12 | -------- 13 | 14 | use http://gobuild.io/ to build the server for your plattform. 15 | 16 | creat a directory for the player...lets call it go-player on your machine and put the built file in this folder. 17 | copy the 'index.html' file and the complete 'assets' folder to this directory. 18 | In this dir. you have to create a subdirectory called music (go-player/music), in this directory you can put your complete music. 19 | 20 | Now run the application, maybe (on Windows) "go-player.exe", and move to your browser and visit localhost:8080, then listen to your music 21 | 22 | screenshot 23 | ---------- 24 |  25 | 26 | license 27 | --------- 28 | 29 | THE MIT LICENSE 30 | 31 | 32 | -------------------------------------------------------------------------------- /assets/assets.js: -------------------------------------------------------------------------------- 1 | var root = "/f/"; 2 | var path = []; 3 | var cache = {}; 4 | 5 | function init() { 6 | load(path); 7 | $('#player').bind('ended', next); 8 | $('#addall').click(addAll); 9 | $('#next').click(next); 10 | } 11 | 12 | function load(path) { 13 | var url = root+path.join('/'); 14 | if (typeof cache[url] != "undefined") { 15 | populate(cache[url]); 16 | return; 17 | } 18 | $.ajax({ 19 | url: url, 20 | dataType: "json", 21 | success: function(data) { 22 | populate(data) 23 | cache[url] = data; 24 | } 25 | }); 26 | } 27 | 28 | function populate(files) { 29 | var $b = $('#browser').empty(); 30 | function add(i, f) { 31 | if (f.Name[0] == '.' || f.Name[0] == ':') return; 32 | var dir = f.IsDir; 33 | var cl = dir ? "dir" : "file"; 34 | f.Path = path.join('/'); 35 | $('').text(f.Name).data('file', f) 36 | .addClass(cl).appendTo($b) 37 | .click(dir?clickDir:clickFile); 38 | } 39 | files.sort(function(a, b) { 40 | a = a.Name.toLowerCase(); 41 | b = b.Name.toLowerCase(); 42 | if (a > b) return 1; 43 | if (a < b) return -1; 44 | return 0; 45 | }); 46 | $b.append(up()); 47 | $.each(files, add); 48 | } 49 | 50 | function up() { 51 | return $('..').click(function() { 52 | path.pop(); 53 | load(path); 54 | }); 55 | } 56 | 57 | function clickDir(e) { 58 | path.push($(e.target).data('file').Name); 59 | load(path); 60 | } 61 | function clickFile(e) { 62 | addToPlaylist($(e.target).data('file')); 63 | } 64 | 65 | function addToPlaylist(f) { 66 | var $p = $('#playlist'); 67 | var playnow = ($p.find('a').length == 0); 68 | var $d = $('').text(f.Name).data('file', f) 69 | .appendTo($p) 70 | .click(function(e) { play(e.target); }); 71 | if (playnow) $d.click(); 72 | } 73 | 74 | function addAll() { 75 | $('#browser a.file').each(function(i, e) { 76 | addToPlaylist($(e).data('file')); 77 | }); 78 | } 79 | 80 | function play(el) { 81 | var name = $(el).data('file').Name; 82 | var path = $(el).data('file').Path; 83 | var url = root+path+'/'+name; 84 | $('#playlist a').removeClass('playing'); 85 | $(el).addClass('playing') 86 | $('#player').attr('src', url); 87 | } 88 | 89 | function next() { 90 | var $next = $('#playlist a.playing').next(); 91 | if ($next.length) play($next); 92 | } 93 | google.load("jquery", "1.4.2"); 94 | google.setOnLoadCallback(init); -------------------------------------------------------------------------------- /assets/assets.min.js: -------------------------------------------------------------------------------- 1 | function init(){load(path);$("#player").bind("ended",next);$("#addall").click(addAll);$("#next").click(next)}function load(e){var t=root+e.join("/");if(typeof cache[t]!="undefined"){populate(cache[t]);return}$.ajax({url:t,dataType:"json",success:function(e){populate(e);cache[t]=e}})}function populate(e){function n(e,n){if(n.Name[0]=="."||n.Name[0]==":")return;var r=n.IsDir;var i=r?"dir":"file";n.Path=path.join("/");$("").text(n.Name).data("file",n).addClass(i).appendTo(t).click(r?clickDir:clickFile)}var t=$("#browser").empty();e.sort(function(e,t){e=e.Name.toLowerCase();t=t.Name.toLowerCase();if(e>t)return 1;if(e..').click(function(){path.pop();load(path)})}function clickDir(e){path.push($(e.target).data("file").Name);load(path)}function clickFile(e){addToPlaylist($(e.target).data("file"))}function addToPlaylist(e){var t=$("#playlist");var n=t.find("a").length==0;var r=$("").text(e.Name).data("file",e).appendTo(t).click(function(e){play(e.target)});if(n)r.click()}function addAll(){$("#browser a.file").each(function(e,t){addToPlaylist($(t).data("file"))})}function play(e){var t=$(e).data("file").Name;var n=$(e).data("file").Path;var r=root+n+"/"+t;$("#playlist a").removeClass("playing");$(e).addClass("playing");$("#player").attr("src",r)}function next(){var e=$("#playlist a.playing").next();if(e.length)play(e)}var root="/f/";var path=[];var cache={};google.load("jquery","1.4.2");google.setOnLoadCallback(init) -------------------------------------------------------------------------------- /assets/style.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | color: #55acee; 3 | font-family: sans-serif; 4 | text-align: center; 5 | } 6 | 7 | body { 8 | font-family: sans-serif; 9 | background: #595959; 10 | } 11 | 12 | #browser { 13 | border-radius: 10px; 14 | padding: 5px 5px 3px 5px; 15 | width: 47%; 16 | max-width: 47%; 17 | float: left; 18 | height: auto; 19 | min-height: 40px; 20 | overflow: auto; 21 | } 22 | 23 | #playlist { 24 | border-radius: 10px; 25 | padding: 5px 5px 3px 5px; 26 | width: 50%; 27 | float: right; 28 | height: auto; 29 | min-height: 40px; 30 | overflow: auto; 31 | } 32 | 33 | #browser a, #playlist a { 34 | display: block; 35 | cursor: pointer; 36 | padding: 2px 4px; 37 | border-radius: 5px; 38 | overflow: hidden; 39 | margin-bottom: 2px; 40 | } 41 | #browser { 42 | background: #ffcc00; 43 | } 44 | 45 | #browser a.dir { 46 | background: #55acee; 47 | color: white; 48 | } 49 | 50 | #browser a.file { 51 | background: #e5b700; 52 | color: blue; 53 | } 54 | 55 | #playlist { 56 | background: #55acee; 57 | } 58 | 59 | #playlist a { 60 | background: #37c871; 61 | } 62 | 63 | #playlist a.playing { 64 | background: #4c9ad6; 65 | color: #ee9755; 66 | } 67 | 68 | #browser a:hover { 69 | color: white; 70 | } 71 | 72 | #playlist a:hover { 73 | color: white; 74 | } 75 | 76 | #controls { 77 | margin-top: 10px; 78 | margin-bottom: 10px; 79 | left: 50%; 80 | } 81 | 82 | #controls a { 83 | cursor: pointer; 84 | background: #eee; 85 | padding: 5px; 86 | border-radius: 5px; 87 | left: 50%; 88 | } 89 | 90 | #divaudio { 91 | width: 100%; 92 | height: 60px; 93 | background: #666666; 94 | border-radius: 10px; 95 | 96 | } 97 | 98 | audio { 99 | width: 100%; 100 | margin-top: 15px; 101 | background: #666666; 102 | } 103 | -------------------------------------------------------------------------------- /go-player.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patdhlk/go-player/15017f5e4b1f553a29f8fdbb49ca7099813b6991/go-player.exe -------------------------------------------------------------------------------- /go-player.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "flag" 6 | "log" 7 | "net/http" 8 | "os" 9 | "path/filepath" 10 | ) 11 | 12 | type Entry struct { 13 | Name string // name of the object 14 | IsDir bool 15 | Mode os.FileMode 16 | } 17 | 18 | const ( 19 | filePrefix = "/f/" 20 | ) 21 | 22 | var ( 23 | addr = flag.String("http", ":8080", "http listen address") 24 | root = flag.String("root", "music/", "music root") 25 | ) 26 | 27 | func main() { 28 | flag.Parse() 29 | //to serve static files, *.css and *.js 30 | http.Handle("/assets/", http.StripPrefix("/assets/", http.FileServer(http.Dir("assets")))) 31 | http.HandleFunc("/", Index) 32 | http.HandleFunc(filePrefix, File) 33 | http.ListenAndServe(*addr, nil) 34 | } 35 | 36 | func Index(w http.ResponseWriter, r *http.Request) { 37 | http.ServeFile(w, r, "./index.html") 38 | //http.FileServer(http.Dir("./")) 39 | log.Print("index called") 40 | log.Print(" request from: ", r.Referer()) 41 | } 42 | 43 | func File(w http.ResponseWriter, r *http.Request) { 44 | fn := filepath.Join(*root, r.URL.Path[len(filePrefix):]) 45 | fi, err := os.Stat(fn) 46 | log.Print("File called: ", fn) 47 | 48 | if err != nil { 49 | http.Error(w, err.Error(), http.StatusNotFound) 50 | return 51 | } 52 | if fi.IsDir() { 53 | serveDirectory(fn, w, r) 54 | return 55 | } 56 | http.ServeFile(w, r, fn) 57 | } 58 | 59 | func serveDirectory(fn string, w http.ResponseWriter, r *http.Request) { 60 | defer func() { 61 | if err, ok := recover().(error); ok { 62 | http.Error(w, err.Error(), http.StatusInternalServerError) 63 | } 64 | }() 65 | d, err := os.Open(fn) 66 | if err != nil { 67 | panic(err) 68 | } 69 | log.Print("serverDirectory called: ", fn) 70 | 71 | files, err := d.Readdir(-1) 72 | if err != nil { 73 | panic(err) 74 | } 75 | 76 | // Json Encode isn't working with the FileInfo interface, 77 | // therefore populate an Array of Entry and add the Name method 78 | entries := make([]Entry, len(files), len(files)) 79 | 80 | for k := range files { 81 | //log.Print(files[k].Name()) 82 | entries[k].Name = files[k].Name() 83 | entries[k].IsDir = files[k].IsDir() 84 | entries[k].Mode = files[k].Mode() 85 | } 86 | 87 | j := json.NewEncoder(w) 88 | 89 | if err := j.Encode(&entries); err != nil { 90 | panic(err) 91 | } 92 | } 93 | 94 | //a not needed HelperFunction 95 | func HelperFunction() { 96 | //some unnecessary code here to show github.com that the go-player is a go project - not a *.js project 97 | e := new(Entry) 98 | e.Name = "NotNecessary" 99 | e.IsDir = false 100 | //unnecessary end 101 | } 102 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | GO-PLAYER 10 | 11 | 12 | Ooops? Your browser doesn't support <audio>?! Take chrome 13 | 14 | 15 | 16 | Add all 17 | Next 18 | Clear 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patdhlk/go-player/15017f5e4b1f553a29f8fdbb49ca7099813b6991/screenshot.png --------------------------------------------------------------------------------
Ooops? Your browser doesn't support <audio>?! Take chrome