1/*
2 * Copyright (C) 2016
3 *      Jean-Luc Barriere <jlbarriere68@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17
18import QtQuick 2.9
19import QtQuick.Controls 2.2
20import "Delegates"
21import "Flickables"
22
23MusicListView {
24    id: renderingControlList
25    clip: true
26
27    model: player.renderingModel
28    objectName: "renderingControlList"
29
30    property color backgroundColor: styleMusic.view.backgroundColor
31    property color foregroundColor: styleMusic.view.foregroundColor
32    property color labelColor: styleMusic.view.labelColor
33    readonly property real rowHeight: units.gu(7)
34    property bool held: false
35    property bool volumePressed: false
36
37    signal finger(bool isHeld)
38
39    // try to reset the model on signal renderingControlChanged
40    Connections {
41        target: player
42        function onRenderingControlChanged() {
43            refreshRendering.start()
44        }
45    }
46
47    // delay the refresh while volume handle is pressed to avoid breaking of drag
48    Timer {
49        id: refreshRendering
50        interval: 0
51        onTriggered: {
52            if (volumePressed) {
53                interval = 100; // retry in 100ms
54                restart();
55            } else {
56                player.refreshRendering();
57                interval = 0;
58            }
59        }
60    }
61
62    delegate: SimpleListItem {
63        id: renderingControlListItem
64        objectName: "renderingControlListItem" + index
65
66        color: renderingControlList.backgroundColor
67        height: renderingControlList.rowHeight
68
69        column: Column {
70            id: column
71            anchors.top: parent.top
72            width: parent.width
73
74            Label {
75                id: nameLabel
76                font.pointSize: units.fs("medium")
77                font.weight: Font.Normal
78                text: model.name
79                color: renderingControlList.labelColor
80                elide: Text.ElideRight
81                wrapMode: Text.NoWrap
82                maximumLineCount: 1
83                verticalAlignment: Text.AlignVCenter
84                anchors {
85                    leftMargin: units.gu(2)
86                    left: parent.left
87                }
88            }
89
90            /* volume slider component */
91            Item {
92                id: controlerContainer
93                anchors {
94                    left: parent.left
95                    leftMargin: units.gu(2)
96                    right: parent.right
97                }
98                height: units.gu(5)
99                width: parent.width
100
101                /* Mute button */
102                Icon {
103                    id: muteButton
104                    anchors.left: parent.left
105                    anchors.verticalCenter: parent.verticalCenter
106                    height: units.gu(5)
107                    width: height
108                    source: model.mute ? "qrc:/images/audio-volume-muted.svg" : "qrc:/images/audio-volume.svg"
109                    opacity: model.mute ? 1.0 : 0.6
110                    color: renderingControlList.foregroundColor
111                    onClicked: {
112                        player.toggleMute(model.uuid, function(result) {
113                            if (result) {
114                                player.renderingModel.setMute(index, !model.mute);
115                            } else {
116                                mainView.actionFailed();
117                            }
118                        });
119                        finger(held)
120                    }
121                }
122
123                StyledSlider {
124                    id: volumeSlider
125                    anchors.leftMargin: units.gu(2)
126                    anchors.left: muteButton.right
127                    anchors.rightMargin: units.gu(2)
128                    anchors.right: gripButton.left
129                    anchors.verticalCenter: parent.verticalCenter
130                    wheelEnabled: true
131                    stepSize: 1.0
132                    live: true
133                    from: 0
134                    to: 100
135                    objectName: "volumeSliderShape"
136                    enabled: !model.outputFixed
137                    opacity: (model.outputFixed ? 0.2 : 1.0)
138                    value: model.volume
139
140                    handleSize: (model.outputFixed ? 0 : units.gu(2))
141                    handleColor: labelColor
142                    handleBorderColor: handleColor
143                    backgroundColor: styleMusic.playerControls.volumeBackgroundColor
144                    foregroundColor: styleMusic.playerControls.volumeForegroundColor
145
146                    onMoved: {
147                        if (!pressed)
148                            setVolume.start();
149                    }
150
151                    onValueChanged: {
152                        if (pressed)
153                            setVolume.start();
154                    }
155
156                    onPressedChanged: {
157                        // report the handle is pressed to delay the model reset
158                        renderingControlList.volumePressed = pressed;
159                    }
160
161                    Timer {
162                        interval: 200
163                        repeat: true
164                        running: volumeSlider.pressed
165                        onTriggered: finger(held)
166                    }
167
168                    Timer {
169                        id: setVolume
170                        interval: 200
171                        property bool ready: true // false: delay the call
172                        onTriggered: {
173                            if (!ready) {
174                                player.setVolumeForFake(model.uuid, volumeSlider.value);
175                                finger(held);
176                                restart();
177                            } else {
178                                ready = false;
179                                player.setVolume(model.uuid, volumeSlider.value, function(result) {
180                                    ready = true; // become ready on finished
181                                    if (!result) {
182                                        customdebug("Set volume failed for zone " + model.uuid);
183                                    }
184                                });
185                                finger(held);
186                            }
187                        }
188                    }
189                }
190
191                /* Grip button */
192                Icon {
193                    id: gripButton
194                    anchors.right: parent.right
195                    anchors.rightMargin: - units.gu(1)
196                    anchors.verticalCenter: parent.verticalCenter
197                    source: "qrc:/images/grip.svg"
198                    width: units.gu(5)
199                    height: width
200                    opacity: renderingControlList.held ? 1.0 : 0.6
201                    color: renderingControlList.foregroundColor
202                    onPressed: finger(held)
203                    onPressAndHold: {
204                        held = !held
205                        finger(held)
206                    }
207                }
208            }
209        }
210    }
211}
212