├── _includes
├── css
│ └── site
│ │ ├── screen.css
│ │ └── mobile.css
├── icons
│ ├── apple.png
│ └── favicon.ico
├── img
│ └── site
│ │ ├── loading.png
│ │ ├── ajax-loader-black.gif
│ │ └── ajax-loader-white.gif
├── php
│ ├── Ajax.php
│ ├── Volume.php
│ └── PageBuilder.php
└── js
│ └── site
│ ├── init.js
│ └── volume.js
├── README.md
└── index.php
/_includes/css/site/screen.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/_includes/icons/apple.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orangespaceman/mac-volume-control-php-js/master/_includes/icons/apple.png
--------------------------------------------------------------------------------
/_includes/icons/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orangespaceman/mac-volume-control-php-js/master/_includes/icons/favicon.ico
--------------------------------------------------------------------------------
/_includes/img/site/loading.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orangespaceman/mac-volume-control-php-js/master/_includes/img/site/loading.png
--------------------------------------------------------------------------------
/_includes/img/site/ajax-loader-black.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orangespaceman/mac-volume-control-php-js/master/_includes/img/site/ajax-loader-black.gif
--------------------------------------------------------------------------------
/_includes/img/site/ajax-loader-white.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orangespaceman/mac-volume-control-php-js/master/_includes/img/site/ajax-loader-white.gif
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # mac-volume-control-php-js
2 |
3 | A PHP-based volume controller for a mac
4 |
5 | ## Post
6 |
7 | [https://f90.co.uk/labs/mac-php-js-volume-control/](https://f90.co.uk/labs/mac-php-js-volume-control/)
8 |
--------------------------------------------------------------------------------
/index.php:
--------------------------------------------------------------------------------
1 | buildPage($volume->volume);
--------------------------------------------------------------------------------
/_includes/php/Ajax.php:
--------------------------------------------------------------------------------
1 | 0) {
3 |
4 | // check what to do
5 | require_once("./Volume.php");
6 | $volume = new Volume;
7 | $method = $_POST['method'];
8 | unset($_POST['method']);
9 |
10 | //
11 | switch ($method) {
12 |
13 | case "getVolume":
14 | $result = $volume->getVolume();
15 | echo json_encode($result);
16 | break;
17 |
18 |
19 | case "setVolume":
20 | $vol = intval($_POST['val']);
21 | $result = $volume->setVolume($vol);
22 | echo json_encode($result);
23 | break;
24 |
25 | }
26 | }
27 |
28 |
--------------------------------------------------------------------------------
/_includes/js/site/init.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Site global JS file
3 | */
4 |
5 | /**
6 | * on Dom ready functionality
7 | */
8 | $(document).ready(function() {
9 |
10 | // add an extra class to the
element for JS-only styling
11 | $("body").addClass("js");
12 |
13 | // hide scroll bar
14 | window.scrollTo(0,1);
15 |
16 | // init vol control
17 | volume.init({
18 | ajaxPath: "./_includes/php/Ajax.php",
19 | interval: 10
20 | });
21 | });
22 |
23 |
24 | /*
25 | * Window load calls for all pages
26 | */
27 | $(window).load(function() {
28 |
29 | });
--------------------------------------------------------------------------------
/_includes/php/Volume.php:
--------------------------------------------------------------------------------
1 | getVolume();
19 | }
20 |
21 |
22 | /*
23 | *
24 | */
25 | function getVolume() {
26 | $this->volume = shell_exec('osascript -e "output volume of (get volume settings)"');
27 | return array("volume" => $this->volume);
28 | }
29 |
30 |
31 | /*
32 | *
33 | */
34 | function setVolume($vol) {
35 | shell_exec("osascript -e 'set volume output volume ".$vol."'");
36 | return $this->getVolume();
37 | }
38 |
39 |
40 | /*
41 | *
42 | */
43 | function mute() {
44 | shell_exec("osascript -e 'set volume output volume 0'");
45 | return $this->getVolume();
46 | }
47 |
48 |
49 | /*
50 | *
51 | */
52 | function volumeUp() {
53 | shell_exec("osascript -e 'set volume output volume (get (output volume of (get volume settings)) + 5)'");
54 | return $this->getVolume();
55 | }
56 |
57 |
58 |
59 | /*
60 | *
61 | */
62 | function volumeDown() {
63 | shell_exec("osascript -e 'set volume output volume (get (output volume of (get volume settings)) - 5)'");
64 | return $this->getVolume();
65 | }
66 | }
--------------------------------------------------------------------------------
/_includes/php/PageBuilder.php:
--------------------------------------------------------------------------------
1 |
22 |
23 |
24 | Volume
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | ';
47 |
48 | // put in volume options
49 | for ($i=0; $i <= 100; $i+=10) {
50 | $return .= '
51 | - '.$i.'
52 | ';
53 | }
54 |
55 | $return .= '
56 |
57 |
61 |
62 |
63 |
64 |
65 | ';
66 |
67 | return $return;
68 | }
69 | }
--------------------------------------------------------------------------------
/_includes/css/site/mobile.css:
--------------------------------------------------------------------------------
1 | /*
2 | * Mobile CSS
3 | */
4 | /* resets */
5 | * { margin:0; padding:0; }
6 |
7 | body {
8 | font:62.5%/1.25 Helvetica, Arial, sans-serif;
9 | background:#000;
10 | }
11 |
12 | ul { list-style:none; }
13 | a { text-decoration:none; }
14 |
15 | /* global */
16 | #horizon {
17 | position:absolute;
18 | left: 0px;
19 | text-align: center;
20 | top: 50%;
21 | width: 100%;
22 | }
23 |
24 | #wrapper {
25 | margin: 0px auto;
26 | position: relative;
27 | text-align: left;
28 | background: -webkit-gradient(linear,left bottom,left top,color-stop(0.09, rgb(0,0,0)),color-stop(0.78, rgb(122,122,122)));
29 | }
30 |
31 |
32 | /* footer */
33 | footer {
34 | overflow:auto;
35 | }
36 |
37 | h1 {
38 | font-size:24px;
39 | color:#f4f4f4;
40 | float:left;
41 | }
42 |
43 | h2 {
44 | float:right;
45 | font-size:16px;
46 | margin:4px 10px 0 0;
47 | }
48 |
49 | h2 a {
50 | display:block;
51 | }
52 |
53 | h2 a span {
54 | display:block;
55 | float:right;
56 | margin:2px 0 0 5px;
57 | width:16px;
58 | height:16px;
59 | border-radius:8px;
60 | }
61 |
62 | h2 a {
63 | color:#ccc;
64 | }
65 | h2 a span,
66 | ul#vol li a span {
67 | background:#ccc;
68 | /*-webkit-box-shadow: 0px 0px 10px #fff;*/
69 | }
70 |
71 | h2 a.mute-on {
72 | color:#0f4;
73 | }
74 | h2 a.mute-on span,
75 | ul#vol li.active a span {
76 | background:#0f4;
77 | -webkit-box-shadow: 0px 0px 20px #0f4;
78 | }
79 |
80 |
81 | /* vol */
82 | ul#vol {
83 | clear:both;
84 | }
85 |
86 | ul#vol li {
87 | float:left;
88 | position:relative;
89 | height:100%;
90 | }
91 |
92 | ul#vol li a,
93 | ul#vol li a span {
94 | display:block;
95 | width:100%;
96 | height:100%;
97 | position:absolute;
98 | left:0;
99 | bottom:0;
100 | /*background:#f90;*/
101 | text-indent:-9999px;
102 | }
103 |
104 | ul#vol li#vol-0 a span { height:1%;}
105 | ul#vol li#vol-10 a span { height:10%;}
106 | ul#vol li#vol-20 a span { height:20%;}
107 | ul#vol li#vol-30 a span { height:30%;}
108 | ul#vol li#vol-40 a span { height:40%;}
109 | ul#vol li#vol-50 a span { height:50%;}
110 | ul#vol li#vol-60 a span { height:60%;}
111 | ul#vol li#vol-70 a span { height:70%;}
112 | ul#vol li#vol-80 a span { height:80%;}
113 | ul#vol li#vol-90 a span { height:90%;}
114 | ul#vol li#vol-100 a span { height:100%;}
115 |
116 | ul#vol li#vol-80.active a span {
117 | background:#fe0;
118 | -webkit-box-shadow: 0px 0px 20px #fe0;
119 | }
120 | ul#vol li#vol-90.active a span {
121 | background:#f90;
122 | -webkit-box-shadow: 0px 0px 20px #f90;
123 | }
124 | ul#vol li#vol-100.active a span {
125 | background:#f00;
126 | -webkit-box-shadow: 0px 0px 20px #f00;
127 | }
128 |
129 |
130 | /* loader */
131 | span#loading {
132 | position:absolute;
133 | right:10px;
134 | bottom:10px;
135 | display:block;
136 | width:16px;
137 | height:16px;
138 | background-image:url(../../img/site/ajax-loader-black.gif);
139 | background-position:right bottom;
140 | background-repeat:no-repeat;
141 | display:none;
142 | }
143 |
144 | span#loading.show {
145 | display:block;
146 | }
147 |
148 |
149 | /* landscape (as default) */
150 | /*@media (max-width: 480px) {*/
151 | #horizon {
152 | margin-top:-160px;
153 | }
154 |
155 | #wrapper {
156 | width:480px;
157 | height:320px;
158 | }
159 |
160 | ul#vol {
161 | padding-top:50px;
162 | height:200px;
163 | margin:0 30px 20px 30px;
164 | }
165 |
166 | ul#vol li {
167 | width:30px;
168 | margin-right:7px;
169 | }
170 |
171 | h2 {
172 | margin-right:20px;
173 | }
174 |
175 | footer {
176 | width:420px;
177 | margin:0 auto;
178 | }
179 | /*}*/
180 |
181 | /* portrait */
182 | @media (max-width: 320px) {
183 |
184 | #horizon {
185 | min-width: 320px;
186 | margin-top: -240px;
187 | }
188 |
189 | #wrapper {
190 | width:320px;
191 | height:480px;
192 | }
193 |
194 | ul#vol {
195 | width:300px;
196 | height:340px;
197 | margin:0 auto 20px auto;
198 | padding-top:50px;
199 | }
200 |
201 | ul#vol li {
202 | width:20px;
203 | margin-right:7px;
204 | }
205 |
206 | h2 {
207 | margin-right:10px;
208 | }
209 |
210 | footer {
211 | width:300px;
212 | margin:0 auto;
213 | }
214 | }
--------------------------------------------------------------------------------
/_includes/js/site/volume.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @fileoverview Volume
3 | *
4 | */
5 | var volume = function(){
6 |
7 | // obj: volume text element
8 | var $volText = null,
9 |
10 |
11 | // obj: volume checking interval
12 | volInterval = null,
13 |
14 |
15 | // int: current volume
16 | currentVolume = null,
17 |
18 |
19 | // bool: is currently muted?
20 | isMuted = false,
21 |
22 |
23 | // int: volume before mute was pressed
24 | preMutedVolume = null,
25 |
26 |
27 | // obj: loading element
28 | loader = null,
29 |
30 |
31 | // array - volume blocks
32 | $volumeBlocks = null;
33 |
34 |
35 | /**
36 | * The options passed through to this function
37 | *
38 | * @var Object
39 | * @private
40 | */
41 | var options = {
42 |
43 | /**
44 | * The location of the AJAX script on the server
45 | *
46 | * @var String
47 | */
48 | ajaxPath : null,
49 |
50 | /**
51 | * The interval time (in seconds) between volume checks
52 | *
53 | *
54 | */
55 | interval : 10
56 | };
57 |
58 |
59 | /**
60 | * Initialise the functionality
61 | * @param {Object} options The initialisation options
62 | * @return void
63 | * @public
64 | */
65 | var init = function(initOptions) {
66 |
67 | // save any options sent through to the intialisation script, if set
68 | for (var option in options) {
69 | if (!!initOptions[option] || initOptions[option] === false) {
70 | options[option] = initOptions[option];
71 | }
72 |
73 | // error check, if no element is specified then stop
74 | if (!options[option] && options[option] !== false && options[option] !== 0) {
75 | throw('Required option not specified: ' + option);
76 | //return false;
77 | }
78 | }
79 |
80 | // get volume text element
81 | $volText = $("#volume-level");
82 |
83 |
84 | // get current volume
85 | currentVolume = $volText.text();
86 |
87 |
88 | // get all volume blocks
89 | $volumeBlocks = $("ul#vol a");
90 |
91 |
92 | // set volume controls
93 | $volumeBlocks.bind('click', function(e){
94 | e.preventDefault();
95 | this.blur();
96 | setVolumeFromBlock(this);
97 | });
98 |
99 |
100 | // set up mute
101 | $("h2#mute a").bind('click', function(e){
102 | e.preventDefault();
103 | this.blur();
104 | mutePressed(this);
105 | });
106 |
107 |
108 | // add loader
109 | loader = $("").attr('id', 'loading').appendTo('#wrapper');
110 |
111 |
112 | // set up initial volume blocks
113 | adjustBlocks();
114 |
115 |
116 | // check volume every x seconds
117 | volInterval = setInterval(getVolume, options.interval * 1000);
118 | };
119 |
120 |
121 | /*
122 | *
123 | */
124 | var mutePressed = function(el) {
125 |
126 | // condition : mute?
127 | if (!isMuted) {
128 | isMuted = true;
129 | preMutedVolume = currentVolume;
130 | setVolume(0);
131 | $(el).addClass('mute-on');
132 |
133 | // restore volume
134 | } else {
135 | isMuted = false;
136 | setVolume(preMutedVolume);
137 | preMutedVolume = null;
138 | $(el).removeClass('mute-on');
139 | }
140 | };
141 |
142 |
143 |
144 | /*
145 | *
146 | */
147 | var getVolume = function() {
148 | _ajax("getVolume");
149 | };
150 |
151 |
152 |
153 | /*
154 | *
155 | */
156 | var setVolume = function(vol) {
157 | _ajax("setVolume", vol);
158 | };
159 |
160 |
161 |
162 | /*
163 | *
164 | */
165 | var _ajax = function(method, val) {
166 |
167 | showLoader();
168 |
169 | var postData, response;
170 |
171 | postData = 'method='+method;
172 |
173 | if (!!val) {
174 | postData += '&val='+val;
175 | }
176 |
177 | postData += '&random='+Math.random();
178 |
179 | // submit request
180 | response = $.post(
181 | options.ajaxPath,
182 | postData,
183 | function(data, textStatus){
184 |
185 | var result = $.parseJSON(data);
186 | currentVolume = result.volume;
187 | $volText.text(result.volume);
188 |
189 | adjustBlocks();
190 |
191 | hideLoader();
192 |
193 | //console.log(result);
194 |
195 | });
196 | };
197 |
198 |
199 | /*
200 | *
201 | */
202 | var adjustBlocks = function() {
203 |
204 | $volumeBlocks.each(function(counter){
205 | var $block = $(this);
206 | var blockVolume = parseInt($block.parent().attr('id').split('-')[1], 10);
207 | if ((blockVolume-2) <= currentVolume) {
208 | $block.parent().addClass('active');
209 | } else {
210 | $block.parent().removeClass('active');
211 | }
212 | });
213 | };
214 |
215 |
216 | /*
217 | *
218 | */
219 | var setVolumeFromBlock = function(el) {
220 | $block = $(el);
221 | var blockVolume = parseInt($block.parent().attr('id').split('-')[1], 10);
222 | setVolume(blockVolume);
223 | };
224 |
225 |
226 | /*
227 | *
228 | */
229 | var showLoader = function() {
230 |
231 | loader.addClass('show');
232 |
233 | };
234 |
235 |
236 |
237 | /*
238 | *
239 | */
240 | var hideLoader = function() {
241 |
242 | loader.removeClass('show');
243 |
244 | };
245 |
246 |
247 |
248 | /**
249 | * Return value, expose certain methods above
250 | */
251 | return {
252 | init: init
253 | };
254 | }();
--------------------------------------------------------------------------------