Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add M3U format #3998

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions formats/M3uFormat.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php

/**
* M3U
*
*/
class M3uFormat extends FormatAbstract
{
const MIME_TYPE = 'application/mpegurl';
private $item_duration = null;
private $item_title = null;
private $item_url = null;
private $item_bytes = null;

private function resetItem()
{
$this->item_duration = null;
$this->item_title = null;
$this->item_url = null;
$this->item_bytes = null;
}
private function itemIsEmpty(): bool
{
return $this->item_url === null;
}
private function itemRender(): string
{
if ($this->itemIsEmpty()) {
return '';
}
$text = "\n";
$commentParts = [];
if ($this->item_duration !== null && $this->item_duration > 0) {
$commentParts[] = $this->item_duration;
}
if ($this->item_title !== null) {
$commentParts[] = $this->item_title;
}

if (count($commentParts) !== 0) {
$text .= '#EXTINF:' . implode(',', $commentParts) . "\n";
}

$text .= $this->item_url . "\n";
return $text;
}

public function stringify()
{
$contents = "#EXTM3U\n";

foreach ($this->getItems() as $item) {
$this->resetItem();
$itemArray = $item->toArray();

if (isset($itemArray['enclosure'])) {
$this->item_url = $itemArray['enclosure']['url'];
$this->item_bytes = $itemArray['enclosure']['length'];
if (isset($itemArray['itunes']) && isset($itemArray['itunes']['duration'])) {
$this->item_duration = self::parseDuration($itemArray['itunes']['duration']);
}
}
if (isset($itemArray['title'])) {
$item->item_title = $itemArray['title'];
}
if (! $this->itemIsEmpty()) {
$contents .= $this->itemRender();
} else {
foreach ($item->enclosures as $url) {
$this->resetItem();
$this->item_url = $url;
if (isset($itemArray['title'])) {
$this->item_title = $itemArray['title'];
}
$contents .= $this->itemRender();
}
}
}
return mb_convert_encoding($contents, $this->getCharset(), 'UTF-8');
}
/*
* parseDuration converts a string like "00:4:20" to 260
* allowing to convert duration as used in the itunes:duration tag to the number of seconds
*/
private static function parseDuration(string $duration_string): int
{
$seconds = 0;
$parts = explode(':', $duration_string);
for ($i = 0; $i < count($parts); $i++) {
$seconds += intval($parts[count($parts) - $i - 1]) * pow(60, $i);
}
return $seconds;
}
}
29 changes: 29 additions & 0 deletions tests/Formats/M3uFormatTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

/**
* M3uFormat
*/

namespace RssBridge\Tests\Formats;

require_once __DIR__ . '/BaseFormatTest.php';

use PHPUnit\Framework\TestCase;

class M3uFormatTest extends BaseFormatTest
{
private const PATH_EXPECTED = self::PATH_SAMPLES . 'expectedM3uFormat/';

/**
* @dataProvider sampleProvider
* @runInSeparateProcess
*/
public function testOutput(string $name, string $path)
{
$data = $this->formatData('M3u', $this->loadSample($path));

$expected = file_get_contents(self::PATH_EXPECTED . $name . '.m3u');
$this->assertEquals($expected, $data);
}
}

4 changes: 4 additions & 0 deletions tests/Formats/samples/expectedM3uFormat/feed.common.m3u
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#EXTM3U

#EXTINF:Atom draft-07 snapshot
http://example.org/audio/ph34r_my_podcast.mp3
1 change: 1 addition & 0 deletions tests/Formats/samples/expectedM3uFormat/feed.empty.m3u
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#EXTM3U
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#EXTM3U
1 change: 1 addition & 0 deletions tests/Formats/samples/expectedM3uFormat/feed.microblog.m3u
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#EXTM3U
Loading