commit 9c7b61256f5e26b237e616b44e597c6aafc49e29 Author: boyska Date: Thu Jan 20 22:24:33 2022 +0100 Initial commit diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..54a562c --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ +all: index.html spec.html radiomanifest.zip +testXMLs := $(shell find shows radio-manifest -type f -name '*.xml') + +%.html: %.asciidoc + asciidoctor -b html5 $< + +radiomanifest.zip: radio-manifest.xsd shows.xsd radio-manifest/Makefile shows/Makefile $(testXMLs) + zip -r $@ $^ + +test: + make -C shows/ + make -C radio-manifest/ + +.PHONY: all diff --git a/index.asciidoc b/index.asciidoc new file mode 100644 index 0000000..caf352c --- /dev/null +++ b/index.asciidoc @@ -0,0 +1,21 @@ += Radiomanifest +CiurmaPirata + +Scopo di questa specifica è quello di fare sì che il sito di una radio possa esporre in maniera strutturata alcune informazioni sul suo sito. + + +* link:spec.html[read the spec] +* link:radio-manifest.xsd[XSD radio-manifest] +* link:shows.xsd[XSD shows] +* link:radiomanifest.zip[examples dataset] +* link:examples/[example websites] + +== Implementations + +=== Clients + +* link:https://git.lattuga.net/boyska/radiomanifest.js/[radiomanifest.js] + +=== Server + +none yet? diff --git a/radio-manifest.xsd b/radio-manifest.xsd new file mode 100644 index 0000000..beacb7d --- /dev/null +++ b/radio-manifest.xsd @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/radio-manifest/Makefile b/radio-manifest/Makefile new file mode 100644 index 0000000..eddcdc4 --- /dev/null +++ b/radio-manifest/Makefile @@ -0,0 +1,14 @@ +VALID = examples/*.xml +NONVALID = failing/*.xml +SCHEMA = ../radio-manifest.xsd + +all: test +test: $(VALID) $(NONVALID) + +examples/%.xml: $(SCHEMA) + xmllint --schema $(SCHEMA) --noout $@ + +failing/%.xml: $(SCHEMA) + if xmllint --schema $(SCHEMA) --noout $@ 2> /dev/null; then false; else true; fi + +.PHONY: all test diff --git a/radio-manifest/examples/1.xml b/radio-manifest/examples/1.xml new file mode 100644 index 0000000..107921d --- /dev/null +++ b/radio-manifest/examples/1.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/radio-manifest/examples/empty.xml b/radio-manifest/examples/empty.xml new file mode 100644 index 0000000..b3e0650 --- /dev/null +++ b/radio-manifest/examples/empty.xml @@ -0,0 +1,4 @@ + + + + diff --git a/radio-manifest/examples/feed-no-type.xml b/radio-manifest/examples/feed-no-type.xml new file mode 100644 index 0000000..b1d0c47 --- /dev/null +++ b/radio-manifest/examples/feed-no-type.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/radio-manifest/examples/reordered.xml b/radio-manifest/examples/reordered.xml new file mode 100644 index 0000000..ab4fdf4 --- /dev/null +++ b/radio-manifest/examples/reordered.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/radio-manifest/examples/source-prio.xml b/radio-manifest/examples/source-prio.xml new file mode 100644 index 0000000..d2fae0b --- /dev/null +++ b/radio-manifest/examples/source-prio.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/radio-manifest/examples/streaming-1.xml b/radio-manifest/examples/streaming-1.xml new file mode 100644 index 0000000..560f32d --- /dev/null +++ b/radio-manifest/examples/streaming-1.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/radio-manifest/failing/repeated.xml b/radio-manifest/failing/repeated.xml new file mode 100644 index 0000000..9b5d694 --- /dev/null +++ b/radio-manifest/failing/repeated.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + diff --git a/radio-manifest/failing/streaming-empty.xml b/radio-manifest/failing/streaming-empty.xml new file mode 100644 index 0000000..ffa7159 --- /dev/null +++ b/radio-manifest/failing/streaming-empty.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/radio-manifest/failing/streaming-prio-toohigh.xml b/radio-manifest/failing/streaming-prio-toohigh.xml new file mode 100644 index 0000000..dc8aff6 --- /dev/null +++ b/radio-manifest/failing/streaming-prio-toohigh.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/radio-manifest/failing/streaming-prio-toolow.xml b/radio-manifest/failing/streaming-prio-toolow.xml new file mode 100644 index 0000000..9fca1be --- /dev/null +++ b/radio-manifest/failing/streaming-prio-toolow.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/radio-manifest/failing/streaming-source-empty.xml b/radio-manifest/failing/streaming-source-empty.xml new file mode 100644 index 0000000..85d1da3 --- /dev/null +++ b/radio-manifest/failing/streaming-source-empty.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/shows-table.xsl b/shows-table.xsl new file mode 100644 index 0000000..82860f9 --- /dev/null +++ b/shows-table.xsl @@ -0,0 +1,43 @@ + + + + + + + Shows list + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameWebsiteFeedSchedule
+ + +
+ +
diff --git a/shows.xsd b/shows.xsd new file mode 100644 index 0000000..29ea39c --- /dev/null +++ b/shows.xsd @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/shows/Makefile b/shows/Makefile new file mode 100644 index 0000000..4db7d99 --- /dev/null +++ b/shows/Makefile @@ -0,0 +1,14 @@ +VALID = examples/*.xml +NONVALID = failing/*.xml +SCHEMA = ../shows.xsd + +all: test +test: $(VALID) $(NONVALID) + +examples/%.xml: $(SCHEMA) + xmllint --schema $(SCHEMA) --noout $@ + +failing/%.xml: $(SCHEMA) + if xmllint --schema $(SCHEMA) --noout $@ 2> /dev/null; then false; else true; fi + +.PHONY: all test diff --git a/shows/examples/basic.xml b/shows/examples/basic.xml new file mode 100644 index 0000000..f387376 --- /dev/null +++ b/shows/examples/basic.xml @@ -0,0 +1,15 @@ + + + + + Learn to cook in C++ + http://radioexample.com/shows/learn-cook + http://radioexample.com/shows/learn-cook/feed + http://radioexample.com/shows/learn-cook.ics + + + Uncensored information + http://radioexample.com/shows/info + http://radioexample.com/shows/info/feed + + diff --git a/shows/examples/empty.xml b/shows/examples/empty.xml new file mode 100644 index 0000000..40aafca --- /dev/null +++ b/shows/examples/empty.xml @@ -0,0 +1,4 @@ + + + + diff --git a/shows/failing/noname.xml b/shows/failing/noname.xml new file mode 100644 index 0000000..04dd3df --- /dev/null +++ b/shows/failing/noname.xml @@ -0,0 +1,8 @@ + + + + http://radioexample.com/shows/learn-cook + http://radioexample.com/shows/learn-cook/feed + http://radioexample.com/shows/learn-cook.ics + + diff --git a/spec.asciidoc b/spec.asciidoc new file mode 100644 index 0000000..4c50b61 --- /dev/null +++ b/spec.asciidoc @@ -0,0 +1,168 @@ += Radiomanifest specification +CiurmaPirata + +Un formato per fare sì che il sito di una radio possa esporre in maniera strutturata alcune informazioni sul +suo sito. + +Tali informazioni sono, brevemente: + +* il palinsesto +* l'elenco delle trasmissioni che vanno in onda in modo regolare, e per ciascuna di esse i principali feed +* gli indirizzi di streaming + + +Per permettere un'implementazione più semplice, ciascuna di queste informazioni segue una sua specifica, possibilmente appoggiandosi a specifiche già esistenti. + +== RadioManifest + +Al fine di avere un singolo punto in cui "esporre" le funzionalità supportate dal sito web, un sito può creare un manifest. Esso *DOVREBBE* (*SHOULD*) chiamarsi sempre ``${BASEURL}/radiomanifest.xml``. + +Ecco un esempio di xml: + + + + + + + + + + + + +(link:radio-manifest.xsd[Schema XSD]) + +Ovvero: + +* 0 o 1 ``schedule``. Gli schedule sono definiti in link:https://icalendar.org/RFC-Specifications/iCalendar-RFC-5545/[formato iCalendar] +* 0 o 1 oggetti ``streaming``; contengono un qualsiasi numero (almeno 1) di source, le quali +** *POSSONO* avere un campo ``name``. Il campo ``name`` è fortemente + raccomandato se viene fornito più di un oggetto ``streaming`` +** *DEVONO* avere un campo ``src``, il quale deve puntare ad una risorsa di tipo M3U. +** *POSSONO* avere un campo ``priority``, contenente un valore intero; se omesso, si assume il valore "1". Un numero più grande indica una +maggiore importanza. Il campo ``priority`` serve a definire l'ordinamento con cui i client *DOVREBBERO* +mostrare le playlist agli utenti, o a definire quale playlist vada usata, se il client sceglie automaticamente +senza proporrere all'utente. Il valore della priority è relativo alle altre source, non si riferisce ad altre +radio. Valori di priority minori di zero indicano che la source non dovrebbe essere resa visibile all'utente +in condizioni normali. +* 0 o 1 oggetti ``shows``. Il campo ``src`` *DEVE* puntare ad una risorsa di formato _shows_ (vedi di + seguito). +* 0 o 1 ``feed``. Il campo ``src`` *DEVE* puntare ad una risorsa di tipo feed. + +### Implementazione client + +Un client dovrebbe chiedere all'utente di fornire l'indirizzo base di un sito. Il manifest dovrebbe essere +rintracciabile andando all'indirizzo ``radiomanifest.xml`` relativo all'indirizzo di un sito. +Ad esempio, se l'utente inserisce "http://hosting.com/myradio/" il manifest *DEVE* essere cercato all'indirizzo +"http://hosting.com/myradio/radiomanifest.xml" + +Quando un client vuole suonare lo streaming associato ad un radiomanifest, esso potrebbe voler mostrare +all'utente la scelta tra le varie source, oppure decidere automaticamente. +Se il client sceglie automaticamente: + + * *DEVE* rispettare l'ordinamento delle priority. + * *DEVE* escludere le source con priority minore di zero. + * Qualora la riproduzione della source dovesse avere problemi, *DOVREBBE* passare alla successiva + * Se alcune source hanno uguale priority, *DOVREBBE* scegliere casualmente tra di esse + +Se il client fa scegliere l'utente: + + * *DEVE* rispettare l'ordinamento delle priority + * *DOVREBBE* omettere le source con priority minore di zero. + +== Schedule + +The goal of the schedule is to express the typical weekly table that is commonly found in radio websites. It is an iCalendar file. Each show should be a distinct ``VEVENT``. + +The schedule *SHOULD* include at least events up until 1 week +The schedule *SHOULD* use recurrency rule where appropriate, so that the user is informed of this. + +== Shows + +The goal of the shows file is to: + +* list shows +* provide useful metadata for each show, such as: +** dedicated feed +** link to specialized page for the show + +Here is an example: + + + + + Learn to cook in C++ + http://radioexample.com/shows/learn-cook + http://radioexample.com/shows/learn-cook/feed + http://radioexample.com/shows/learn-cook.ics + + + Uncensored information + http://radioexample.com/shows/info + http://radioexample.com/shows/info/feed + + + +(link:shows.xsd[Schema XSD]) + +Only ``name`` is required. A schedule can point to an iCal resource. All entries in the calendar are assumed to +be part of the show. + +=== Relationship with schedule + +It's pretty clear that in many cases shows.xml and schedule.ics will benefit from being linked. How to do +that? + + 1. If there is an ``X-SHOW-ID``, and it is the same as ```` + 2. If ``CATEGORIES`` include ```` + 3. If ``SUMMARY`` is the same as ```` + +== Implementation details + +=== HTTP Implementation + +Clients: + + - *MUST* provide an ``Accept`` header in every HTTP request. This will enable maximum flexibility in the + future, allowing clients and servers to smoothly move to new file formats + +Servers: + + - *MUST* implement CORS adequately. Every file related to this specification must be retrievable by a browser + on a different domain via a `GET`. + + +== Casi d'uso + +=== Player + +Supponiamo di voler realizzare un player di radio con feature avanzate, che sia però portabile su molte radio. +Data una lista di URL di siti web, è possibile fare un player che: + +* supporti vari indirizzi di streaming in modo trasparente per l'utente +* permetta all'utente di scegliere il tipo di streaming, ad esempio se la radio fornisce streaming di diversa + qualità +* possa dire all'utente informazioni utili sul palinsesto della radio che sta ascoltando +* permetta di puntare allo storico, o di andare rapidamente alla pagina della trasmissione che sta + ascoltando. + +Come capita spesso, questo può essere applicato anche alla scrittura di app che supportino molte radio, senza che però esse debbano essere limitate al solo streaming come è il caso attualmente (vedi le varie Transistor, RadioDroid, ecc.) + +=== Radio automation + +Se un radio automation (della radio A) vuole importare contenuti da un'altra radio B, esso può facilmente +fornire all'utente della radio A utili informazioni. Ad esempio, permette di vedere il palinsesto in forma +grafica, selezionare uno show, vedere un'anteprima del feed corrispondente, quindi importarlo in una specifica +fascia oraria. + +=== radio-browser++ + +https://www.radio-browser.info/ fornisce molte info utili su delle radio. Grazie a radio-manifest, sarebbe più semplice: + +* mantenere le informazioni in modo più semplice; finché una radio mantiene lo stesso sito web, può aggiornare la lista di url di streaming in modo automatico +* più informazioni; radio-browser potrebbe includere le informazioni dettagliate disponibili tramite ```` e ```` per fornire informazioni aggiuntive. + +=== RadioDroid++ + +RadioDroid is a fine Android app to listen to stream. We'd like to have an improved version of RadioDroid that +also includes features that RadioManifest provide. See the _Player_ use case.