Skip to content

Commit

Permalink
Merge pull request #60 from ben-xo/feature/support-m4b-audiobooks-59
Browse files Browse the repository at this point in the history
Feature/support m4b audiobooks 59
  • Loading branch information
ben-xo authored Jul 28, 2022
2 parents bb56a6a + e515a45 commit b43ff05
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 12 deletions.
5 changes: 4 additions & 1 deletion CHANGELOG.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
Changelog
=========

1.33 unreleased * README fixed by @denilsonsa - thanks!
1.34 2022-07-28 * Add support for M4B audiobook files as requested by @crosbyh
Many thanks for your support!

1.33 2022-05-25 * README fixed by @denilsonsa - thanks!
* Caching algorithm changed to so that it is no longer dependent
on added media files having a newer file date (GitHub #51),
and will look for any changes in filesize or date, as well
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[![Testing dir2cast](https://github.com/ben-xo/dir2cast/actions/workflows/testing.yml/badge.svg)](https://github.com/ben-xo/dir2cast/actions/workflows/testing.yml)


dir2cast by Ben XO v1.34 (2022-07-28)
================================================================================

Expand All @@ -22,10 +23,10 @@ Features:
pick up most of the podcast text straight from the tags in the file (such as
the artist, title and comment tags.)

* supports MP3, MP4, and M4A files
* supports MP3, MP4, M4A and M4B files

* dir2cast will automatically use the ID3 fields from your files for the Author,
Title, etc. ID3v2 is supported, as are the regular tags found in MP4 and M4A
Title, etc. ID3v2 is supported, as are the usual tags found in MP4 / M4A / M4B
files. (Uses getID3, which is bundled with dir2cast.)

* dir2cast will automatically use the cover art embedded in your file as well.
Expand Down Expand Up @@ -81,7 +82,7 @@ Please note: the config file will make more sense if you read all of this `READM
before trying the installation instructions.

dir2cast is quite flexible but the general idea is that you add cover art and
tags to your media files - mp3, mp4 or m4a currently supported - and then the
tags to your media files (mp3, mp4, m4a and m4b currently supported) and then the
podcast that it generates uses the tags from your files.

1. Edit `dir2cast.ini` to your taste.
Expand Down
5 changes: 3 additions & 2 deletions dir2cast.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php

/******************************************************************************
* Copyright (c) 2008-2021, Ben XO ([email protected]).
* Copyright (c) 2008-2022, Ben XO ([email protected]).
*
* All rights reserved.
*
Expand Down Expand Up @@ -56,7 +56,7 @@
/* DEFAULTS *********************************************/

// error handler needs these, so let's set them now.
define('VERSION', '1.33');
define('VERSION', '1.34');
define('DIR2CAST_HOMEPAGE', 'https://github.com/ben-xo/dir2cast/');
define('GENERATOR', 'dir2cast ' . VERSION . ' by Ben XO (' . DIR2CAST_HOMEPAGE . ')');

Expand Down Expand Up @@ -1200,6 +1200,7 @@ public function addItem($filename)
break;

case 'm4a':
case 'm4b':
$this->addRssFileItem(new M4A_RSS_Item($filename));
break;

Expand Down
21 changes: 15 additions & 6 deletions test/Dir_PodcastTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,14 @@ public function createTestItems()
file_put_contents('test2.mp4', 'content');
file_put_contents('test3.m4a', 'content');
file_put_contents('test4.other', 'content');
file_put_contents('test5.m4b', 'content');

$filemtime = time();
touch('test1.mp3', $filemtime+50);
touch('test2.mp4', $filemtime);
touch('test3.m4a', $filemtime-50);
touch('test4.other', $filemtime-100);
touch('test5.m4b', $filemtime-75);

return $filemtime;
}
Expand All @@ -47,12 +49,14 @@ public function createEmptyTestItems()
file_put_contents('test2.mp4', '');
file_put_contents('test3.m4a', '');
file_put_contents('test4.other', '');
file_put_contents('test5.m4b', '');

$filemtime = time();
touch('test1.mp3', $filemtime+50);
touch('test2.mp4', $filemtime);
touch('test3.m4a', $filemtime-50);
touch('test4.other', $filemtime-100);
touch('test5.m4b', $filemtime-75);

return $filemtime;
}
Expand All @@ -65,7 +69,7 @@ public function test_empty_dir_leads_to_empty_podcast()
$this->assertEquals(0, $mp->getMaxMtime());
}

public function test_three_supported_files_of_zero_length_not_added_to_podcast()
public function test_four_supported_files_of_zero_length_not_added_to_podcast()
{
$filemtime = $this->createEmptyTestItems();

Expand All @@ -75,17 +79,18 @@ public function test_three_supported_files_of_zero_length_not_added_to_podcast()
$this->assertEquals(0, $mp->getMaxMtime());
}

public function test_three_supported_files_added_to_podcast()
public function test_four_supported_files_added_to_podcast()
{
$filemtime = $this->createTestItems();
$mp = $this->newPodcast();
$content = $mp->generate();
$this->assertCount(3, $mp->getItems());
$this->assertCount(4, $mp->getItems());

$items = $mp->getItems();
$this->assertInstanceOf(MP3_RSS_Item::class, $items[0]);
$this->assertInstanceOf(MP4_RSS_Item::class, $items[1]);
$this->assertInstanceOf(M4A_RSS_Item::class, $items[2]);
$this->assertInstanceOf(M4A_RSS_Item::class, $items[3]);
$this->assertEquals($filemtime+50, $mp->getMaxMtime());
}

Expand All @@ -100,12 +105,13 @@ public function test_generating_twice_doesnt_rescan()

$content = $mp->generate(); // generate again

$this->assertCount(3, $mp->getItems());
$this->assertCount(4, $mp->getItems());

$items = $mp->getItems();
$this->assertInstanceOf(MP3_RSS_Item::class, $items[0]);
$this->assertInstanceOf(MP4_RSS_Item::class, $items[1]);
$this->assertInstanceOf(M4A_RSS_Item::class, $items[2]);
$this->assertInstanceOf(M4A_RSS_Item::class, $items[3]);
$this->assertEquals($filemtime+50, $mp->getMaxMtime());
}

Expand All @@ -122,6 +128,7 @@ public function test_regenerates_if_metadata_files_added()
$this->assertInstanceOf(MP3_RSS_Item::class, $items[0]);
$this->assertInstanceOf(MP4_RSS_Item::class, $items[1]);
$this->assertInstanceOf(M4A_RSS_Item::class, $items[2]);
$this->assertInstanceOf(M4A_RSS_Item::class, $items[3]);
$this->assertEquals($filemtime+50 - 200, $mp->getMaxMtime());

unset($mp); // releases locks
Expand All @@ -144,6 +151,7 @@ public function test_regenerates_if_metadata_files_added()
$this->assertInstanceOf(MP3_RSS_Item::class, $items[0]);
$this->assertInstanceOf(MP4_RSS_Item::class, $items[1]);
$this->assertInstanceOf(M4A_RSS_Item::class, $items[2]);
$this->assertInstanceOf(M4A_RSS_Item::class, $items[3]);
$this->assertEquals($now-500, $mp->getMaxMtime());
$this->assertEquals('party123', $items[1]->getSummary());

Expand All @@ -157,10 +165,10 @@ public function test_helpers_added_to_found_items()
$mp = $this->newPodcast();

$helper = $this->createMock(Podcast_Helper::class);
$helper->expects($this->exactly(3))->method('appendToItem');
$helper->expects($this->exactly(4))->method('appendToItem');

$helper2 = $this->createMock(Podcast_Helper::class);
$helper2->expects($this->exactly(3))->method('appendToItem');
$helper2->expects($this->exactly(4))->method('appendToItem');

$mp->addHelper($helper);
$mp->addHelper($helper2);
Expand Down Expand Up @@ -200,6 +208,7 @@ protected function delete_test_files()
file_exists('test3.m4a') && unlink('test3.m4a');
file_exists('test4.other') && unlink('test4.other');
file_exists('test2.txt') && unlink('test2.txt');
file_exists('test5.m4b') && unlink('test5.m4b');
}

public function tearDown(): void
Expand Down
10 changes: 10 additions & 0 deletions test/Dir_Podcast_RecursiveTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,19 @@ public function createTestItems()
mkdir('test2');
mkdir('test3');
mkdir('test4');
mkdir('test5');
file_put_contents('test1/test1.mp3', 'content');
file_put_contents('test2/test2.mp4', 'content');
file_put_contents('test3/test3.m4a', 'content');
file_put_contents('test4/test4.other', 'content');
file_put_contents('test5/test5.m4b', 'content');

$filemtime = time();
touch('test1/test1.mp3', $filemtime+50);
touch('test2/test2.mp4', $filemtime);
touch('test3/test3.m4a', $filemtime-50);
touch('test4/test4.other', $filemtime-100);
touch('test5/test5.m4b', $filemtime-75);

return $filemtime;
}
Expand All @@ -42,16 +45,19 @@ public function createEmptyTestItems()
mkdir('test2');
mkdir('test3');
mkdir('test4');
mkdir('test5');
file_put_contents('test1/test1.mp3', '');
file_put_contents('test2/test2.mp4', '');
file_put_contents('test3/test3.m4a', '');
file_put_contents('test4/test4.other', '');
file_put_contents('test5/test5.m4b', '');

$filemtime = time();
touch('test1/test1.mp3', $filemtime+50);
touch('test2/test2.mp4', $filemtime);
touch('test3/test3.m4a', $filemtime-50);
touch('test4/test4.other', $filemtime-100);
touch('test5/test5.m4b', $filemtime-75);

return $filemtime;
}
Expand All @@ -69,10 +75,12 @@ protected function delete_test_files()
file_exists('test2/test2.mp4') && unlink('test2/test2.mp4');
file_exists('test3/test3.m4a') && unlink('test3/test3.m4a');
file_exists('test4/test4.other') && unlink('test4/test4.other');
file_exists('test5/test5.m4b') && unlink('test5/test5.m4b');
is_dir('test1') && rmdir('test1');
is_dir('test2') && rmdir('test2');
is_dir('test3') && rmdir('test3');
is_dir('test4') && rmdir('test4');
is_dir('test5') && rmdir('test5');
parent::delete_test_files();
}

Expand All @@ -89,6 +97,7 @@ public function test_regenerates_if_metadata_files_added()
$this->assertInstanceOf(MP3_RSS_Item::class, $items[0]);
$this->assertInstanceOf(MP4_RSS_Item::class, $items[1]);
$this->assertInstanceOf(M4A_RSS_Item::class, $items[2]);
$this->assertInstanceOf(M4A_RSS_Item::class, $items[3]);
$this->assertEquals($filemtime+50 - 200, $mp->getMaxMtime());

unset($mp); // releases locks
Expand All @@ -111,6 +120,7 @@ public function test_regenerates_if_metadata_files_added()
$this->assertInstanceOf(MP3_RSS_Item::class, $items[0]);
$this->assertInstanceOf(MP4_RSS_Item::class, $items[1]);
$this->assertInstanceOf(M4A_RSS_Item::class, $items[2]);
$this->assertInstanceOf(M4A_RSS_Item::class, $items[3]);
$this->assertEquals($now-500, $mp->getMaxMtime());
$this->assertEquals('party123', $items[1]->getSummary());

Expand Down

0 comments on commit b43ff05

Please sign in to comment.