Feat: Added listener count
This commit is contained in:
parent
e2d735a6e5
commit
560ea833b1
7 changed files with 227 additions and 7 deletions
82
server.go
82
server.go
|
@ -37,12 +37,21 @@ type ConnectionPool struct {
|
|||
}
|
||||
|
||||
type MetadataConnection struct {
|
||||
metadataSent bool
|
||||
metadataSent bool
|
||||
}
|
||||
|
||||
type MetadataConnectionPool struct {
|
||||
MetadataConnectionMap map[*MetadataConnection]struct{}
|
||||
mu sync.Mutex
|
||||
MetadataConnectionMap map[*MetadataConnection]struct{}
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
type PeopleConnection struct {
|
||||
numberSent int
|
||||
}
|
||||
|
||||
type PeopleConnectionPool struct {
|
||||
PeopleConnectionMap map[*PeopleConnection]struct{}
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// Audio connection pool
|
||||
|
@ -103,6 +112,24 @@ func (cp *MetadataConnectionPool) Broadcast() {
|
|||
}
|
||||
}
|
||||
|
||||
// People connection pool
|
||||
func (cp *PeopleConnectionPool) AddConnection(connection *PeopleConnection) {
|
||||
defer cp.mu.Unlock()
|
||||
cp.mu.Lock()
|
||||
cp.PeopleConnectionMap[connection] = struct{}{}
|
||||
}
|
||||
|
||||
func (cp *PeopleConnectionPool) DeleteConnection(connection *PeopleConnection) {
|
||||
defer cp.mu.Unlock()
|
||||
cp.mu.Lock()
|
||||
delete(cp.PeopleConnectionMap, connection)
|
||||
}
|
||||
|
||||
func NewPeopleConnectionPool() *PeopleConnectionPool {
|
||||
peopleConnectionMap := make(map[*PeopleConnection]struct{})
|
||||
return &PeopleConnectionPool{PeopleConnectionMap: peopleConnectionMap}
|
||||
}
|
||||
|
||||
func getFileDelay(mp3FilePath string) int64 {
|
||||
t := 0.0
|
||||
size := 0
|
||||
|
@ -209,6 +236,7 @@ func streamFolder(connectionPool *ConnectionPool, metadataConnectionPool *Metada
|
|||
func main() {
|
||||
connPool := NewConnectionPool()
|
||||
metadataConnPool := NewMetadataConnectionPool()
|
||||
peopleConnPool := NewPeopleConnectionPool()
|
||||
|
||||
music_files := []string{}
|
||||
|
||||
|
@ -235,6 +263,7 @@ func main() {
|
|||
http.HandleFunc("/stream", func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
w.Header().Add("Content-Type", "audio/mp3")
|
||||
w.Header().Set("Cache-Control", "no-cache")
|
||||
w.Header().Add("Connection", "keep-alive")
|
||||
|
||||
flusher, ok := w.(http.Flusher)
|
||||
|
@ -268,6 +297,13 @@ func main() {
|
|||
|
||||
connection := &MetadataConnection{metadataSent: false}
|
||||
metadataConnPool.AddConnection(connection)
|
||||
|
||||
go func(done <-chan struct{}) {
|
||||
<-done
|
||||
metadataConnPool.DeleteConnection(connection)
|
||||
log.Printf("%s's connection to the metadata stream has been closed\n", r.Host)
|
||||
}(r.Context().Done())
|
||||
|
||||
log.Printf("%s has connected to the metadata stream\n", r.Host)
|
||||
// Simulate sending events (you can replace this with real data)
|
||||
for {
|
||||
|
@ -281,7 +317,11 @@ func main() {
|
|||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Fprintf(w, "data: %s\n\n", fmt.Sprintf("%s", finalData))
|
||||
if _, err := fmt.Fprintf(w, "data: %s\n\n", fmt.Sprintf("%s", finalData)); err != nil {
|
||||
metadataConnPool.DeleteConnection(connection)
|
||||
log.Printf("%s's connection to the metadata stream has been closed\n", r.Host)
|
||||
return
|
||||
}
|
||||
w.(http.Flusher).Flush()
|
||||
connection.metadataSent = true
|
||||
}
|
||||
|
@ -289,6 +329,40 @@ func main() {
|
|||
}
|
||||
})
|
||||
|
||||
http.HandleFunc("/listeners", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
w.Header().Set("Access-Control-Expose-Headers", "Content-Type")
|
||||
|
||||
w.Header().Set("Content-Type", "text/event-stream")
|
||||
w.Header().Set("Cache-Control", "no-cache")
|
||||
w.Header().Set("Connection", "keep-alive")
|
||||
|
||||
connection := &PeopleConnection{numberSent: 0}
|
||||
peopleConnPool.AddConnection(connection)
|
||||
|
||||
go func(done <-chan struct{}) {
|
||||
<-done
|
||||
peopleConnPool.DeleteConnection(connection)
|
||||
log.Printf("%s's connection to the listeners stream has been closed\n", r.Host)
|
||||
}(r.Context().Done())
|
||||
|
||||
log.Printf("%s has connected to the listeners stream\n", r.Host)
|
||||
for {
|
||||
if(connection.numberSent != len(connPool.ConnectionMap)) {
|
||||
connection.numberSent = len(connPool.ConnectionMap)
|
||||
// n, err := fmt.Fprintf(w, "data: %s\n\n", fmt.Sprintf("%d", connection.numberSent))
|
||||
_, err := w.Write([]byte(fmt.Sprintf("data: %d\n\n", connection.numberSent)))
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
w.(http.Flusher).Flush()
|
||||
time.Sleep(time.Second * 1)
|
||||
}
|
||||
})
|
||||
|
||||
log.Println("Listening on port 8080...")
|
||||
log.Fatal(http.ListenAndServe(":8080", nil))
|
||||
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
<script>
|
||||
import { basePath } from './lib/router.tsx'
|
||||
import menthealeauLogo from './assets/menthealeau.svg'
|
||||
import dancing_1 from './assets/d1.svg'
|
||||
import dancing_2 from './assets/d2.svg'
|
||||
import dancing_3 from './assets/d3.svg'
|
||||
import dancing_4 from './assets/d4.svg'
|
||||
import dancing_5 from './assets/d5.svg'
|
||||
|
||||
let dancing_guys = [dancing_1, dancing_2, dancing_3, dancing_4, dancing_5]
|
||||
|
||||
let isPlaying = $state(false)
|
||||
let title = $state("")
|
||||
let url = $state("")
|
||||
let numberOfListeners = $state(0)
|
||||
let imageData = $state("")
|
||||
let loadingSound = $state(false)
|
||||
let firstTimePlaying = $state(true)
|
||||
|
@ -20,6 +28,19 @@
|
|||
imageData = receivedData.artwork
|
||||
}
|
||||
|
||||
const listenerSource = new EventSource(basePath + '/listeners')
|
||||
listenerSource.onmessage = function(event) {
|
||||
let receivedData = event.data
|
||||
console.log(receivedData)
|
||||
numberOfListeners = parseInt(receivedData)
|
||||
}
|
||||
|
||||
function getRandomInt(min, max) {
|
||||
min = Math.ceil(min);
|
||||
max = Math.floor(max);
|
||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
}
|
||||
|
||||
async function buttonClick() {
|
||||
console.log(audioPlayer.duration)
|
||||
if(isPlaying) {
|
||||
|
@ -70,15 +91,20 @@
|
|||
<audio bind:this={audioPlayer}>
|
||||
<source src={basePath + "/stream"} type="audio/mp3">
|
||||
</audio>
|
||||
<div class="flex flex-row w-full mt-16 -mb-24 h-6">
|
||||
{#each {length: numberOfListeners} as _,i}
|
||||
<img src={dancing_guys[getRandomInt(0,4)]} class="max-h-6 max-w-6 animate-bounce">
|
||||
{/each}
|
||||
</div>
|
||||
<div class="flex flex-col items-center w-full">
|
||||
<div class="bg-[#ff99b4] w-32 rounded-full -mb-12">
|
||||
{#if loadingSound}
|
||||
<svg class="mr-3 -ml-1 w-full animate-spin text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg>
|
||||
{:else}
|
||||
{#if isPlaying}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" onclick={buttonClick} class="text-white w-full" viewBox="0 0 24 24"><path fill="currentColor" d="M6 16V8q0-.825.588-1.412T8 6h8q.825 0 1.413.588T18 8v8q0 .825-.587 1.413T16 18H8q-.825 0-1.412-.587T6 16"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" onclick={buttonClick} class="text-white w-full cursor-pointer" viewBox="0 0 24 24"><path fill="currentColor" d="M6 16V8q0-.825.588-1.412T8 6h8q.825 0 1.413.588T18 8v8q0 .825-.587 1.413T16 18H8q-.825 0-1.412-.587T6 16"/></svg>
|
||||
{:else}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" onclick={buttonClick} class="text-white w-full" viewBox="0 0 24 24"><path fill="currentColor" d="M8 17.175V6.825q0-.425.3-.713t.7-.287q.125 0 .263.037t.262.113l8.15 5.175q.225.15.338.375t.112.475t-.112.475t-.338.375l-8.15 5.175q-.125.075-.262.113T9 18.175q-.4 0-.7-.288t-.3-.712"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" onclick={buttonClick} class="text-white w-full cursor-pointer" viewBox="0 0 24 24"><path fill="currentColor" d="M8 17.175V6.825q0-.425.3-.713t.7-.287q.125 0 .263.037t.262.113l8.15 5.175q.225.15.338.375t.112.475t-.112.475t-.338.375l-8.15 5.175q-.125.075-.262.113T9 18.175q-.4 0-.7-.288t-.3-.712"/></svg>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
|
@ -89,7 +115,7 @@
|
|||
<span class="speech-bubble arrow-right">Oh ... De tout.</span>
|
||||
</div>
|
||||
<div class="w-full opacity-50">
|
||||
<span>Créé par Zuma · <a href="https://git.shenanigans.cc/globuzma/mentalaradio">Source</a></span>
|
||||
<span>Créé par Zuma · <a class="underline" href="https://git.shenanigans.cc/globuzma/mentalaradio">Source</a></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
24
src/assets/d1.svg
Normal file
24
src/assets/d1.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 12 KiB |
24
src/assets/d2.svg
Normal file
24
src/assets/d2.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 12 KiB |
24
src/assets/d3.svg
Normal file
24
src/assets/d3.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 12 KiB |
24
src/assets/d4.svg
Normal file
24
src/assets/d4.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 14 KiB |
24
src/assets/d5.svg
Normal file
24
src/assets/d5.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 14 KiB |
Loading…
Reference in a new issue