AzuraCast/src/Radio/Frontend/SHOUTcast.php

177 lines
5.3 KiB
PHP
Raw Normal View History

<?php
namespace App\Radio\Frontend;
use App\Entity;
2020-07-08 09:03:50 +02:00
use Exception;
use NowPlaying\Result\Result;
use Psr\Http\Message\UriInterface;
use Symfony\Component\Process\Process;
class SHOUTcast extends AbstractFrontend
{
public function supportsMounts(): bool
2019-09-04 20:00:51 +02:00
{
return true;
}
public function supportsListenerDetail(): bool
{
return true;
}
public function getVersion(): ?string
{
$binary_path = $this->getBinary();
2019-09-04 20:00:51 +02:00
if (!$binary_path) {
return null;
}
$process = new Process([$binary_path, '--version']);
$process->setWorkingDirectory(dirname($binary_path));
$process->run();
if (!$process->isSuccessful()) {
return null;
}
return trim($process->getOutput());
}
/**
* @inheritDoc
*/
public function getBinary(): string
2019-09-04 20:00:51 +02:00
{
$new_path = '/var/azuracast/servers/shoutcast2/sc_serv';
2019-09-04 20:00:51 +02:00
// Docker versions before 3 included the SC binary across the board.
if ($this->environment->isDocker() && !$this->environment->isDockerRevisionAtLeast(3)) {
2019-09-04 20:00:51 +02:00
return $new_path;
}
return file_exists($new_path)
? $new_path
: false;
}
public function getNowPlaying(Entity\Station $station, bool $includeClients = true): Result
{
$feConfig = $station->getFrontendConfig();
$radioPort = $feConfig->getPort();
$baseUrl = 'http://' . ($this->environment->isDocker() ? 'stations' : 'localhost') . ':' . $radioPort;
2021-04-12 00:33:51 +02:00
$npAdapter = $this->adapterFactory->getShoutcast2Adapter($baseUrl);
$npAdapter->setAdminPassword($feConfig->getAdminPassword());
$defaultResult = Result::blank();
$otherResults = [];
$sid = 0;
foreach ($station->getMounts() as $mount) {
$sid++;
try {
$result = $npAdapter->getNowPlaying((string)$sid, $includeClients);
if (!empty($result->clients)) {
foreach ($result->clients as $client) {
$client->mount = 'local_' . $mount->getId();
}
}
} catch (Exception $e) {
$this->logger->error(sprintf('NowPlaying adapter error: %s', $e->getMessage()));
$result = Result::blank();
}
$mount->setListenersTotal($result->listeners->total);
$mount->setListenersUnique($result->listeners->unique);
$this->em->persist($mount);
if ($mount->getIsDefault()) {
$defaultResult = $result;
} else {
$otherResults[] = $result;
}
}
$this->em->flush();
foreach ($otherResults as $otherResult) {
$defaultResult = $defaultResult->merge($otherResult);
}
return $defaultResult;
}
public function getConfigurationPath(Entity\Station $station): ?string
{
return $station->getRadioConfigDir() . '/sc_serv.conf';
}
public function getCurrentConfiguration(Entity\Station $station): ?string
2019-09-04 20:00:51 +02:00
{
$configPath = $station->getRadioConfigDir();
$frontendConfig = $station->getFrontendConfig();
$config = [
'password' => $frontendConfig->getSourcePassword(),
'adminpassword' => $frontendConfig->getAdminPassword(),
'logfile' => $configPath . '/sc_serv.log',
'w3clog' => $configPath . '/sc_w3c.log',
'banfile' => $this->writeIpBansFile($station),
'ripfile' => $configPath . '/sc_serv.rip',
'maxuser' => $frontendConfig->getMaxListeners() ?? 250,
'portbase' => $frontendConfig->getPort(),
'requirestreamconfigs' => 1,
2019-09-04 20:00:51 +02:00
];
$customConfig = $frontendConfig->getCustomConfiguration();
if (!empty($customConfig)) {
$custom_conf = $this->processCustomConfig($customConfig);
if (!empty($custom_conf)) {
$config = array_merge($config, $custom_conf);
}
}
$i = 0;
foreach ($station->getMounts() as $mount_row) {
/** @var Entity\StationMount $mount_row */
$i++;
2019-09-04 20:00:51 +02:00
$config['streamid_' . $i] = $i;
$config['streampath_' . $i] = $mount_row->getName();
if ($mount_row->getRelayUrl()) {
2019-09-04 20:00:51 +02:00
$config['streamrelayurl_' . $i] = $mount_row->getRelayUrl();
}
if ($mount_row->getAuthhash()) {
$config['streamauthhash_' . $i] = $mount_row->getAuthhash();
}
}
$configFileOutput = '';
foreach ($config as $config_key => $config_value) {
$configFileOutput .= $config_key . '=' . str_replace("\n", '', $config_value) . "\n";
}
return $configFileOutput;
}
2019-09-04 20:00:51 +02:00
public function getCommand(Entity\Station $station): ?string
{
if ($binary = $this->getBinary()) {
return $binary . ' ' . $this->getConfigurationPath($station);
2019-09-04 20:00:51 +02:00
}
return null;
2019-09-04 20:00:51 +02:00
}
public function getAdminUrl(Entity\Station $station, UriInterface $base_url = null): UriInterface
{
$public_url = $this->getPublicUrl($station, $base_url);
return $public_url
->withPath($public_url->getPath() . '/admin.cgi');
}
}