|
|
@ -0,0 +1,257 @@ |
|
|
|
#!/usr/bin/php |
|
|
|
<?php |
|
|
|
|
|
|
|
function error($message) |
|
|
|
{ |
|
|
|
file_put_contents('php://stderr', $message."\n"); |
|
|
|
} |
|
|
|
|
|
|
|
function notice($message) |
|
|
|
{ |
|
|
|
file_put_contents('php://stdin', $message."\n"); |
|
|
|
} |
|
|
|
|
|
|
|
function filter(array $data, array $default) |
|
|
|
{ |
|
|
|
foreach ($data as $k => $v) { |
|
|
|
if (!array_key_exists($k, $default)) { |
|
|
|
unset($data[$k]); |
|
|
|
} elseif (is_array($default[$k]) && !is_array($v)) { |
|
|
|
$data[$k] = (array) $v; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
foreach ($default as $k => $v) { |
|
|
|
if (!array_key_exists($k, $data)) { |
|
|
|
$data[$k] = $v; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return $data; |
|
|
|
} |
|
|
|
|
|
|
|
function filterScreen(array $data) |
|
|
|
{ |
|
|
|
$default = [ |
|
|
|
'name' => null, |
|
|
|
'resolutionX' => null, |
|
|
|
'resolutionY' => null, |
|
|
|
]; |
|
|
|
|
|
|
|
return filter($data, $default); |
|
|
|
} |
|
|
|
|
|
|
|
function filterMode(array $data) |
|
|
|
{ |
|
|
|
$default = [ |
|
|
|
'config' => [], |
|
|
|
'primary' => null, |
|
|
|
]; |
|
|
|
|
|
|
|
$data = filter($data, $default); |
|
|
|
|
|
|
|
foreach ($data['config'] as $k => $v) { |
|
|
|
$v = explode(',', $v); |
|
|
|
$v = array_map('trim', $v); |
|
|
|
|
|
|
|
$data['config'][$k] = $v; |
|
|
|
} |
|
|
|
|
|
|
|
return $data; |
|
|
|
} |
|
|
|
|
|
|
|
function getCurrentModeFile() |
|
|
|
{ |
|
|
|
return sys_get_temp_dir().'/monitordisplay.tmp'; |
|
|
|
} |
|
|
|
|
|
|
|
function getCurrentMode() |
|
|
|
{ |
|
|
|
$currentModeFile = getCurrentModeFile(); |
|
|
|
|
|
|
|
if (file_exists($currentModeFile)) { |
|
|
|
$currentMode = (array) @parse_ini_file($currentModeFile); |
|
|
|
} else { |
|
|
|
$currentMode = []; |
|
|
|
} |
|
|
|
|
|
|
|
return filter($currentMode, [ |
|
|
|
'mode' => null, |
|
|
|
'config' => null, |
|
|
|
]); |
|
|
|
} |
|
|
|
|
|
|
|
function build(array $modes, array $screens, $mode, $toggle, array $currentMode, $addOff) |
|
|
|
{ |
|
|
|
if ($mode === null) { |
|
|
|
if (!array_key_exists($currentMode['mode'], $modes)) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
$tmpMode = $currentMode['mode']; |
|
|
|
$mode = $modes[$currentMode['mode']]; |
|
|
|
} else { |
|
|
|
if (!array_key_exists($mode, $modes)) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
$tmpMode = $mode; |
|
|
|
$mode = $modes[$mode]; |
|
|
|
} |
|
|
|
|
|
|
|
if ($toggle === true) { |
|
|
|
if ($currentMode['mode'] === null) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if ($currentMode['config'] === null) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
$currentMode['config'] = (int) $currentMode['config']; |
|
|
|
|
|
|
|
if (!array_key_exists($currentMode['config'], $mode['config'])) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
$configs = $mode['config']; |
|
|
|
$config = ($currentMode['config'] + 1) % count($configs); |
|
|
|
} else { |
|
|
|
$config = 0; |
|
|
|
} |
|
|
|
|
|
|
|
if (!array_key_exists($config, $mode['config'])) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
$tmpConfig = $config; |
|
|
|
$config = $mode['config'][$config]; |
|
|
|
|
|
|
|
$command = ['xrandr']; |
|
|
|
|
|
|
|
$x = 0; |
|
|
|
|
|
|
|
$screensUsed = []; |
|
|
|
|
|
|
|
foreach ($config as $screen) { |
|
|
|
if (!array_key_exists($screen, $screens)) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
$tScreen = $screens[$screen]; |
|
|
|
$name = $tScreen['name']; |
|
|
|
$resolutionX = $tScreen['resolutionX']; |
|
|
|
$resolutionY = $tScreen['resolutionY']; |
|
|
|
|
|
|
|
if (empty($name) || empty($resolutionX) || empty($resolutionY)) { |
|
|
|
error(sprintf('Invalid screen configuration "%s"', $screen)); |
|
|
|
die(1); |
|
|
|
} |
|
|
|
|
|
|
|
$command[] = '--output'; |
|
|
|
$command[] = $name; |
|
|
|
$screensUsed[] = $name; |
|
|
|
|
|
|
|
if ($mode['primary'] === $name) { |
|
|
|
$command[] = '--primary'; |
|
|
|
} |
|
|
|
|
|
|
|
$command[] = '--mode'; |
|
|
|
$command[] = sprintf('%dx%d', $resolutionX, $resolutionY); |
|
|
|
|
|
|
|
$command[] = '--pos'; |
|
|
|
$command[] = sprintf('%dx%d', $x, 0); |
|
|
|
$x += $resolutionX; |
|
|
|
} |
|
|
|
|
|
|
|
if ($addOff) { |
|
|
|
foreach ($screens as $screen) { |
|
|
|
if (!in_array($screen['name'], $screensUsed)) { |
|
|
|
$command[] = '--output'; |
|
|
|
$command[] = $screen['name']; |
|
|
|
$command[] = '--off'; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
$command = implode(' ', $command); |
|
|
|
|
|
|
|
return [ |
|
|
|
'tmp' => sprintf("mode=%s\nconfig=%d", $tmpMode, $tmpConfig), |
|
|
|
'command' => $command, |
|
|
|
]; |
|
|
|
} |
|
|
|
|
|
|
|
$files = [ |
|
|
|
'/etc/monitordisplay/config.ini', |
|
|
|
getenv('HOME').'/.config/monitordisplay/config.ini', |
|
|
|
getenv('HOME').'/.monitordisplay', |
|
|
|
]; |
|
|
|
|
|
|
|
$config = []; |
|
|
|
$currentMode = getCurrentMode(); |
|
|
|
|
|
|
|
foreach ($files as $file) { |
|
|
|
if (file_exists($file)) { |
|
|
|
$parsing = @parse_ini_file($file, true); |
|
|
|
|
|
|
|
if ($parsing === false) { |
|
|
|
error(sprintf('The file "%s" is not a valid ini file.', $file)); |
|
|
|
|
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
notice(sprintf('Configuration file merged: %s', $file)); |
|
|
|
|
|
|
|
$config = array_merge( |
|
|
|
$config, |
|
|
|
$parsing |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (empty($config)) { |
|
|
|
error('No configuration found'); |
|
|
|
error(sprintf('Paths checked: %s', implode(', ', $files))); |
|
|
|
die(1); |
|
|
|
} |
|
|
|
|
|
|
|
$screens = []; |
|
|
|
$modes = []; |
|
|
|
|
|
|
|
foreach ($config as $section => $values) { |
|
|
|
$type = explode(':', $section); |
|
|
|
|
|
|
|
if (count($type) !== 2) { |
|
|
|
error(sprintf('Invalid section "%s". Ignored.', $section)); |
|
|
|
} |
|
|
|
|
|
|
|
if ($type[0] === 'screen') { |
|
|
|
$screens[$type[1]] = filterScreen($values); |
|
|
|
} elseif ($type[0] === 'mode') { |
|
|
|
$modes[$type[1]] = filterMode($values); |
|
|
|
} else { |
|
|
|
error(sprintf('Invalid section "%s". Ignored.', $section)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (empty($screens)) { |
|
|
|
error('No screen found.'); |
|
|
|
die(1); |
|
|
|
} |
|
|
|
|
|
|
|
if (empty($modes)) { |
|
|
|
error('No mode found.'); |
|
|
|
die(1); |
|
|
|
} |
|
|
|
|
|
|
|
$options = getopt('m:ts'); |
|
|
|
$mode = isset($options['m']) ? $options['m'] : null; |
|
|
|
$toggle = isset($options['t']); |
|
|
|
$addOff = !isset($options['s']); |
|
|
|
$build = build($modes, $screens, $mode, $toggle, $currentMode, $addOff); |
|
|
|
|
|
|
|
if (!empty($build)) { |
|
|
|
file_put_contents(getCurrentModeFile(), $build['tmp']); |
|
|
|
shell_exec($build['command']); |
|
|
|
} |