From 91c10d05ad1a56112978317fe5084dcb43b7c513 Mon Sep 17 00:00:00 2001 From: Daniil Gentili Date: Sun, 29 Nov 2020 20:02:50 +0100 Subject: [PATCH] Bugfixes --- src/danog/MadelineProto/Settings.php | 40 +++++++++ src/danog/MadelineProto/Settings/VoIP.php | 40 +++++++++ src/danog/MadelineProto/VoIP.php | 81 +++++++++++++++---- .../MadelineProto/VoIP/MessageHandler.php | 2 +- 4 files changed, 146 insertions(+), 17 deletions(-) create mode 100644 src/danog/MadelineProto/Settings/VoIP.php diff --git a/src/danog/MadelineProto/Settings.php b/src/danog/MadelineProto/Settings.php index 1a5530b0f..35035655b 100644 --- a/src/danog/MadelineProto/Settings.php +++ b/src/danog/MadelineProto/Settings.php @@ -20,6 +20,7 @@ use danog\MadelineProto\Settings\SecretChats; use danog\MadelineProto\Settings\Serialization; use danog\MadelineProto\Settings\Templates; use danog\MadelineProto\Settings\TLSchema; +use danog\MadelineProto\Settings\VoIP; /** * Settings class used for configuring MadelineProto. @@ -82,6 +83,10 @@ class Settings extends SettingsAbstract * Template settings. */ protected Templates $templates; + /** + * VoIP settings. + */ + protected VoIP $voip; /** * Create settings object from possibly legacy settings array. @@ -125,6 +130,13 @@ class Settings extends SettingsAbstract $this->db = new DatabaseMemory; $this->templates = new Templates; $this->ipc = new IPc; + $this->voip = new VoIP; + } + public function __wakeup() + { + if (!isset($this->voip)) { + $this->voip = new VoIP; + } } /** * Merge legacy array settings. @@ -149,6 +161,7 @@ class Settings extends SettingsAbstract $this->serialization->mergeArray($settings); $this->schema->mergeArray($settings); $this->ipc->mergeArray($settings); + $this->voip->mergeArray($settings); switch ($settings['db']['type'] ?? 'memory') { case 'memory': @@ -203,6 +216,8 @@ class Settings extends SettingsAbstract $this->ipc->merge($settings); } elseif ($settings instanceof Templates) { $this->templates->merge($settings); + } elseif ($settings instanceof VoIP) { + $this->voip->merge($settings); } elseif ($settings instanceof DatabaseAbstract) { if (!$this->db instanceof $settings) { $this->db = $settings; @@ -225,6 +240,7 @@ class Settings extends SettingsAbstract $this->schema->merge($settings->schema); $this->ipc->merge($settings->ipc); $this->templates->merge($settings->templates); + $this->voip->merge($settings->voip); if (!$this->db instanceof $settings->db) { $this->db = $settings->db; @@ -610,4 +626,28 @@ class Settings extends SettingsAbstract return $this; } + + /** + * Get voIP settings. + * + * @return VoIP + */ + public function getVoip(): VoIP + { + return $this->voip; + } + + /** + * Set voIP settings. + * + * @param VoIP $voip VoIP settings. + * + * @return self + */ + public function setVoip(VoIP $voip): self + { + $this->voip = $voip; + + return $this; + } } diff --git a/src/danog/MadelineProto/Settings/VoIP.php b/src/danog/MadelineProto/Settings/VoIP.php new file mode 100644 index 000000000..ff2cb440c --- /dev/null +++ b/src/danog/MadelineProto/Settings/VoIP.php @@ -0,0 +1,40 @@ +preloadAudio; + } + + /** + * Set whether to preload all songs in memory. + * + * @param bool $preloadAudio Whether to preload all songs in memory + * + * @return self + */ + public function setPreloadAudio(bool $preloadAudio): self + { + $this->preloadAudio = $preloadAudio; + + return $this; + } +} diff --git a/src/danog/MadelineProto/VoIP.php b/src/danog/MadelineProto/VoIP.php index 3ff0da685..c7ae34aee 100644 --- a/src/danog/MadelineProto/VoIP.php +++ b/src/danog/MadelineProto/VoIP.php @@ -132,7 +132,7 @@ class VoIP private $protocol; private $visualization; private $holdFiles = []; - private $inputFiles; + private $inputFiles = []; private $outputFile; private $isPlaying = false; @@ -247,6 +247,7 @@ class VoIP if ($this->callState === self::CALL_STATE_ENDED || empty($this->configuration)) { return false; } + $this->callState = self::CALL_STATE_ENDED; Logger::log("Now closing $this"); if (isset($this->timeoutWatcher)) { Loop::cancel($this->timeoutWatcher); @@ -349,6 +350,17 @@ class VoIP case self::PKT_INIT_ACK: yield from $this->startWriteLoop($socket); break; + case self::PKT_STREAM_DATA: + $cnt = 1; + break; + case self::PKT_STREAM_DATA_X2: + $cnt = 2; + break; + case self::PKT_STREAM_DATA_X3: + $cnt = 3; + break; + } + if (isset($cnt)) { } } /** @@ -359,37 +371,74 @@ class VoIP */ private function startWriteLoop(Endpoint $socket): \Generator { - if ($this->voip_state !== self::STATE_ESTABLISHED) { - $this->voip_state = self::STATE_ESTABLISHED; + if ($this->voip_state === self::STATE_ESTABLISHED) { + return; + } + $this->voip_state = self::STATE_ESTABLISHED; - $ctx = new ConnectionContext; - $ctx->addStream(FileBufferedStream::class, yield open('kda.opus', 'r')); - $stream = yield from $ctx->getStream(); - $ogg = yield from Ogg::init($stream, 60000); - $it = $ogg->getEmitter()->iterate(); - Tools::callFork($ogg->read()); - Tools::callFork((function () use ($it, $socket) { - $timestamp = 0; - $frames = []; + $holdFiles = []; + $timestamp = 0; + while (true) { + $file = \array_shift($this->inputFiles); + if (!$file) { + if (empty($holdFiles)) { + $holdFiles = $this->holdFiles; + } + if (empty($holdFiles)) { + return; + } + $file = \array_shift($holdFiles); + } + $it = yield from $this->openFile($file); + $frames = []; + if ($this->MadelineProto->getSettings()->getVoip()->getPreloadAudio()) { while (yield $it->advance()) { $frames []= $it->getCurrent(); } - foreach ($frames as $k => $frame) { + foreach ($frames as $frame) { $t = (\microtime(true) / 1000) + 60; if (!yield $this->send_message(['_' => self::PKT_STREAM_DATA, 'stream_id' => 0, 'data' => $frame, 'timestamp' => $timestamp], $socket)) { Logger::log("Exiting VoIP write loop in $this!"); return; } - - Logger::log("Writing $k in $this!"); + //Logger::log("Writing $timestamp in $this!"); yield new Delayed((int) ($t - (\microtime(true) / 1000))); $timestamp += 60; } - })()); + } else { + while (yield $it->advance()) { + $t = (\microtime(true) / 1000) + 60; + if (!yield $this->send_message(['_' => self::PKT_STREAM_DATA, 'stream_id' => 0, 'data' => $it->getCurrent(), 'timestamp' => $timestamp], $socket)) { + Logger::log("Exiting VoIP write loop in $this!"); + return; + } + + //Logger::log("Writing $timestamp in $this!"); + yield new Delayed((int) ($t - (\microtime(true) / 1000))); + + $timestamp += 60; + } + } } } + /** + * Open OGG file for reading. + * + * @param string $file + * @return \Generator + */ + private function openFile(string $file): \Generator + { + $ctx = new ConnectionContext; + $ctx->addStream(FileBufferedStream::class, yield open($file, 'r')); + $stream = yield from $ctx->getStream(); + $ogg = yield from Ogg::init($stream, 60000); + $it = $ogg->getEmitter()->iterate(); + Tools::callFork($ogg->read()); + return $it; + } /** * Play file. * diff --git a/src/danog/MadelineProto/VoIP/MessageHandler.php b/src/danog/MadelineProto/VoIP/MessageHandler.php index 97362178d..5b76913cd 100644 --- a/src/danog/MadelineProto/VoIP/MessageHandler.php +++ b/src/danog/MadelineProto/VoIP/MessageHandler.php @@ -328,7 +328,7 @@ trait MessageHandler } } if (!$this->received_packet($in_seq_no, $out_seq_no, $ack_mask)) { - return false; + return yield from $this->recv_message($endpoint); } switch ($result['_']) { // streamTypeSimple codec:int8 = StreamType;