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