console and play command
This commit is contained in:
parent
98c1952938
commit
4ad5d79f00
|
@ -4,10 +4,12 @@
|
||||||
require_once __DIR__ . '/../vendor/autoload.php';
|
require_once __DIR__ . '/../vendor/autoload.php';
|
||||||
|
|
||||||
use Deblan\Application;
|
use Deblan\Application;
|
||||||
|
use Deblan\ConfigLoader;
|
||||||
|
|
||||||
$app = new Application('LiveCoding CLI', '1');
|
$app = new Application('LiveCoding CLI', '1');
|
||||||
|
|
||||||
$app->chdir(__DIR__.'/../');
|
$app->chdir(__DIR__.'/../');
|
||||||
$app->addCommandsPath('src/Deblan/Command/', 'Deblan\\Command');
|
$app->addCommandsPath('src/Deblan/Command/', 'Deblan\\Command');
|
||||||
$app->loadCommands();
|
$app->loadCommands();
|
||||||
|
$app->setConfigLoader(new ConfigLoader());
|
||||||
$app->run();
|
$app->run();
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
"require": {
|
"require": {
|
||||||
"symfony/filesystem": "^2.7",
|
"symfony/filesystem": "^2.7",
|
||||||
"symfony/finder": "^2.7",
|
"symfony/finder": "^2.7",
|
||||||
"symfony/console": "^2.7"
|
"symfony/console": "^2.7",
|
||||||
|
"symfony/yaml": "^2.7",
|
||||||
|
"symfony/process": "^2.7"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
namespace Deblan;
|
namespace Deblan;
|
||||||
|
|
||||||
|
use ReflectionClass;
|
||||||
|
use ReflectionException;
|
||||||
use Symfony\Component\Console\Application as BaseApplication;
|
use Symfony\Component\Console\Application as BaseApplication;
|
||||||
use Symfony\Component\Finder\Finder;
|
use Symfony\Component\Finder\Finder;
|
||||||
|
|
||||||
|
@ -11,7 +13,9 @@ use Symfony\Component\Finder\Finder;
|
||||||
*/
|
*/
|
||||||
class Application extends BaseApplication
|
class Application extends BaseApplication
|
||||||
{
|
{
|
||||||
protected $commandsPaths = array();
|
protected $commandsPaths = [];
|
||||||
|
|
||||||
|
protected $configLoader;
|
||||||
|
|
||||||
public function addCommandsPath($path, $namespace)
|
public function addCommandsPath($path, $namespace)
|
||||||
{
|
{
|
||||||
|
@ -54,5 +58,45 @@ class Application extends BaseApplication
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
public function setConfigLoader(ConfigLoader $configLoader)
|
||||||
|
{
|
||||||
|
$this->configLoader = $configLoader;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getConfigLoader()
|
||||||
|
{
|
||||||
|
return $this->configLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildUrl($uri = '')
|
||||||
|
{
|
||||||
|
return sprintf('https://www.livecoding.tv/%s', ltrim($uri, '/'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildStreamUrl($stream)
|
||||||
|
{
|
||||||
|
return sprintf(
|
||||||
|
'rtmp://eumedia1.livecoding.tv:1935/livecodingtv/%s',
|
||||||
|
trim($stream, '/')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPlayer($stream)
|
||||||
|
{
|
||||||
|
$stream = $this->buildStreamUrl($stream);
|
||||||
|
|
||||||
|
return str_replace(
|
||||||
|
'%stream%',
|
||||||
|
escapeshellarg($stream),
|
||||||
|
$this->getConfigLoader()->getConfig()['player']['command']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isDebugMode()
|
||||||
|
{
|
||||||
|
return $this->getConfigLoader()->getConfig()['debug'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
79
src/Deblan/Command/PlayCommand.php
Normal file
79
src/Deblan/Command/PlayCommand.php
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Deblan\Command;
|
||||||
|
|
||||||
|
use RuntimeException;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Process\Process;
|
||||||
|
|
||||||
|
class PlayCommand extends Command
|
||||||
|
{
|
||||||
|
protected function configure()
|
||||||
|
{
|
||||||
|
$this
|
||||||
|
->setName('play')
|
||||||
|
->setDescription('Play a stream')
|
||||||
|
->addArgument('stream', InputArgument::REQUIRED, 'Name of the stream')
|
||||||
|
// ->addOption('bar', null, InputOption::VALUE_NONE, '')
|
||||||
|
->setHelp("The <info>%command.name%</info> ");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output)
|
||||||
|
{
|
||||||
|
$config = $this->getApplication()->getConfigLoader()->getConfig();
|
||||||
|
$stream = trim($input->getArgument('stream'), "/ \r\n");
|
||||||
|
|
||||||
|
if (0 === preg_match('/^\w+$/', $stream)) {
|
||||||
|
$output->writeln('<error>The stream name is not valid.');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$output->writeln(sprintf('Playing <comment>%s</comment>', $stream));
|
||||||
|
|
||||||
|
if (!empty($config['player']['before'])) {
|
||||||
|
$command = $config['player']['before'];
|
||||||
|
// $process = new Process($command);
|
||||||
|
// $process->run();
|
||||||
|
}
|
||||||
|
|
||||||
|
$hash = $this->getHash($this->getApplication()->buildUrl($stream.'/'));
|
||||||
|
$command = $this->getApplication()->getPlayer($stream.'?t='.$hash);
|
||||||
|
$process = new Process($command);
|
||||||
|
|
||||||
|
if ($this->getApplication()->isDebugMode()) {
|
||||||
|
$callback = function ($type, $buffer) use ($output) {
|
||||||
|
if ('err' !== $type) {
|
||||||
|
$output->writeln($buffer);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
$callback = function ($type, $buffer) use ($output) {
|
||||||
|
if ('err' === $type) {
|
||||||
|
$output->writeln(sprintf('<error>%s</error>', $buffer));
|
||||||
|
} else {
|
||||||
|
$output->writeln($buffer);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
$process->run($callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getHash($streamUrl)
|
||||||
|
{
|
||||||
|
$page = file_get_contents($streamUrl);
|
||||||
|
|
||||||
|
preg_match('/var streamURL = ".+\?t=([^"]+)"/s', $page, $match);
|
||||||
|
|
||||||
|
if (!isset($match[1])) {
|
||||||
|
throw new RuntimeException('Hash is not accessible.');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $match[1];
|
||||||
|
}
|
||||||
|
}
|
39
src/Deblan/ConfigLoader.php
Normal file
39
src/Deblan/ConfigLoader.php
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Deblan;
|
||||||
|
|
||||||
|
use Symfony\Component\Filesystem\Filesystem;
|
||||||
|
use Symfony\Component\Yaml\Yaml;
|
||||||
|
|
||||||
|
class ConfigLoader
|
||||||
|
{
|
||||||
|
protected $configFile;
|
||||||
|
|
||||||
|
protected $filesystem;
|
||||||
|
|
||||||
|
public function __construct($configFile = 'app/config.yml')
|
||||||
|
{
|
||||||
|
$this->configFile = $configFile;
|
||||||
|
$this->filesystem = new Filesystem();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function configExists()
|
||||||
|
{
|
||||||
|
return $this->filesystem->exists($this->configFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function save(array $data)
|
||||||
|
{
|
||||||
|
$config = array_merge(
|
||||||
|
$this->getConfig(),
|
||||||
|
$data
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->filesystem->dumpFile($this->configFile, Yaml::dump($config));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getConfig()
|
||||||
|
{
|
||||||
|
return $this->configExists() ? Yaml::parse($this->configFile) : [];
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue