Can skip to a random track on double click
continuous-integration/drone/push Build is passing Details
continuous-integration/drone/tag Build is passing Details

This commit is contained in:
nemunaire 2024-01-14 10:17:03 +01:00
parent 677f93723b
commit 19fa419d89
7 changed files with 83 additions and 0 deletions

View File

@ -162,6 +162,21 @@ func declareInputsRoutes(cfg *config.Config, router *gin.RouterGroup) {
c.JSON(http.StatusOK, true) c.JSON(http.StatusOK, true)
}) })
streamRoutes.POST("/next_random_track", func(c *gin.Context) {
input, ok := c.MustGet("input").(inputs.PlaylistInput)
if !ok {
c.AbortWithStatusJSON(http.StatusMethodNotAllowed, gin.H{"errmsg": "The source doesn't support that"})
return
}
err := input.NextRandomTrack()
if err != nil {
c.AbortWithStatusJSON(http.StatusMethodNotAllowed, gin.H{"errmsg": err.Error()})
return
}
c.JSON(http.StatusOK, true)
})
streamRoutes.POST("/prev_track", func(c *gin.Context) { streamRoutes.POST("/prev_track", func(c *gin.Context) {
input, ok := c.MustGet("input").(inputs.PlaylistInput) input, ok := c.MustGet("input").(inputs.PlaylistInput)
if !ok { if !ok {

View File

@ -194,6 +194,28 @@ func declareSourcesRoutes(cfg *config.Config, router *gin.RouterGroup) {
c.JSON(http.StatusOK, true) c.JSON(http.StatusOK, true)
}) })
sourcesRoutes.POST("/next_random_track", func(c *gin.Context) {
src := c.MustGet("source").(sources.SoundSource)
if !src.IsActive() {
c.AbortWithStatusJSON(http.StatusNotAcceptable, gin.H{"errmsg": "Source not active"})
return
}
s, ok := src.(inputs.PlaylistInput)
if !ok || !s.HasPlaylist() {
c.AbortWithStatusJSON(http.StatusMethodNotAllowed, gin.H{"errmsg": "The source doesn't support"})
return
}
err := s.NextRandomTrack()
if err != nil {
c.AbortWithStatusJSON(http.StatusMethodNotAllowed, gin.H{"errmsg": err.Error()})
return
}
c.JSON(http.StatusOK, true)
})
sourcesRoutes.POST("/prev_track", func(c *gin.Context) { sourcesRoutes.POST("/prev_track", func(c *gin.Context) {
src := c.MustGet("source").(sources.SoundSource) src := c.MustGet("source").(sources.SoundSource)

View File

@ -25,6 +25,7 @@ type ControlableInput interface {
type PlaylistInput interface { type PlaylistInput interface {
HasPlaylist() bool HasPlaylist() bool
NextTrack() error NextTrack() error
NextRandomTrack() error
PreviousTrack() error PreviousTrack() error
} }

View File

@ -269,6 +269,36 @@ func (s *MPVSource) NextTrack() error {
return nil return nil
} }
func (s *MPVSource) NextRandomTrack() error {
if s.ipcSocketDir == "" {
return fmt.Errorf("Not supported")
}
conn := mpvipc.NewConnection(s.ipcSocket())
err := conn.Open()
if err != nil {
return err
}
defer conn.Close()
_, err = conn.Call("playlist-shuffle")
if err != nil {
return err
}
_, err = conn.Call("playlist-next", "weak")
if err != nil {
return err
}
_, err = conn.Call("playlist-unshuffle")
if err != nil {
return err
}
return nil
}
func (s *MPVSource) PreviousTrack() error { func (s *MPVSource) PreviousTrack() error {
if s.ipcSocketDir == "" { if s.ipcSocketDir == "" {
return fmt.Errorf("Not supported") return fmt.Errorf("Not supported")

View File

@ -24,6 +24,7 @@
<button <button
class="btn btn-sm btn-primary" class="btn btn-sm btn-primary"
on:click={() => source.nexttrack()} on:click={() => source.nexttrack()}
on:dblclick={() => source.nextrandomtrack()}
> >
<i class="bi bi-skip-forward-fill"></i> <i class="bi bi-skip-forward-fill"></i>
</button> </button>

View File

@ -39,6 +39,13 @@ export class Input {
} }
} }
async nextrandomtrack(idstream) {
const data = await fetch(`api/inputs/${this.id}/streams/${idstream}/next_random_track`, {headers: {'Accept': 'application/json'}, method: 'POST'});
if (data.status != 200) {
throw new Error((await res.json()).errmsg);
}
}
async prevtrack(idstream) { async prevtrack(idstream) {
const data = await fetch(`api/inputs/${this.id}/streams/${idstream}/prev_track`, {headers: {'Accept': 'application/json'}, method: 'POST'}); const data = await fetch(`api/inputs/${this.id}/streams/${idstream}/prev_track`, {headers: {'Accept': 'application/json'}, method: 'POST'});
if (data.status != 200) { if (data.status != 200) {

View File

@ -46,6 +46,13 @@ export class Source {
} }
} }
async nextrandomtrack() {
const data = await fetch(`api/sources/${this.id}/next_random_track`, {headers: {'Accept': 'application/json'}, method: 'POST'});
if (data.status != 200) {
throw new Error((await res.json()).errmsg);
}
}
async prevtrack() { async prevtrack() {
const data = await fetch(`api/sources/${this.id}/prev_track`, {headers: {'Accept': 'application/json'}, method: 'POST'}); const data = await fetch(`api/sources/${this.id}/prev_track`, {headers: {'Accept': 'application/json'}, method: 'POST'});
if (data.status != 200) { if (data.status != 200) {