components_manager_QueueManager.bs

import "pkg:/source/utils/misc.bs"
import "ViewCreator.bs"
import "pkg:/source/api/Items.bs"
import "pkg:/source/api/baserequest.bs"
import "pkg:/source/utils/config.bs"
import "pkg:/source/api/Image.bs"
import "pkg:/source/utils/deviceCapabilities.bs"

sub init()
    m.hold = []
    m.queue = []
    m.originalQueue = []
    m.queueTypes = []
    m.isPlaying = false
    ' Preroll videos only play if user has cinema mode setting enabled
    m.isPrerollActive = m.global.session.user.settings["playback.cinemamode"]
    m.position = 0
    m.shuffleEnabled = false
end sub

' Clear all content from play queue
sub clear()
    m.isPlaying = false
    m.queue = []
    m.queueTypes = []
    m.isPrerollActive = m.global.session.user.settings["playback.cinemamode"]
    setPosition(0)
end sub

' Clear all hold content
sub clearHold()
    m.hold = []
end sub

' Delete item from play queue at passed index
sub deleteAtIndex(index)
    m.queue.Delete(index)
    m.queueTypes.Delete(index)
end sub

' Return the number of items in the play queue
function getCount()
    return m.queue.count()
end function

' Return the item currently in focus from the play queue
function getCurrentItem()
    return getItemByIndex(m.position)
end function

' Return the items in the hold
function getHold()
    return m.hold
end function

' Return whether or not shuffle is enabled
function getIsShuffled()
    return m.shuffleEnabled
end function

' Return the item in the passed index from the play queue
function getItemByIndex(index)
    return m.queue[index]
end function

' Returns current playback position within the queue
function getPosition()
    return m.position
end function

' Hold an item
sub hold(newItem)
    m.hold.push(newItem)
end sub

' Move queue position back one
sub moveBack()
    m.position--
end sub

' Move queue position ahead one
sub moveForward()
    m.position++
end sub

' Return the current play queue
function getQueue()
    return m.queue
end function

' Return the types of items in current play queue
function getQueueTypes()
    return m.queueTypes
end function

' Return the unique types of items in current play queue
function getQueueUniqueTypes()
    itemTypes = []

    for each item in getQueueTypes()
        if not inArray(itemTypes, item)
            itemTypes.push(item)
        end if
    end for

    return itemTypes
end function

' Return item at end of play queue without removing
function peek()
    return m.queue.peek()
end function

' Play items in queue
sub playQueue()
    m.isPlaying = true
    nextItem = getCurrentItem()
    if not isValid(nextItem) then return

    nextItemMediaType = getItemType(nextItem)
    if nextItemMediaType = "" then return

    if nextItemMediaType = "audio"
        CreateAudioPlayerView()
        return
    end if

    if nextItemMediaType = "audiobook"
        CreateAudioPlayerView()
        return
    end if

    if nextItemMediaType = "musicvideo"
        CreateVideoPlayerView()
        return
    end if

    if nextItemMediaType = "video"
        CreateVideoPlayerView()
        return
    end if

    if nextItemMediaType = "movie"
        CreateVideoPlayerView()
        return
    end if

    if nextItemMediaType = "episode"
        CreateVideoPlayerView()
        return
    end if

    if nextItemMediaType = "recording"
        CreateVideoPlayerView()
        return
    end if

    if nextItemMediaType = "trailer"
        CreateVideoPlayerView()
        return
    end if
end sub

' Remove item at end of play queue
sub pop()
    m.queue.pop()
    m.queueTypes.pop()
end sub

' Return isPrerollActive status
function isPrerollActive() as boolean
    return m.isPrerollActive
end function

' Set prerollActive status
sub setPrerollStatus(newStatus as boolean)
    m.isPrerollActive = newStatus
end sub

' Push new items to the play queue
sub push(newItem)
    m.queue.push(newItem)
    m.queueTypes.push(getItemType(newItem))
end sub

' Set the queue position
sub setPosition(newPosition)
    m.position = newPosition
end sub

' Reset shuffle to off state
sub resetShuffle()
    m.shuffleEnabled = false
end sub

' Toggle shuffleEnabled state
sub toggleShuffle()
    m.shuffleEnabled = not m.shuffleEnabled

    if m.shuffleEnabled
        shuffleQueueItems()
        return
    end if

    resetQueueItemOrder()
end sub

' Reset queue items back to original, unshuffled order
sub resetQueueItemOrder()
    set(m.originalQueue)
end sub

' Return original, unshuffled queue
function getUnshuffledQueue()
    return m.originalQueue
end function

' Save a copy of the original queue and randomize order of queue items
sub shuffleQueueItems()
    ' By calling getQueue 2 different ways, Roku avoids needing to do a deep copy
    m.originalQueue = m.global.queueManager.callFunc("getQueue")
    itemIDArray = getQueue()
    temp = invalid

    if m.isPlaying
        ' Save the currently playing item
        temp = getCurrentItem()
        ' remove currently playing item from itemIDArray
        itemIDArray.Delete(m.position)
    end if

    ' shuffle all items
    itemIDArray = shuffleArray(itemIDArray)

    if m.isPlaying
        ' Put currently playing item in front of itemIDArray
        itemIDArray.Unshift(temp)
    end if

    set(itemIDArray)
end sub

' Return the fitst item in the play queue
function top()
    return getItemByIndex(0)
end function

' Replace play queue with passed array
sub set(items)
    clear()
    m.queue = items
    for each item in items
        m.queueTypes.push(getItemType(item))
    end for
end sub

' Set starting point for top item in the queue
sub setTopStartingPoint(positionTicks)
    if getCount() = 0 then return
    m.queue[0].startingPoint = positionTicks
end sub

' getItemType: Returns the media type of the passed item
'
' @param {dynamic} item - Item to evaluate
' @return {string} indicating type of media item is
function getItemType(item) as string
    if isValid(item) and isValid(item.json) and isValid(item.json.mediatype) and item.json.mediatype <> ""
        return LCase(item.json.mediatype)
    else if isValid(item) and isValid(item.type) and item.type <> ""
        return LCase(item.type)
    end if

    return ""
end function