diff --git a/audio/audio.go b/audio/audio.go index 7803d5e..56a82c5 100644 --- a/audio/audio.go +++ b/audio/audio.go @@ -8,15 +8,9 @@ import ( "../icecast" ) -// type stream_t struct { -// filepath string -// bitrate int -// channels int -// encoding_src string -// encoding_dst string -// } +type Next func() (string, error) -func Play(filename string) { +func Start(next_cb Next) { sig := make(chan os.Signal, 1) signal.Notify(sig, os.Interrupt, os.Kill) @@ -26,41 +20,51 @@ func Play(filename string) { channels := 1 bytes_per_sec := int(samplerate) * channels * bytes_per_sample - r, e := os.Open(filename) - chk(e) - defer r.Close() - _, er := icecast.Connect() chk(er) audio := make([]byte, 2 * 1024) - dt := time.Second * time.Duration(len(audio)) / time.Duration(bytes_per_sec) - now := time.Now() + for fname, exit := next_cb(); exit == nil; fname, exit = next_cb() { - for { + r, e := os.Open(fname) + chk(e) + defer r.Close() + + now := time.Now() + + for { + + n, err := r.Read(audio) + if n == 0 { + break + } + chk(err) + + pre := time.Now() + + icecast.Send(audio) + + post := time.Now() + lag := time.Duration((post.Sub(pre))) + + select { + case <-sig: + return + default: + } + + dt = (time.Second * time.Duration(n) / time.Duration(bytes_per_sec)) - lag + + time.Sleep(dt) - n, err := r.Read(audio) - if n == 0 { - break } - chk(err) - icecast.Send(audio) - - select { - case <-sig: - return - default: - } - - time.Sleep(dt) + fmt.Println(time.Duration(time.Now().Sub(now))) } - fmt.Println(time.Duration(time.Now().Sub(now))) - } diff --git a/playlist/playlist.go b/playlist/playlist.go index fa5f75c..0f78ecf 100644 --- a/playlist/playlist.go +++ b/playlist/playlist.go @@ -13,12 +13,15 @@ import ( var pln = log.Println +type Pop func(*Playlist) + type Playlist struct { NAME string CTRACK config.Track_t CALBUM config.Album_t LIST []uint32 MAX int + CALLB Pop } type PrettyPlaylist struct { @@ -29,6 +32,19 @@ type PrettyPlaylist struct { MAX int } +type MinimalTrack struct { + ID string `json:"id"` + NAME string `json:"name"` + MAKER string `json:"maker"` + ALBUM string `json:"album"` +} + +type MinimalPlaylist struct { + NAME string `json:"name"` + CTRACK string `json:"ctrack"` + CALBUM string `json:"calbum"` + LIST []MinimalTrack `json:"list"` +} func MakeRandom(name string, max int) (*Playlist, error) { err := archive.Build() @@ -80,19 +96,22 @@ func (pp *PrettyPlaylist) Unpretty() *Playlist { p := &Playlist{NAME: pp.NAME, CTRACK: pp.CTRACK, CALBUM: pp.CALBUM, MAX: pp.MAX} p.LIST = make([]uint32, len(pp.LIST)) for i := 0; i < len(pp.LIST); i++ { - p.LIST = append(p.LIST, pp.LIST[i].ID) + p.LIST[i] = pp.LIST[i].ID } return p } -// type PrettyPlaylist struct { -// NAME string -// CTRACK config.Track_t -// CALBUM config.Album_t -// LIST []config.Track_t -// MAX int -// } - +func (p *Playlist) Minimal() *MinimalPlaylist { + mp := &MinimalPlaylist{NAME: p.NAME, CTRACK: p.CTRACK.NAME} + mp.CALBUM = p.CALBUM.MAKER + " - " + p.CALBUM.NAME + mp.LIST = make([]MinimalTrack, len(p.LIST)) + for i := 0; i < len(p.LIST); i++ { + track := archive.Archive_map[p.LIST[i]] + strid := strconv.FormatUint(uint64(track.ID), 10) + mp.LIST[i] = MinimalTrack{ID: strid, NAME: track.NAME, MAKER: track.MAKER, ALBUM: track.ALBUM} + } + return mp +} func (pp *PrettyPlaylist) Print() { @@ -115,9 +134,9 @@ func print(slice []uint32) { // https://github.com/golang/go/wiki/SliceTricks // https://stackoverflow.com/questions/33834742/remove-and-adding-elements-to-array-in-go-lang -func (p *Playlist) Pop() error { +func (p *Playlist) Pop() (string, error) { if len(p.LIST) == 0 { - return errors.New("Playlist is empty") + return "", errors.New("Playlist is empty") } t := p.LIST[0] @@ -130,7 +149,11 @@ func (p *Playlist) Pop() error { p.CTRACK = archive.Archive_map[t] p.CALBUM = config.Xcfg.Archive.ALBUMS[p.CTRACK.AID] - return nil + if p.CALLB != nil { + p.CALLB(p) + } + + return p.CTRACK.PATH, nil } func (p *Playlist) Push(track_id uint32) error { @@ -191,26 +214,43 @@ func (p *Playlist) Move(track_id uint32, at_index int) error { return errors.New("Invalid track ID") } - slice_head := p.LIST[:k] - slice_move := p.LIST[k+1:at_index+1] - slice_tail := make([]uint32, len(p.LIST[at_index+1:])) - copy(slice_tail, p.LIST[at_index+1:]) + // pln("k: " + strconv.Itoa(k)) + // pln("at_index: " + strconv.Itoa(at_index)) + // pln("------") - // slice_move = append(slice_move, track_id) + var slice_head, slice_move, slice_tail []uint32 + if k < at_index { + slice_head = make([]uint32, len(p.LIST[:k])) + copy(slice_head, p.LIST[:k]) + // slice_head = p.LIST[:k] + slice_move = make([]uint32, len(p.LIST[k+1:at_index+1])) + copy(slice_move, p.LIST[k+1:at_index+1]) + // slice_move = p.LIST[k:at_index] + slice_tail = make([]uint32, len(p.LIST[at_index+1:])) + copy(slice_tail, p.LIST[at_index+1:]) + p.LIST = append(slice_head, append(append(slice_move, track_id), slice_tail...)...) + } else if k > at_index { + slice_head = make([]uint32, len(p.LIST[:at_index])) + copy(slice_head, p.LIST[:at_index]) + // slice_head = p.LIST[:at_index] + slice_move = make([]uint32, len(p.LIST[at_index:k])) + copy(slice_move, p.LIST[at_index:k]) + // slice_tail = p.LIST[k+1:] + slice_tail = make([]uint32, len(p.LIST[k+1:])) + copy(slice_tail, p.LIST[k+1:]) + p.LIST = append(append(append(slice_head, track_id), slice_move...), slice_tail...) + } - pln("from_index: " + strconv.Itoa(k)) - pln("at_index: " + strconv.Itoa(at_index)) - pln("------") - pln("slice head: ") - print(slice_head) - pln("slice move: ") - print(slice_move) - pln("** ") - pln("slice tail: ") - print(slice_tail) - pln("...........................") - p.LIST = append(slice_head, append(append(slice_move, track_id), slice_tail...)...) + // pln("slice head: ") + // print(slice_head) + // pln("slice move: ") + // print(slice_move) + // pln("** ") + // pln("slice tail: ") + // print(slice_tail) + // pln("...........................") + return nil } diff --git a/serve.go b/serve.go index 7aefb72..7e0e56a 100644 --- a/serve.go +++ b/serve.go @@ -5,19 +5,25 @@ import ( "log" "net/http" "./config" + "./audio" "./playlist" "./www" ) var pln = fmt.Println +var p *playlist.Playlist = nil func main() { config.Loadconfig("config.ini") + p, err := playlist.MakeRandom("YOYO", 10) if err != nil { panic(err) } - p.Pop() - www.Init(p) + + www.Init(p) + + go audio.Start(p.Pop) + log.Fatal(http.ListenAndServe(":8718", nil)) -} \ No newline at end of file +} diff --git a/www/tmpl/playlist.html b/www/tmpl/playlist.html index fdd5597..6f5f888 100644 --- a/www/tmpl/playlist.html +++ b/www/tmpl/playlist.html @@ -19,13 +19,10 @@ console.log("update") list = Array.from(document.querySelectorAll('#sortable>li')); var i = list.indexOf(u.item[0]) - console.log(u.item.attr("id") + " is now " + i) on_update_operation(u.item.attr("id"), i) } }); $( "#sortable" ).disableSelection(); - - // connect to ppop sock = new WebSocket("ws://localhost:8718/ppop"); sock.onopen = function() { console.log("ppop open") @@ -34,31 +31,63 @@ console.log("ppop closed") sock = new WebSocket("ws://localhost:8718/ppop"); } - sock.onmessage = function(msg) { - console.log(msg.data) + check_fix_list(JSON.parse(msg.data)) } - - // setInterval(function() { - // sock.send(JSON.stringify({"op": "tick", "id": "0", "index": 0})); - // },3000); - } ); var sock = null; function on_update_operation(id, index) { if(sock) { console.log("sending") - sock.send(JSON.stringify({"op": "move", "id": id, "index": index})); + sock.send(JSON.stringify({"op": "move", "id": id, "index": index})) } } + function check_fix_list(playlist) { + + console.log(playlist) + + $("#pname").text("Playlist: " + playlist.name) + $("#tname").text("Current Track: " + playlist.ctrack) + $("#aname").text("Current Album: " + playlist.calbum) + + + list = Array.from(document.querySelectorAll('#sortable>li')) + + + console.log("length ul: " + list.length) + console.log("length playlist: " + playlist.list.length) + + + for (let i = 0; i < list.length; i++) { + if(i >= playlist.list.length) { + break + } else if (list[i].id != playlist.list[i]["id"]) { + console.log("difference at index: " + i) + list[i].setAttribute("id", playlist.list[i]["id"]) + list[i].innerHTML = "" + playlist.list[i]["maker"] + + " - " + playlist.list[i]["album"] + + " - " + playlist.list[i]["name"] + "" ; + } + } + + var ul = document.getElementById('sortable'); + if(list.length > playlist.list.length) { + for(let i = playlist.list.length; i < list.length; i++) { + ul.removeChild(list[i]) + } + } else if (list.length < playlist.list.length) { + + } + console.log("synched!!") + } Radiodiodio -

Playlist: {{.NAME}}

- -

Current Track: {{.CTRACK.NAME}}

-

Current Album : {{.CALBUM.NAME}} - {{.CALBUM.MAKER}}

+

Playlist: {{.NAME}}

+ +

Current Track: {{.CTRACK.NAME}}

+

Current Album : {{.CALBUM.NAME}} - {{.CALBUM.MAKER}}