<commit_before>import QtQuick 2.8
import "../code/utils.js" as Utils

Item {
    readonly property bool isConnected: d.zoneCount > 0 & d.modelReady
    readonly property var model: pnModel
    readonly property alias timer: pnTimer
    readonly property alias hostUrl: reader.hostUrl

    readonly property var zoneModel: {
        var list = []
        for(var i=0; i<pnModel.count; ++i)
            list.push({ "zoneid": pnModel.get(i).zoneid, "zonename": pnModel.get(i).zonename })
        return list
    }

    QtObject{
        id: d
        property int zoneCount: 0
        property bool modelReady: false
        property int initCtr: 0
        property var currentVars: []

        function init() {
            zoneCount = 0
            initCtr = 0
            modelReady = false
            currentVars.length = 0
        }
    }

    signal connectionReady()
    signal trackChange(var zoneid, var filekey)
    signal totalTracksChange(var zoneid, var totalTracks)

    function run(cmd, zonendx) {
        if (zonendx === undefined)
            reader.exec(cmd)
        else {
            var delim = cmd.indexOf('?') === -1 ? '?' : '&'
            reader.exec("%1%2Zone=%3".arg(cmd).arg(delim).arg(pnModel.get(zonendx).zoneid))
            event.singleShot(300, function(){ updateModelItem(zonendx) })
        }
    }

    function zonesByStatus(status) {
        var list = []
        for(var i=0; i<pnModel.count; ++i) {
            if (pnModel.get(i).status === status)
                list.push(i)
        }
        return list
    }
    function imageUrl(filekey, size) {
        var imgsize = (size === undefined | size === null) ? 'medium' : size
        return hostUrl + "File/GetImage?Thumbnailsize=" + imgsize + "&File=" + filekey
    }

    function updateModel(status, include) {
        var inclStatus = (include === undefined || include === null) ? true : include

        if (inclStatus) {
            for (var z=0; z<pnModel.count; ++z) {
                if (pnModel.get(z).status === status) {
                    updateModelItem(z)
                }
            }
        }
        else {
            for (var z=0; z<pnModel.count; ++z) {
                if (pnModel.get(z).status !== status) {
                    updateModelItem(z)
                }
            }
        }
    }
    function updateModelItem(ndx) {
        // reset some transient fields
        pnModel.setProperty(ndx, "linkedzones", "")
        // pass model/ndx so the reader will update it directly
        reader.runQuery("Playback/Info?zone=" + pnModel.get(ndx).zoneid, pnModel, ndx)
    }
    function init(host) {
        // clean up
        pnTimer.stop()
        pnModel.clear()
        d.init()
        reader.currentHost = host
        // Set callback to get zones, reset when done to prepare reader for pn poller
        reader.callback = function(data)
        {
            // seeding model entries
            d.zoneCount = data["numberzones"]
            for(var i = 0; i<d.zoneCount; ++i) {
                // setup defined props in the model for each zone
                pnModel.append({"zoneid": data["zoneid"+i]
                                   , "zonename": data["zonename"+i]
                                   , "status": "Stopped"
                                   , "linked": false
                                   , "mute": false})
                // keep up with changes to specific items for add'l signalling
                d.currentVars.push({"zoneid": data["zoneid"+i], "filekey": "", "playingnowtracks": "" })
            }
            updateModel("Playing", false)
            pnTimer.start()
            reader.callback = null
        }
        reader.runQuery("Playback/Zones")
    }

    function playPlaylist(plid, zonendx) {
        run("Playlist/Files?Shuffle=1&Action=Play&Playlist=" + plid, zonendx)
    }
    function addPlaylist(plid, zonendx) {
        run("Playlist/Files?Shuffle=1&Action=Play&PlayMode=Add&Playlist=" + plid, zonendx)
    }
    function play(zonendx) {
        run("Playback/PlayPause", zonendx)
    }
    function previous(zonendx) {
        run("Playback/Previous", zonendx)
    }
    function next(zonendx) {
        run("Playback/Next", zonendx)
    }
    function stop(zonendx) {
        run("Playback/Stop", zonendx)
    }
    function stopAllZones() {
        run("Playback/StopAll")
    }

    function unLinkZone(zonendx) {
        run("Playback/UnlinkZones", zonendx)
    }
    function linkZones(zone1id, zone2id) {
        run("Playback/LinkZones?Zone1=" + zone1id + "&Zone2=" + zone2id)
    }

    function isMuted(zonendx) {
        return pnModel.get(zonendx).mute
    }

    function toggleMute(zonendx) {
        setMute(zonendx, !isMuted(zonendx))
    }
    function setMute(zonendx, mute) {
        var val = (mute === undefined)
                ? "0"
                : mute ? "1" : "0"

        run("Playback/Mute?Set=" + val + "&ZoneType=Index", zonendx)
//        runEx("Playback/Mute?Set=" + val + "&ZoneType=Index&Zone=" + zonendx
//                 , function(data)
//                 {
//                     pnModel.set(zonendx, {"mute": data["state"] === "1" ? true : false})
//                 })
    }
    function setVolume(level, zonendx) {
        run("Playback/Volume?Level=" + level, zonendx)
    }

    function shuffle(zonendx) {
        run("Playback/Shuffle?Mode=reshuffle", zonendx)
        event.singleShot(250, function()
        {
            var obj = pnModel.get(zonendx)
            totalTracksChange(obj.zoneid, obj.playingnowtracks)
        })
    }

    function removeTrack(trackndx, zonendx) {
        run("Playback/EditPlaylist?Action=Remove&Source=" + trackndx, zonendx);
    }
    function clearPlaylist(zonendx) {
        run("Playback/ClearPlaylist", zonendx);<commit_msg>Add mcws cmd StopAll; Add support for mcws repeat modes<commit_after>import QtQuick 2.8
import "../code/utils.js" as Utils

Item {
    readonly property bool isConnected: d.zoneCount > 0 & d.modelReady
    readonly property var model: pnModel
    readonly property alias timer: pnTimer
    readonly property alias hostUrl: reader.hostUrl

    readonly property var zoneModel: {
        var list = []
        for(var i=0; i<pnModel.count; ++i)
            list.push({ "zoneid": pnModel.get(i).zoneid, "zonename": pnModel.get(i).zonename })
        return list
    }

    // private stuff
    QtObject{
        id: d
        property int zoneCount: 0
        property bool modelReady: false
        property int initCtr: 0
        property var currentVars: []

        function init() {
            zoneCount = 0
            initCtr = 0
            modelReady = false
            currentVars.length = 0
        }

        function loadRepeatMode(zonendx) {
            runEx("Playback/Repeat?ZoneType=Index&Zone=" + zonendx
                 , function(data)
                 {
                     pnModel.set(zonendx, {"repeat": data["mode"]})
                 })
        }
    }

    signal connectionReady()
    signal trackChange(var zoneid, var filekey)
    signal totalTracksChange(var zoneid, var totalTracks)

    function run(cmd, zonendx) {
        if (zonendx === undefined)
            reader.exec(cmd)
        else {
            var delim = cmd.indexOf('?') === -1 ? '?' : '&'
            reader.exec("%1%2Zone=%3".arg(cmd).arg(delim).arg(pnModel.get(zonendx).zoneid))
            event.singleShot(300, function(){ updateModelItem(zonendx) })
        }
    }

    function zonesByStatus(status) {
        var list = []
        for(var i=0; i<pnModel.count; ++i) {
            if (pnModel.get(i).status === status)
                list.push(i)
        }
        return list
    }
    function imageUrl(filekey, size) {
        var imgsize = (size === undefined | size === null) ? 'medium' : size
        return hostUrl + "File/GetImage?Thumbnailsize=" + imgsize + "&File=" + filekey
    }

    function updateModel(status, include) {
        var inclStatus = (include === undefined || include === null) ? true : include

        if (inclStatus) {
            for (var z=0; z<pnModel.count; ++z) {
                if (pnModel.get(z).status === status) {
                    updateModelItem(z)
                }
            }
        }
        else {
            for (var z=0; z<pnModel.count; ++z) {
                if (pnModel.get(z).status !== status) {
                    updateModelItem(z)
                }
            }
        }
    }
    function updateModelItem(ndx) {
        // reset some transient fields
        pnModel.setProperty(ndx, "linkedzones", "")
        // pass model/ndx so the reader will update it directly
        reader.runQuery("Playback/Info?zone=" + pnModel.get(ndx).zoneid, pnModel, ndx)
    }
    function init(host) {
        // clean up
        pnTimer.stop()
        pnModel.clear()
        d.init()
        reader.currentHost = host
        // Set callback to get zones, reset when done to prepare reader for pn poller
        reader.callback = function(data)
        {
            // seeding model entries
            d.zoneCount = data["numberzones"]
            for(var i = 0; i<d.zoneCount; ++i) {
                // setup defined props in the model for each zone
                pnModel.append({"zoneid": data["zoneid"+i]
                                   , "zonename": data["zonename"+i]
                                   , "status": "Stopped"
                                   , "linked": false
                                   , "mute": false})
                // keep up with changes to specific items for add'l signalling
                d.currentVars.push({"zoneid": data["zoneid"+i], "filekey": "", "playingnowtracks": "" })
                d.loadRepeatMode(i)
            }
            updateModel("Playing", false)
            pnTimer.start()
            reader.callback = null
        }
        reader.runQuery("Playback/Zones")
    }

    function playPlaylist(plid, zonendx) {
        run("Playlist/Files?Shuffle=1&Action=Play&Playlist=" + plid, zonendx)
    }
    function addPlaylist(plid, zonendx) {
        run("Playlist/Files?Shuffle=1&Action=Play&PlayMode=Add&Playlist=" + plid, zonendx)
    }
    function play(zonendx) {
        run("Playback/PlayPause", zonendx)
    }
    function previous(zonendx) {
        run("Playback/Previous", zonendx)
    }
    function next(zonendx) {
        run("Playback/Next", zonendx)
    }
    function stop(zonendx) {
        run("Playback/Stop", zonendx)
    }
    function stopAllZones() {
        run("Playback/StopAll")
    }

    function unLinkZone(zonendx) {
        run("Playback/UnlinkZones", zonendx)
    }
    function linkZones(zone1id, zone2id) {
        run("Playback/LinkZones?Zone1=" + zone1id + "&Zone2=" + zone2id)
    }

    function isMuted(zonendx) {
        return pnModel.get(zonendx).mute
    }

    function toggleMute(zonendx) {
        setMute(zonendx, !isMuted(zonendx))
    }
    function setMute(zonendx, mute) {
        var val = (mute === undefined)
                ? "0"
                : mute ? "1" : "0"

        run("Playback/Mute?Set=" + val + "&ZoneType=Index", zonendx)
    }
    function setVolume(level, zonendx) {
        run("Playback/Volume?Level=" + level, zonendx)
    }

    function shuffle(zonendx) {
        run("Playback/Shuffle?Mode=reshuffle", zonendx)
        event.singleShot(250, function()
        {
            var obj = pnModel.get(zonendx)
            totalTracksChange(obj.zoneid, obj.playingnowtracks)
        })
    }

    function setRepeat(mode, zonendx) {
        run("Playback/Repeat?Mode=" + mode, zonendx)
        event.singleShot(250, function() { d.loadRepeatMode(zonendx) })
    }
    function repeatMode(zonendx) {
        return pnModel.get(zonendx).repeat
    }

    function removeTrack(trackndx, zonendx) {
        run("Playback/EditPlaylist?Action=Remove&Source=" + trackndx, zonendx);
    }
    function clearPlaylist(zonendx) {
        run("Playback/ClearPlaylist", zonendx);
{'fraction_non_alphanumeric': 0.12417481407203142, 'fraction_numerical': 0.006016545500125345, 'mean_word_length': 1.871401151631478, 'pattern_counts': {'":': 22, '<': 13, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3205415', 'n_tokens_mistral': 3787, 'n_tokens_neox': 3663, 'n_words': 749}