From e729de79bba9547f1dcb6fd8e4f12b9b29eb1259 Mon Sep 17 00:00:00 2001 From: Christian Weiske Date: Tue, 20 May 2008 20:57:49 +0000 Subject: [PATCH] import enigma2 -> mediatomb radio sync script --- ABOUT | 1 + DreamboxBouqets.php | 86 +++++++++++++++++++++ config.php.dist | 29 ++++++++ copy-radio-bouqets.php | 68 +++++++++++++++++ sync-radiobouqets.php | 165 +++++++++++++++++++++++++++++++++++++++++ syncfunctions.php | 88 ++++++++++++++++++++++ 6 files changed, 437 insertions(+) create mode 100644 ABOUT create mode 100644 DreamboxBouqets.php create mode 100644 config.php.dist create mode 100644 copy-radio-bouqets.php create mode 100644 sync-radiobouqets.php create mode 100644 syncfunctions.php diff --git a/ABOUT b/ABOUT new file mode 100644 index 0000000..34bad9c --- /dev/null +++ b/ABOUT @@ -0,0 +1 @@ +enigma2 radio stations to mediatomb converter diff --git a/DreamboxBouqets.php b/DreamboxBouqets.php new file mode 100644 index 0000000..2e420d5 --- /dev/null +++ b/DreamboxBouqets.php @@ -0,0 +1,86 @@ + +*/ +class DreamboxBouqets +{ + /** + * Fetch radio bouqets + * + * @param string $ip IP-address or hostname of the dreambox + * + * @return array Array of bouqets and the items + */ + public static function fetchRadioBouqets($ip) + { + $host = 'http://' . $ip; + $streamhost = 'http://' . $ip . ':8001'; + $url_getServices = $host . "/web/getservices?sRef="; + $url_stream_playlist = $host . '/web/stream.m3u?ref='; + //1%3A7%3A2%3A0%3A0%3A0%3A0%3A0%3A0%3A0%3A(type%20%3D%3D%202)%20FROM%20BOUQUET%20%22userbouquet.info_______________radio_.radio%22%20ORDER%20BY%20bouquet + $url_bouqet_epg = $host . '/web/epgnow?bRef='; + $url_stream = $streamhost . '/'; + + //TODO: fetch from dreambox config.js + $bouqet_radio = '1:7:2:0:0:0:0:0:0:0:(type == 2)FROM BOUQUET "bouquets.radio" ORDER BY bouquet'; + + + $url = $url_getServices . urlencode($bouqet_radio); + $radiobouqets = new SimpleXMLElement( + file_get_contents($url) + ); + + $arBouqets = array(); + foreach ($radiobouqets->e2service as $bouqet) { + $strBouqetName = self::properBouqetName($bouqet->e2servicename); + $arBouqets[$strBouqetName] = array(); + + $strRef = $bouqet->e2servicereference; + $url = $url_getServices . urlencode($strRef); + $epgurl = $url_bouqet_epg . urlencode($strRef); + + $stations = new SimpleXMLElement( + file_get_contents( + $url + ) + ); + foreach ($stations->e2service as $station) { + $strStationRef = (string)$station->e2servicereference; + $arBouqets[$strBouqetName][$strStationRef] = array( + 'name' => (string)$station->e2servicename, + 'playlist' => $url_stream_playlist . $strStationRef, + 'stream' => $url_stream . $strStationRef + ); + } + + $epgs = new SimpleXMLElement( + file_get_contents($epgurl) + ); + foreach ($epgs->e2event as $epg) { + $strStationRef = (string)$epg->e2eventservicereference; + $arBouqets[$strBouqetName][$strStationRef] = array_merge( + $arBouqets[$strBouqetName][$strStationRef], + array( + 'epgtitle' => (string)$epg->e2eventtitle, + 'epgdescription' => (string)$epg->e2eventdescription, + 'epgdescription2' => (string)$epg->e2eventdescriptionextendet, + ) + ); + } + + } + + return $arBouqets; + }//public static function fetchRadioBouqets(..) + + + + protected static function properBouqetName($name) + { + return trim(preg_replace('#\(.+\)$#', '', $name)); + } +} + +?> \ No newline at end of file diff --git a/config.php.dist b/config.php.dist new file mode 100644 index 0000000..e5036fc --- /dev/null +++ b/config.php.dist @@ -0,0 +1,29 @@ + array( + 'host' => 'dreambox' + ), + 'mediatomb' => array( + 'host' => 'dojo', + 'port' => 49152, + 'user' => 'cweiske', + 'pass' => 'mediatomb', + + 'radiodir' => 'Radio', + 'rootBouqet' => 'Favourites', + 'mimetype' => 'audio/x-satellite-mpeg2' + ), + 'namefixes' => array( + 'DKULTUR' => 'D-Kultur', + 'DLF' => 'Deutschlandfunk', + 'JAZZ RADIO' => 'Jazz Radio', + 'MDR FIGARO' => 'Figaro', + 'MDR INFO' => 'mdr info', + 'MDR JUMP' => 'Jump', + 'MDR SPUTNIK' => 'Sputnik', + 'MDR1 SACHSEN' => 'mdr1 Radio Sachsen', + 'P-COUNTRY' => 'Premiere Country', + 'VIBRATION' => 'Vibration', + ) +); +?> \ No newline at end of file diff --git a/copy-radio-bouqets.php b/copy-radio-bouqets.php new file mode 100644 index 0000000..6d7bf3b --- /dev/null +++ b/copy-radio-bouqets.php @@ -0,0 +1,68 @@ + +* @license LGPL http://www.gnu.org/copyleft/lesser.html +*/ +require_once 'DreamboxBouqets.php'; +require_once 'Services/MediaTomb.php'; +require_once 'config.php'; + +echo "fetching bouqets\n"; +$arBouqets = DreamboxBouqets::fetchRadioBouqets( + $GLOBALS['enigtombConfig']['dreambox']['host'] +); + +$mt = new Services_MediaTomb( + $GLOBALS['enigtombConfig']['mediatomb']['user'], + $GLOBALS['enigtombConfig']['mediatomb']['pass'], + $GLOBALS['enigtombConfig']['mediatomb']['host'], + $GLOBALS['enigtombConfig']['mediatomb']['port'] +); + +$strRadiodir = $GLOBALS['enigtombConfig']['mediatomb']['radiodir']; + +$radiodir = $mt->getContainerByPath($strRadiodir); +if ($radiodir !== null) { + $mt->delete($radiodir); +} + +foreach ($arBouqets as $strBouqetName => $arStations) { + echo "adding " . $strBouqetName . "\n"; + if ($strBouqetName == $GLOBALS['enigtombConfig']['mediatomb']['rootBouqet']) { + $dir = $mt->getContainerByPath($strRadiodir); + if ($dir === null) { + $dir = $mt->createContainerByPath($strRadiodir); + } + } else { + $dir = $mt->createContainerByPath($strRadiodir . '/' . $strBouqetName); + } + + foreach ($arStations as $arStation) { + echo " adding " . $arStation['name'] . "\n"; + $strName = $arStation['name']; + if ($arStation['epgtitle']) { + $strName .= ' - ' . $arStation['epgtitle']; + } + if ($arStation['epgdescription']) { + $strDescription = $arStation['epgdescription']; + } else { + $strDescription = ''; + } + if ($arStation['epgdescription2']) { + $strDescription .= ' ' . $arStation['epgdescription2']; + } + if (!$strDescription) { + $strDescription = $strName; + } + $mt->createExternalLink( + $dir->id, $strName, $arStation['stream'], trim($strDescription), + $GLOBALS['enigtombConfig']['mediatomb']['mimetype'], + Services_MediaTomb::PROTOCOL_HTTP_GET + ); + } +} + +?> \ No newline at end of file diff --git a/sync-radiobouqets.php b/sync-radiobouqets.php new file mode 100644 index 0000000..1af0868 --- /dev/null +++ b/sync-radiobouqets.php @@ -0,0 +1,165 @@ + +* @license LGPL http://www.gnu.org/copyleft/lesser.html +*/ +require_once 'DreamboxBouqets.php'; +require_once 'Services/MediaTomb.php'; +require_once 'config.php'; +require_once dirname(__FILE__) . '/syncfunctions.php'; + +$bReally = true; + +echo "Synchronizing dreambox radio bouqets and mediatomb radion station list\n"; +echo " fetching bouqets\n"; +$arBouqets = DreamboxBouqets::fetchRadioBouqets( + $GLOBALS['enigtombConfig']['dreambox']['host'] +); + +$mt = new Services_MediaTomb( + $GLOBALS['enigtombConfig']['mediatomb']['user'], + $GLOBALS['enigtombConfig']['mediatomb']['pass'], + $GLOBALS['enigtombConfig']['mediatomb']['host'], + $GLOBALS['enigtombConfig']['mediatomb']['port'] +); + +$strRadiodir = $GLOBALS['enigtombConfig']['mediatomb']['radiodir']; + +$radiodir = $mt->createContainerByPath($strRadiodir); + +/** +* create bouqet/container sync list +*/ +$arBouqetNames = array_keys($arBouqets); +$arRadiodirContainers = $radiodir->getContainers(); +$arContainerNames = array(); +foreach ($arRadiodirContainers as $nId => $container) { + $arBouqetNames[] = $container->title; + $arContainerNames[$container->title] = $nId; +} + +if (isset($GLOBALS['enigtombConfig']['mediatomb']['rootBouqet']) + && $GLOBALS['enigtombConfig']['mediatomb']['rootBouqet'] +) { + $arBouqetNames[] = $GLOBALS['enigtombConfig']['mediatomb']['rootBouqet']; + $arContainerNames[$GLOBALS['enigtombConfig']['mediatomb']['rootBouqet']] = $radiodir->id; + $arRadiodirContainers[$radiodir->id] = $radiodir; +} + +$arBouqetNames = array_unique($arBouqetNames); + +/** +* sync bouqets and containers +* Does not know about renamed bouqets +*/ +echo " syncing bouqets and containers\n"; +$arValidContainers = array(); +foreach ($arBouqetNames as $strBouqetName) { + if (isset($arContainerNames[$strBouqetName]) && isset($arBouqets[$strBouqetName])) { + //everything is ok + echo " " . $strBouqetName . " already exists, ok\n"; + $nContainerId = $arContainerNames[$strBouqetName]; + $arValidContainers[$nContainerId] = $arRadiodirContainers[$nContainerId]; + } else if (!isset($arContainerNames[$strBouqetName])) { + //container does not exist + if ($strBouqetName != $GLOBALS['enigtombConfig']['mediatomb']['rootBouqet']) { + echo " creating " . $strBouqetName . "\n"; + $container = $mt->createContainerByPath($strRadiodir . '/' . $strBouqetName); + $arValidContainers[$container->id] = $container; + } + } else if (!isset($arBouqets[$strBouqetName])) { + if ($strBouqetName != $GLOBALS['enigtombConfig']['mediatomb']['rootBouqet']) { + //bouqet does not exist anymore -> delete container + echo " deleting container " . $strBouqetName . "\n"; + if ($bReally) { + $mt->delete($arContainerNames[$strBouqetName]); + } + } + } +} + +/** +* Sync radio stations +*/ +echo " syncing stations\n"; +foreach ($arValidContainers as $nContainerId => $container) { + /** + * Build stations sync list + */ + if (isset($GLOBALS['enigtombConfig']['mediatomb']['rootBouqet']) + && $GLOBALS['enigtombConfig']['mediatomb']['rootBouqet'] + && $container == $radiodir + ) { + $strContainerTitle = $GLOBALS['enigtombConfig']['mediatomb']['rootBouqet']; + } else { + $strContainerTitle = $container->title; + } + echo " syncing stations in " . $strContainerTitle . "\n"; + + //existing stations in mediatomb + $arStationItems = $container->getItems(0, 1000); + $arStationUris = array(); + $arStationItemsByUri = array(); + foreach ($arStationItems as $item) { + $arStationUris[] = $item->url; + $arStationItemsByUri[$item->url] = $item; + } + unset($arStationItems); + + //stations in bouqet + foreach ($arBouqets[$strContainerTitle] as $arStation) { + $arStationUris[] = $arStation['stream']; + $arBouqetStationsByUri[$arStation['stream']] = $arStation; + } + unset($arBouqets[$strContainerTitle]); + + $arStationUris = array_unique($arStationUris); + + //sync stations + foreach ($arStationUris as $strUri) { + echo ' syncing station ' . $strUri . "\n"; + if (isset($arBouqetStationsByUri[$strUri]) && isset($arStationItemsByUri[$strUri])) { + //station exists on both dreambox and mediatomb + //update title + echo " updating title and description\n"; + $arTitles = enigtombGetStationTitle($arBouqetStationsByUri[$strUri]); + echo " " . $arTitles['title'] . "\n"; + if ($arTitles['description'] && $arTitles['description'] != $arTitles['title']) { + echo " " . $arTitles['description'] . "\n"; + } + $arStationItemsByUri[$strUri]->title = $arTitles['title']; + $arStationItemsByUri[$strUri]->description = $arTitles['description']; + if ($bReally) { + $arStationItemsByUri[$strUri]->save(); + } + } else if (!isset($arBouqetStationsByUri[$strUri])) { + //station does not exist on dreambox + //delete it in mediatomb + echo " deleting\n"; + if ($bReally) { + $arStationItemsByUri[$strUri]->delete(); + } + } else if (!isset($arStationItemsByUri[$strUri])) { + //station exists on dreambox only + //create it in mediatomb + echo " creating\n"; + $arTitles = enigtombGetStationTitle($arBouqetStationsByUri[$strUri]); + echo " " . $arTitles['title'] . "\n"; + if ($bReally) { + $arStationItemsByUri[$strUri]->createExternalLink( + $arTitles['title'], $strUri, $arTitles['description'], + $GLOBALS['enigtombConfig']['mediatomb']['mimetype'], + 'http-get', 'object.item', false + ); + } + } + } +} + + +echo "done\n"; +?> \ No newline at end of file diff --git a/syncfunctions.php b/syncfunctions.php new file mode 100644 index 0000000..a63d8a0 --- /dev/null +++ b/syncfunctions.php @@ -0,0 +1,88 @@ + +* @license LGPL http://www.gnu.org/copyleft/lesser.html +*/ + +if (!function_exists('enigtombGetStationTitle')) { + /** + * Returns a proper title from the bouqet station data + * for the mediatomb entry + * + * @param array $arStation Station in a dreambox bouqet + * + * @return array Array of title and description to use in the UPnP server. + * Keys title and description + */ + function enigtombGetStationTitle($arStation) + { + $strName = enigtombFixName($arStation['name']); + + if ($arStation['epgtitle'] + && $arStation['epgtitle'] != 'None' + && $arStation['epgtitle'] != $arStation['name'] + ) { + if (strtolower(substr($arStation['epgtitle'], 0, strlen($strName))) == strtolower($strName)) { + $strEpgTitle = substr($arStation['epgtitle'], strlen($strName)); + } else if (strtolower(substr($arStation['epgtitle'], 0, strlen($arStation['name']))) == strtolower($arStation['name'])) { + $strEpgTitle = substr($arStation['epgtitle'], strlen($arStation['name'])); + } else { + $strEpgTitle = $arStation['epgtitle']; + } + $strEpgTitle = trim($strEpgTitle); + if (substr($strEpgTitle, 0, 1) == '-') { + $strEpgTitle = trim(substr($strEpgTitle, 1)); + } + + if (strtoupper($strEpgTitle) == $strEpgTitle) { + $strEpgTitle = ucwords(strtolower($strEpgTitle)); + } + + $strName .= ' - ' . $strEpgTitle; + } + + if ($arStation['epgdescription'] && $arStation['epgdescription'] != 'None') { + $strDescription = $arStation['epgdescription']; + } else { + $strDescription = ''; + } + if ($arStation['epgdescription2'] && $arStation['epgdescription2'] != 'None') { + $strDescription .= ' ' . $arStation['epgdescription2']; + } + if (!$strDescription) { + $strDescription = $strName; + } + + return array( + 'title' => trim($strName), + 'description' => trim($strDescription) + ); + }//function enigtombGetStationTitle(..) +} + + + +if (!function_exists('enigtombFixName')) { + /** + * Replaces the given name with a fixed one from the config. + * Necessary, because some stations send their names in ALL UPPERCASE + * which just isn't nicely readable. + * + * @param string $strName Name to fix + * + * @return string Fixed name + */ + function enigtombFixName($strName) + { + $strName = trim($strName); + if (isset($GLOBALS['enigtombConfig']['namefixes'][$strName])) { + return $GLOBALS['enigtombConfig']['namefixes'][$strName]; + } else { + return $strName; + } + }//function enigtombFixName(..) +} + +?> \ No newline at end of file -- 2.30.2