Can skip to a random track on double click
This commit is contained in:
parent
677f93723b
commit
19fa419d89
@ -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 {
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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")
|
||||||
|
@ -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>
|
||||||
|
@ -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) {
|
||||||
|
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user