AAMOT OLE 19780220 OSLO METROPOLITAN UNIVERSITY 20200704 MSc EE Public Network Radio Software for Accessing Free World Broadcasts on Internet GNOMERadio (gnome-radio) http://www.gnomeradio.org/ 1 Public Network Radio Software for Accessing Free World Broadcasts on Internet GNOME Radio (gnome-radio) http://www.gnomeradio.org/~ole/master.pdf Ole Kr. Aamot July 3, 2020 Thesis submitted for the degree of Philosophiæ Doctor 2 Introduksjon I denne Master-oppgaven innen emnet medisinsk teknologi er dataprogrammet gnome-radio utviklet i løpet av 9 måneder for datamaskinoperativsystemet GNU/Linux og skrivebordet GNOME som har blitt utviklet og kontinuerlig forbedret i løpet av 23 år fra 25. juli 1997 til 4. juli 2020. Min hypotese var at mennesker holder seg stabile ved å lytte til radiosendinger på en datamaskin fordi mennesker liker å høre til musikk på radio på datamaskin og stabile mennesker på radio. Oppgaven er et ingeniørarbeid som tok 18 år å fullføre og er dedikert til Oda (musikkterapeut og musiker i Tøyen Botanical Crush) og mine to foreldre Gun- hild (sykepleier) og Helge (ingeniør). Programmet er implementert for GNOME i programmeringspråket ANSI C og er tilgjengelig for Debian GNU/Linux, Fedora Linux, Ubuntu Linux og MacPorts. Programmet kan lastes ned fra http://www.gnomeradio.org/ Du kan følge prosjektet på https://wiki.gnome.org/Apps/Radio og https://gitlab.gnome.org/ole/gnome-radio Takk for velvilje fra studenter ved entreprenøruniversitetet Massachusetts Insti- tute of Technology i Cambridge, MA som har utdannet utallige entreprenører i ingeniørvitenskap, Universitetet i Oslo og Høgskolen i Oslo og Akershus og ven- ner, særlig du som hjalp meg og oppmuntret meg til å fortsette utdannelsen etter en arbeidsperiode i 9 år for Domeneshop AS fra mandag til fredag kl. 9 - 17, og pasienter ved Lovisenberg Diakonale Sykehus som deltok i spørreundersøkelsen. Takk til Graham Morrison i spalten FOSSPicks for britisk omtale av GNOME Internet Radio Locator i Linux Magazine 222 i mai 2019, Marius Nestor for om- tale på Softpedia, Øyvind Sæther for anmeldelse på linuxreviews.org og Justin Dove, Greg Thomas og Peter Norvig for invitasjon til Massachusetts Institute of Technology (http://web.mit.edu/), University of California Berkeley (http://www.berkeley.edu/) og Google, Inc. (http://www.google.com/) i Mountain View, California, U.S.A. Takk også til Ranveig, Anja og Veena, Asgeir, Daniel, Kristian, Arnfinn, Kent, Ståle, Dag og Jan som var svært tålmodige arbeidskolleger i Oslo i 9 år og takk til 3 mine gode venner Nina Rosenkrantz de Neergaard, Martin Eggen, Karen Stærfelt, Håkon og Tarjei Solvang Tjønn, Sigrid Larsson og John Grande, Ami Niemela, Saga, Mio og Jan Ole Kjellesvig, Hans Petter Jansson, Daniel Mikkelsen, Lars Bungum, Maren Jakobsen, Henry og Karl-Erik Olausen, Geir Kaaresen, Oskar Nakken, Elnaz Asgari, Petter Reinholdtsen, Vetle Berg Abrahamsen, Janan Anes, Patrick Edvard Antonsen, og Hans Petter Solli, Sigrid Sandkjær, og Oda Bjørke Dypvik. Dataprogrammet startet med frie radiosendinger på IMCbra med Elin Nilsen og Ellinor Lønnå sommeren 2002 under protestene mot Verdensbankmøtet i Oslo i 2002 og mennesker har fortsatt å kopiere og installere dataprogrammet til frie datamaskiner over hele verden via Internett via frivillig installasjon og samar- beid fra 2014 etter mitt besøk i New York City, Cambridge og Boston i Mas- sachusetts, U.S.A. i juni 2014 og jeg startet igjen utviklingen 1. november 2014 og videreutviklingen for GNOME Maps og GStreamer etter mitt besøk på UC Berke- ley, i Palo Alto og hos Google i Mountain View i California i august og september 2015 og endte med konklusjonen om at radio er stabiliserende og sosialiserende å lytte til i GNOME Internet Radio Locator for mennesker som var i karantene under Korona-pandemien i verden mellom 12. mars 2020 og 15. juni 2020. Til slutt stor takk til forskningssjef Dalip Dewan i DART, assisterende forskn- ingssjef Wolfgang Leister og sjefsforsker Per Røe, ved Norsk Regnesentral, pro- fessor Carsten Griwodz i Nettverk og distribuerte systemer, professor Astrid Nøk- lebye Heiberg i psykiatri ved Universitetet i Oslo, førsteamanuensis i arkivviten- skap Thomas Sødring ved Oslo Metropolitan University og programleder Fredrik Solvang i NRKsom trodde på prosjektet mitt, samt overingeniør Jon Sverre Disching- ton Hanssen og førsteamanuensis Hilde Hemmer ved Elektronikklaboratoriet, in- geniør Vetle Berg Abrahamsen og medstudent Adrian Szabo Aabech for 9 Volt FM-senderne som Aabech og Abrahamsen bygget på ingeniørhøgskolen høsten 2017 og som fortsatt sender radio i 30 meter på FM 92.1 MHz. Med et sterkt ønske om fred og forståelse i verden gjennom radio og utvikling. Ole Kr. Aamot, Oslo Metropolitan University, 4. juli 2020 4 Submitted in coherence with Norwegian Education Law This dissertation fullfills the requirements of the Master of Science degree in Electrical Engineering at Oslo Metropolitan University, in coordination with the status of the Master of Science program in Network and system administration at University of Oslo, Faculty of Mathematics and Natural Sciences, Norway. A Typeset in LT X. E 5 Forord Opphavet til offentlig radio ble første gang uttrykt og forklart av Edwin Howard Armstrong i kjelleren i Philosophy Hall ved Columbia University i New York City. Justin Dove (PhD) ved Massachusetts Institute of Technology er en av de som anbefalte meg å besøke Columbia University i New York City da jeg besøkte Cambridge, MA i juni 2014. Jeg besøkte senere University of Berkeley California i august 2015 hvor jeg møtte Greg Thomas (PhD) som studerte ved Columbia Uni- versity og besøkte Googleplex, Menlo Park, Hewlett Packard Garage og Stanford University. Denne oppgaven er derfor inspirert av Justin Dove (PhD) og Greg Thomas (PhD), mine to amerikanske venner fra østkysten og vestkysten av U.S.A., og Gary Gramolini (PhD, musiker og gitarlærer) og Peter Norvig (PhD og forskn- ingssjef i Google, Inc.) fra Providence, Rhode Island som jeg møtte i Mountain View i august 2015. U.S.A. går gjennom en tung tid når denne oppgaven skrives og radio kan kan- skje hjelpe litt med å stabilisere det amerikanske samfunnet. Radio har reddet verden tidligere. Radioreportere som amerikaneren Edward R. Murrow fra London under blitz-bombingen av London, nordmannen Toralv Øksnevad, “stemmen fra London’, ankermann i BBCs sendinger fra Bush House i London på norsk mellom januar 1941 og mai 1945 under Nazi-Tysklands okku- pasjon av Norge mellom 9. april 1940 og 8. mai 1945, Gunnar Nygaards norske sendinger fra USA fra september 1940, og rapportene til amerikaneren George Putnam på amerikanske skip på vei mot Normandy og D-dagen 6. juni 1944, den hemmelige, allierte invasjonen av Europa i Frankrike holdt oss informert. Under 2. verdenskrig og senere har radio tjent offentligheten ved å skape en offentlig mening og adressert problemer som krever offentlighetens lys. Radio som medium har hatt betydning for å informere mennesker om protester, konflikter mellom land og internasjonale kampanjer for å slippe fri fengslede men- neskerettighetsforkjempere og styrte diktatorer i land uten reell ytringsfrihet. Menneskerettighetsorganisasjonen Amnesty International har i flere land sendt “distress signal”-kampanjer på FM-båndet for å opplyse allmennheten og frigi mennesker som sitter i fengsel uten lov og dom og uten tilgang til advokat. I enkelte land driver myndighetene i diktaturer med såkalt “jamming” av ra- diosignaler på FM-båndet for å hindre mennesker fra å lytte til frie radiosendinger. Internett-radio er ikke sårbart for “jamming” av signalene. Radio som teknologi har utvidet horisonten til mange mennesker siden den 6 irsk-italienske oppfinneren Guglielmo Marconi kom til U.S.A. i 1899 for å vise hvordan den trådløse telegrafen kunne sende Morse-koder uten kabler. Internett ble oppfunnet av ARPA i 1969 og utbredelsen har vært en viktig faktor i demokratibevegelser i hele verden siden World Wide Web (WWW) ble oppfunnet i 1989 av Tim Berners-Lee og Cascading Style Sheets (CSS) ble fores- lått av nordmannen Håkon Wium Lie 10. oktober 1994 ved CERN i Sveits og utviklet som Internett-standardene HTTP, HTML og CSS. Senere ble Internett-radio oppfunnet i forbindelse med arbeid med gode kom- primeringsalgoritmer for lyd som MP3, Advanced Audio Codec (AAC), Ogg Vor- bis og FLAC. Internett-radio gjorde det mulig å kringkaste lyd med høy lydkvalitet. Denne Master-oppgaven beskriver arbeidet med å kartlegge frie radiostasjoner som kringkaster i verden og programmere et grafisk kart basert på det grafiske grensesnittet GTK+ og lydstrøm via HTTP over et TCP/IP datanettverk mellom minst to datamaskiner som konverterer lydbølger til digitale bits, og digitale bits til lydbølger. Denne Master-oppgaven representerer 21 år med arbeid for å kartlegge frie ra- diostasjoner og 1 år med programmeringsarbeid for å presentere frie radiostasjoner på et grafisk kart presentert på en datamaskin med det grafiske brukergrensesnittet GTK+/GNOME og implementere kontinuerlig lydstreaming over et datanettverk mellom minst to datamaskiner som er kapable til å konvertere digitale bits med ly- dbølger og stillhet til akustiske lydbølger i et stereoheadsett eller monohøytalere. Arbeidet med å finne radiostasjoner som sender direkte radio har tatt mest tid. De fleste radiostasjonene er tilknyttet universiteter og høgskoler, noen av radiostasjonene er kommersielle, mens andre er offisielle kringkastingskanaler som National Public Radio (NPR) i U.S.A., British Broadcasting Corporation (BBC) i Storbritannia, Radio Eins (RDS) i Tyskland, Echo of Moscow i Russ- land, Danmarks Radio (DR) i Danmark, Sveriges Radio (SR) i Sverige og Norsk rikskringkasting (NRK) i Norge. Mange av stasjonene i U.S.A. har reklame foran sendingen når en begynner å lytte. Dette gjelder f.eks. American Uni- versity Radio (WAMU) som har vært den viktigste National Public Radio (NPR) medlemsstasjonen for Washington siden 2007 og Hawaii Public Radio i U.S.A. som kringkaster National Public Radio (www.npr.org) i U.S.A. som ble startet 26. februar 1970 i Washington, D.C., i U.S.A. I 1979 startet lobbyorganisasjonen National Cable Television Association i Washington, D.C. den amerikanske ra- diostasjonen C-SPAN(Cable Satellite Public Affairs Network - http://www.c-span.org/), som kringkaster forhandlingene i Kongressen (United States House of Represen- 7 tatives) og Senatet (United States Senate) i Washington, District of Columbia, U.S.A. På tidspunktet da dette ble skrevet foregikk det en riksrettssak mot Presi- dent Donald J. Trump som først var diskutert i Kongressen og deretter fremmet i Senatet og en virus-pandemi kjent som Korona/COVID-19 som har rammet men- nesker i hele verden. Prosjektet Dataskrivebordet GNU Network Object Model Environment (GNOME) ble startet av Miguel de Icaza, Federico Mena og Elliot Lee i august 1997 basert på Gimp Tool Kit (GTK+) fra UC Berkeley i U.S.A. og videreutviklet av Red Hat Software, Inc. i Red Hat Development Labs og Eazel, Inc. GNOME Foundation som ble etablert under GUADEC 2000 ved ENST på Telecom France i Paris 17. mars 2000 og har støttet utviklingen av GNOME og sosiale møter mellom GNOME- utviklere på konferansen GUADEC i 19 byer. Arbeidet med programvaren GNOME Internet Radio Locator begynte ved Norsk Regnesentral i 2002. Utviklingen ble startet igjen 1. november 2014 med publisering av versjon 0.1.0 og fortsatte i 2015, 2016 og 2017 med tekstsøk og ra- diostasjoner i XML-fila http://www.gnome.org/%7eole/gnome-internet-radio-locator/gnome-internet-radio-locator.xml og direktestrømming av radiostasjoner ved hjelp av GStreamer, publisering av 1.0.0 16. september 2018, 2.0.0 20. februar 2019 og 3.0.1 26. februar 2020. En ny variant (gnome-internet-radio-locator) med omskrivning for GNOME 3 begynte i 2017 med støtte for OpenStreetMap og kartmarkører. En ny omskrivn- ing for GTK+ 4 begynte i 2018. I 2019 la jeg til farger på markørene og publiserte versjon 2.0.4 av gnome- internet-radio-locator som del av GNOME-prosjektet 24. mai 2019. Jeg publiserte gnome-radio versjon 0.2.0 10. september 2019 med støtte for lyd, og gnome-internet-radio-locator versjon 3.0.1 24. januar 2020 med støtte for direkte lydstrømming via GStreamer-bibliotekene for lydkomprimering ved algoritmene MPEG-1 Layer III, Ogg Vorbis, AAC og FLAC. Programmet støtter 124 radiostasjoner i 97 byer i Australia, Sør-Afrika, Saudi Arabia, Catalonia, Belgia, Italia, Frankrike, Storbritannia, Dublin, Irland, Skott- land, Færøyene, Tyskland, Danmark, Sverige, Finland, Russland, Mexico, Guatemala, Canada, U.S.A. og Norge. I Norge er de lokale radiostasjonene til NRK P1 i Trøndelag, Nordland, Finn- mark, Innlandet, Buskerud, Rogaland, Møre og Romsdal, Sogn og Fjordane, 8 Hordaland, Sørlandet og Østfold oppmarkert på kartet over Norge. Internasjonale radiostasjoner er oppmarkert på kartet i resten av verden. 9 10 Saudi Arabia and South Africa 11 Buskerud, Rogaland, Møre og Romsdal, Sogn og Fjordane, Kristiansand, Hordaland, Østfold 12 Screenshot of gnome-internet-radio-locator 3.0.1 13 Screenshot of gnome-radio 0.2.0 (Hawaii Public Radio) 14 Screenshot of gnome-radio 0.1.7 (Southern California Public Radio) 15 Screenshot of gnome-radio 0.1.5 (New York Public Radio) 16 Screenshot of gnome-radio 0.1.6 (MapBox) Arbeidet vil fullføres innen 4. juli 2020. 17 18 Contents I Electricity 27 1 Electrical Engineering 29 II Radio 31 2 American, British, Norwegian, and European Radio History 33 3 Sound waves 41 4 Electrical fields 43 5 Electrical systems 45 5.1 Conduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 5.2 Induction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 5.3 Radiation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 III Audio 47 6 Digital Audio 49 7 Solid state recording 51 8 Audio compression 53 9 MPEG 1.0 Audio Layer III, Ogg Vorbis and MPEG-4 AAC 55 10 Streaming audio 57 19 IV Computers 59 11 Computer systems 61 12 Computer storage 63 13 Network systems 65 14 Network adressing 67 V Internet 69 15 Internet systems (Internet Protocol) 71 16 Domain Name Systems for Internet systems 73 17 Radio microphones 75 18 Audio systems 77 19 Audio codecs 79 20 Audio fingerprinting 81 21 Audio response 83 22 Visual response 85 23 Graphical Display interfaces 87 24 Operating systems 89 25 Installation systems 91 26 Desktop Systems 93 27 Mapping systems 95 28 Graphical User Interface systems 97 20 29 Experiment 99 29.1 Time-Dilation in Internet-to-FM Audio Signal . . . . . . . . . . . 99 29.2 Experiment Setup Details . . . . . . . . . . . . . . . . . . . . . . 99 30 Result of experiment 101 31 Final production system 103 32 Survey 105 33 Result 107 34 Future work 109 VI Software 111 35 Position of Radio in the 7 Layers of the OSI Model 113 35.1 Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 35.2 Presentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 35.3 Session . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 35.4 Transport . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 35.5 Network . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 35.6 Data Link . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 35.7 Physical . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114 36 Source Code in gnome-internet-radio-locator-3.0.1.tar.xz 117 36.1 gnome-internet-radio-locator.c . . . . . . . . . . . . . . . . . . . 117 36.2 gnome-internet-radio-locator-gui.c . . . . . . . . . . . . . . . . . 147 36.3 gnome-internet-radio-locator-listener.c . . . . . . . . . . . . . . . 163 36.4 gnome-internet-radio-locator-markers.c . . . . . . . . . . . . . . 163 36.5 gnome-internet-radio-locator-player.c . . . . . . . . . . . . . . . 201 36.6 gnome-internet-radio-locator-program.c . . . . . . . . . . . . . . 219 36.7 gnome-internet-radio-locator-runners.c . . . . . . . . . . . . . . . 220 36.8 gnome-internet-radio-locator-station.c . . . . . . . . . . . . . . . 220 36.9 gnome-internet-radio-locator-stations-map.c . . . . . . . . . . . . 243 36.10gnome-internet-radio-locator-streams.c . . . . . . . . . . . . . . . 243 36.11gnome-internet-radio-locator-tz.c . . . . . . . . . . . . . . . . . . 243 36.12gnome-internet-radio-locator-gui.h . . . . . . . . . . . . . . . . . 256 21 36.13gnome-internet-radio-locator.h . . . . . . . . . . . . . . . . . . . 257 36.14gnome-internet-radio-locator-keys.h . . . . . . . . . . . . . . . . 261 36.15gnome-internet-radio-locator-listener.h . . . . . . . . . . . . . . . 263 36.16gnome-internet-radio-locator-markers.h . . . . . . . . . . . . . . 264 36.17gnome-internet-radio-locator-player.h . . . . . . . . . . . . . . . 266 36.18gnome-internet-radio-locator-kb.h . . . . . . . . . . . . . . . . . 268 36.19gnome-internet-radio-locator-player-renderer.h . . . . . . . . . . 269 36.20gnome-internet-radio-locator-player-resourcer.h . . . . . . . . . . 271 36.21gnome-internet-radio-locator-program.h . . . . . . . . . . . . . . 271 36.22gnome-internet-radio-locator-runners.h . . . . . . . . . . . . . . . 274 36.23gnome-internet-radio-locator-station.h . . . . . . . . . . . . . . . 275 36.24gnome-internet-radio-locator-stations-map.h . . . . . . . . . . . . 278 36.25gnome-internet-radio-locator-streams.h . . . . . . . . . . . . . . 281 36.26gnome-internet-radio-locator-tz.h . . . . . . . . . . . . . . . . . . 284 37 Source Code in gnome-radio-0.2.0.tar.gz 289 37.1 gnome-radio-file.c . . . . . . . . . . . . . . . . . . . . . . . . . . 289 37.2 gnome-radio-file.h . . . . . . . . . . . . . . . . . . . . . . . . . 291 37.3 gnome-radio-main.c . . . . . . . . . . . . . . . . . . . . . . . . . 293 VII Software Packages for i386, x86_64 and amd64 301 VIII Figures and Layouts 305 38 Illustrations 307 39 Electronical Layouts 311 39.1 Wireless Transmission . . . . . . . . . . . . . . . . . . . . . . . 312 39.2 Radio Transmission . . . . . . . . . . . . . . . . . . . . . . . . . 313 39.3 Microphone . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314 39.4 Loudspeaker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315 22 IX Classification of radio 317 X Human vs. algorithmic curation of music on radio 321 XI Rescue and emergency communication over public radio 325 XII Essay: Democratic voices on public radio in Norway as Free Software (gnomeradio.org) 329 XIII Binary Delivery 333 XIV Installation Instruction for Public Network Radio Software 337 40 Installation on GNU/Linux 339 40.1 Debian GNU/Linux 10 i386 . . . . . . . . . . . . . . . . . . . . 339 40.2 Debian GNU/Linux 9 amd64 . . . . . . . . . . . . . . . . . . . . 339 40.3 Fedora Core 32 x86_64 . . . . . . . . . . . . . . . . . . . . . . . 339 40.4 Fedora Core 31 x86_64 . . . . . . . . . . . . . . . . . . . . . . . 339 40.5 Fedora Core 30 x86_64 . . . . . . . . . . . . . . . . . . . . . . . 340 40.6 Fedora Core 29 x86_64 . . . . . . . . . . . . . . . . . . . . . . . 340 40.7 Ubuntu 20.04 amd64 . . . . . . . . . . . . . . . . . . . . . . . . 340 40.8 Ubuntu 19.10 amd64 . . . . . . . . . . . . . . . . . . . . . . . . 340 40.9 Ubuntu 19.04 amd64 . . . . . . . . . . . . . . . . . . . . . . . . 340 23 Topics Part I: Electricity Chapter 1: Electrical Engineering Part II: Radio Chapter 2: American, British, Norwegian and European Radio History Chapter 3: Audio waves Chapter 4: Electrical fields Chapter 5: Electrical systems Part III: Computers Chapter 6: Computer systems Chapter 7: Computer storage Chapter 8: Network systems Chapter 9: Network adressing Chapter 10: Internet systems (Internet Protocol) Chapter 11: Domain Name Systems for Internet systems Chapter 12: Radio microphones Chapter 13: Audio systems Chapter 14: Audio codecs Chapter 15: Audio fingerprinting Chapter 16: Audio response Chapter 17: Visual response Chapter 18: Graphical Display interfaces Chapter 19: Operating systems Chapter 20: Installation systems Chapter 21: Desktop systems Chapter 22: Mapping systems Chapter 23: Graphical User Interface systems Chapter 24: Experiment Chapter 25: Result of experiment Chapter 26: Final production systems Chapter 27: Survey Chapter 28: Result Chapter 29: Future work Part IV: Software Chapter 30: Position in the 7 Layers of the OSI Model Chapter 31: Source Code in gnome-internet-radio-locator-3.0.1.tar.xz 24 Chapter 32: Source Code in gnome-radio-0.2.0.tar.gz Chapter 33: Software Packages for i386, x86 64 and amd64 Chapter 34: References Part V: Software Packages for i386, x86 64 and amd64 Part VI: Figures and Layouts Chapter 35: Illustrations Chapter 36: Circuits Part VII: Classification of radio Part VIII: Human vs. algorithmic curation of music on radio Part IX: Rescue and emergency communication on public radio Part X: Essay: Democratic voices on public radio in Norway as Free Software (gnomeradio.org) Part XI: Binary Delivery Part XII: Installation Instruction for Public Network Radio Software 25 26 Part I Electricity 27 Chapter 1 Electrical Engineering A. P. Trotter, a leading British electrical engineer, wrote that “electrical engineer- ing was born at the Paris Exhibition” (1889), one of the first long distance radio transmissions happened from the Eiffel tower in Paris from the Paris Exibition in 1889 on January 12, 1908. As it is shown in this Master thesis, that primarily documents the computer software implementation in the computer programming language ANSI C of the Free Software radio software packages GNOME Internet Radio Locator (gnome- internet-radio-locator) and GNOME Radio (gnome-radio) implemented and pub- lished in this paper, it was possible to visualize some of the modern age Inter- net radio broadcasters on a world map about 109 years later in 2017 with the help of the free software libraries GTK+/GNOME, GStreamer and libchamplain in the GNOME Radio project (http://www.gnomeradio.org/) and auto- matically begin the reception of a live radio broadcast on a personal computer running the free computer operating systems Debian GNU/Linux, Fedora Core and Ubuntu Linux from free radio stations broadcasting around the world over the Internet. Visit http://www.gnomeradio.org/ for details on how to install soft- ware for visualizing the location on a world map and begin the reception of a live radio broadcast on Free Software systems such as GNU/Linux. The work continues in the GNOME Radio project after this thesis was sum- moned on February 26, 2020, with the release of GNOME Internet Radio Locator version 3.0.1 for Fedora Core 32 (2020) in http://www.gnomeradio.org/~ole/fedora/ To install GNOME Radio on Fedora Core 32 Desktop (2020), download the RPMfile http://www.gnomeradio.org/~ole/fedora/RPMS/x86_64/gnome-internet-radio-locator-3.0.1-1.fc32.x86_64.rpm and run rpm -Uvh http://www.gnomeradio.org/~ole/fedora/RPMS/x86_64/gnome-internet-radio-locator-3.0.1-1.fc32.x86_64.rpm 29 as root. 30 Part II Radio 31 Chapter 2 American, British, Norwegian, and European Radio History According to The Oxford Companion to American History, radio was theoreti- cally foreseen in 1865 by the Scottish physicist James Clerk Maxwell. His elec- tromagnetic equations led to experiments by the German physicist Heinrich Hertz, who, by using an electrical discharge, produced the ’hertzian,’ or radio, waves (1886). His work was in turn advanced before 1900 by the research of the Italian physicist Guglielmo Marconi, and by the electrical engineer John Fleming, who perceived that a specially constructed light bulb (’diode’) could serve to detect ra- dio signals. The related invention in 1906 of the three-electrode vacuum tube by Lee de Forest made radio practicable by its ability to amplify weak signals. The first successful telegraph was demonstrated by Samuel Finley Breese Morse, with a network linking Washington DC to Baltimore in the United States of America with 35 miles of copper cable. His first transmitted telegraphic mes- sage on May 24, 1844 was: “What hath God wrought”, transmitted in Morse code on line from Washington, D.C., to Baltimore, according to the books “Principles of Digital Audio” by Ken C. Pohlmann published by McGraw-Hill in 2000 and Webster’s Guide To American History published by G. & C. Merriam Company, Publishers in Springfield, Massachusetts, U.S.A. in 1971. Though construction of line was financed by the government, Morse failed to persuade it to buy rights to his invention and formed his own company. His partner Alfred Vail invented telegraphic printer in 1844. On February 14, 1876, Alexander Graham Bell, a successful teacher of the deaf, filed for a patent on a magnetoelectric telephone device where the human voice could be transmitted in a two-way system. He demonstrated his invention 33 on March 10, 1876 at the Philadelphia Centennial Exhibition of 1876 and attacted considerable attention. The first telephone system, with 21 subscribers, was es- tablished two years later in New Haven, Connecticut. Thomas Alva Edison produced the initial audio wave recording on a sheet of tin foil wrapped around a cylinder that can be turned on December 6, 1877 of him reciting “Mary Had a Little Lamb”. The first telephone communication between cities opened in 1877 between Salem, Massachusetts, and Boston, and Chicago and Milwaukee. By 1880 almost 150 separate telephone companies were operating 34,000 miles of lines. The successful development of telegraph and telephone in the United States led to near-monopolies by Western Union (telegraph) and American Telephone and Telegraph Company (AT&T) (telephone). At the same time, as electricity was used more after 1880, companies appeared that manufactured electric lights, electric motors and the like. The most important electrical manufacturing firms were Westinghouse, started in 1886, which brought the alternating current power system to the United States, and General Electric (GE), formed in 1892 as an amalgamation of two older firms, including Thomas Alva Edison’s. After sev- eral years of competition and patent arguments, GE and Westinghouse agreed in 1896 that GE should receive two-thirds of the business growing from their shared patents. This early patent “pool” agreement was an important precedent for the ra- dio manufacturing industry. Another important firm was Western Electric, which specialized in telephone communications equipment and was taken over by Amer- ican Telephone and Telegraph Company in 1881. The first important armed-forces tests of radio were conducted independently by the United States Navy and the British Royal Navy in 1899. The American tests were made of Marconi apparatus aboard the U.S. battleships New York and Massachusetts. Although radio signals bridged distances of up to 40 miles, it was clear that the lack of suitable tuning devices led to unacceptable interference. Radio clearly was such a potential saver of lives and property in peril at sea that otherwise practices that interfered with its maritime operation had to be overcome. By 1909 the Bell system was so successful that the American Telephone and Telegraph Company (AT&T) was able to purchase Western Union - only to have to resell it in 1914 because of the antitrust laws. AT&T was split into several parts in 1884. Bell’s basic patents expired in 1894. The Radio Act of 1912 established several key legal and regulatory principles that continue to undergird broadcast regulation 34 Radio broadcasting was a new electrical communications concept. Radio re- moved our dependence on wires, and finally “broadcasting” presented a new con- cept. Wireless, or radio, is a logical extension of wired telegraphy and telephony. Wires are easily broken and hard to string between distant communities or over physical obstacles. With wireless techniques, communication could take place as rapidly as with wired devices but did not require a physical connection. Distant locations could be contacted quickly, relaying might be unnecessary, and ships could keep in touch with land. The penalty for this was that a radio message would go out in all directions at once and could be picked up by anyone who cared to listen. The Radio Act of 1912 established several key legal and regulatory principles that continued to undergird broadcast regulation more than three quarters of a century later. In the beginning the federal government would control broadcasting. No one could broadcast without a license from the Secretary of Commerce and Labor. The 1912 Act declared that broadcasting without a license was illegal and that only the government could convey a license. During World War I, the Navy was able to gain control of all radio stations in the United States except those operated by the Army. The Radio Corporation of America came into being 17 October 1919. In March 1919, only a few months after the end of the First World War, the voice of a British wireless operator was heard nearly three thousand miles away across the Atlantic in the United States. This was probably the first external broad- cast ever made from the British Isles - the transmitter was in Ballyunion in Ireland - and was look on at the time as uncanny, according to the book “A Skyful of Freedom - 60 Years of the BBC World Service” by Andrew Walker published by Broadside Books Limited in 1992. Once the wartime restrictions on transmission were lifted in September 1919, the amateur broadcasters were back in force, and because so many had served in the war, they were familiar with the latest technological advances. Radio remained in its experimental stage until improvements, especially those by E. F. W. Alexanderson, who opened the way for a primitive form of broad- casting in 1920. Soon thereafter notable advances made possible the growth of broadcasting chains and the development of international transmissions. Following the broadcast of the 1921 World Series between the Yankees and the Giants on WJZ, broadcasting as we know it took off. In late March 1923 Hoover called a second National Radio Conference. 35 In 1924 there was 2,500,000 radios in the United States, as opposed to 5,000 sets in 1920. On November 30, 1924 Radio Corporation of America (RCA) demonstrated wireless telegraph transmission of photographs from New York to London. The first loudspeaker was developed in 1925 by Rice and Kellog shortly after the valve amplifier. The British Broadcasting Corporation was established on 1 January 1927. It was the direct successor of the British Broadcasting Company which had been formed in 1922 as a consortium of manufacturers of domestic wireless receiving sets. The newly-established body was now set up as a public corporation under Royal Charter, deriving its authority from the King in Council. This constitutional device was adopted in order to distance the corporation from the government and from parliament, although ultimately it was to be responsible to them. Designed to provide public service broadcasting of a high quality the BBC enjoyed a monopoly until 1955, when commercial broadcasting was introduced. Initially, the BBC was put under the control of the Postmaster General, but in 1974, broadcasting matters were transferred to the Home Office, and the Home Secretary became the minister responsible for broadcasting. As the minister in charge of the BBC at the time of its establishment, the Postmaster General assumed the task of framing its legal basis. And, despite the fact that the BBC was meant to be distanced from the gov- ernment, he provided himself with overriding formal powers over transmissions and the content of programmes: among other things, he could require the BBC to broadcast or to refrain from broadcasting any matter as he saw fit. (Etzioni-Halevy 1988) In the United States of America, National Broadcasting Company was orga- nized as first nationwide radio broadcasting network in 1926; National Broad- casting Company (NBC) was established in 1926, Columbia Broadcasting Sys- tem (CBS) was organized in 1927 and Mutual Broadcasting System (MBS) was founded in 1934. Federal Radio Commision was created in 1927. The Radio Act of 1927 en- acted ideas that had been in the legislative hopper since the first National Radio Conference. The two key aspects of the Radio Act of 1927 are the declaration that there could be no private ownership in the entire spectrum and the related decision that users of the spectrum would be licensed under the public interest standard. The new Radio Act put first things first. Although the 1912 Act had required a license to use the air, it had been silent on the issue of ownership of the airwaves. The 36 1927 Act was not. It bluntly declared that there could be no private ownership of the airwaves; they were public and use could occur only with the government’s permission. That permission, in the form of a license, would be granted without charge, but for no more than three years. The first audio broadcasts used amplitude modulation (AM) of the carrier wave in the MF and HF bands. According to the book “The Art of Sound Repro- duction” written by John Watkinson and published by Focal Press in 1998, AM broadcasts are prone to interference and do not reproduce the whole frequency range, but AM works for long distance broadcasts. Shortly before the Second World War frequency modulation (FM) was developed. Edwin H. Armstrong, originally backed by Radio Corporation America, devel- oped a system for transmitting radio based on modulation in the frequency (hence FM, frequency modulation) instead of the amplitude (AM, amplitude modulation) of the radio wave. FM can transmit anything the human ear can hear and more. AM has the advantage that it can transmit farther than FM, but that is its only advantage. Armstrong was believed to have conceived and invented wideband frequency modulation (FM) on September 1931, while his patent was granted on December 26, 1933. In November 1934 Federal Communications Commission (FCC)replaced Fed- eral Radio Commission. It is authorized to control all foreign and interstate radio, telegraph, and cable communications. According to Section 3(0) of the Communications Act of 1934, broadcasting is “the dissemination of radio communications” intended to be received by the public, directly or by means of intermediary relay stations. We should establish here that broadcasting signifies transmission of music, speech, and/or pictures in forms that the general public can understand, on a regu- lar and announced schedule, on a frequency band for which the general public has receivers, by a station licensed by the government for that purpose (if licensing was then required). The public interest was a bedrock requirement for the issuing of a radio station license from the very beginning. It is a paramount philosophy of the Communica- tions Act of 1934. By the late 1930s, radio was woven into the fabric of American life. Public events, from political rallies to sporting events and vaudeville routines, were now enjoyed by millions in private. 37 The invention in 1939 of a new form of radio transmission and reception, frequency modulation (FM), by E. H. Armstrong, eliminated static and improved fidelity. In the beginning the Federal Communications Commission (FCC) granted ra- dio station licenses and required radio stations to classify programming into a min- imum of seven categories: Entertainment, Religion, Agricultural, Educational, News, Discussion, and Talks. Increasingly, Americans got their news from radio, especially news of the ex- panding war in Europe. The immediacy and drama of the war news tied people more intimately to unfolding events, it also, apparently, put some on edge. During World War II listening to radio from the BBC became very important in Norway, where the BBC at first had problems of credibility because of its over- optimism during the military campaign of 1940. It was accused of having put out “fake news” - “just another form of propaganda” much like the U.S. President Donald J. Trump accused the media of in the beginning of his presidency. The Norwegian democratically elected government and King Haakon escaped to London on April 9th, 1940 and so did several members of the broadcasting service. They were eventually seconded to the BBC at their own request and worked so successfully with their British colleagues that by 1941 a Norwegian who escaped to the United States was reporting: “Nobody reads any news papers or listens to any radio except the BBC.” After Denmark was occupied by Nazi Germany in 1940 a Danish political leader who had escaped to Britain broadcast a call for action over the Danish service when it did report the heroism shown in other occupied countries in 1942. From then on Danes regarded themselves at war and the BBC was with them. The North American service gradually grew until by 1942 it was on the air for more than seven hours a day. By that time the United States was in the war, and there were programmes linking the American and Canadian forces in Britain with home. American programmes were transmitted to Britain via a BBC studio in New York. On D-Day, the invasion of Normandy, no fewer than 725 out of 914 radio stations in the U.S.A. carried BBC War Reports. In the first half of 1945 regular rebroadcasting reached a peak. It was estimated that over 15 million people in the States were hearing one or more BBC programmes a week as the war in Europe drew to a close. (Walker 1992) 38 By 1950 92% of households had radios, and the direction of industry expan- sion was in the range of offerings (stations) and in the encouraging the ownership of more than one radio. In contract, at that time only 62% of households had a telephone. Over the next 38 years, the role of radio changed, but did not diminish. From In 1957 FM accounted for only 2 percent of radio ad sales, but increas ed to 15 percent by 1965. Corporation for Public Broadcasting is a private, nonprofit corporation created by Congress in the Public Broadcasting Act of 1967. In 1969 the Public Broadcasting System (PBS) was established, which re- ceived some federal money to support noncommercial and educational programs. But according to The Reader’s Companion to American History, PBS must still rely on viewer support and corporate sponsorship to survive. In 1970 with the help from Corporation for Public Broadcasting, National Pub- lic Radio (NPR), America’s first National Public Radio Network was established. By 1988, the average household had six radios, and four out of five adults listened to the radio every weekday. Delivery of digital audio files over the Internet had became possible in the early 1990s, soon after the introduction of the World Wide Web and browsers, partly thanks to the new and efficient audio coding system of mp3 (MPEG-1 Au- dio Layer III), developed at the German Fraunhofer Institute between 1988-1992 simultaneously with audio coding for DAB (Fraunhofer 2009). First attempts to stream audio over the Internet were also made by that time, and after the introduction of the essential computer software such as Real Audio, streaming started to gain popularity (Priestman 2002; Menduni 2007). Earlier when one had to first download the audio file and then listen, the stream player made it possible to listen to the audio while also receiving it. The sound quality was not very high at first, but the number of radio stations offering audio streaming services over the Internet grew rapidly in the 1990s, especially in the United States (Lax and Ala-Fossi 2008). Digital radio is one of the most exciting developments ever in radio. The crys- tal clear sound, utterly silent background and interference free reception delivers a new level of performance from broadcast sources. The New York Times welcomed the new digital revolution as the “biggest technological leap” since FM technology was developed in the 1940s and 50s’, offering the same “high quality” of sound – free of static and hiss. (O’Neill 2010). The experience of a digital broadcast of a live symphony orchestra concert is astonishing. 39 40 Chapter 3 Sound waves On radio you can listen to immediate sound waves in the broadcasts. Longitudinal waves in a medium, usually in air, are called sound waves. The most general dedinition of sound is a longitudinal wave in a medium. The wave function for a sound as a longitudinal wave y(x,t) can be described as the interval t with amplitude A with the cosinus function, if the wave is sinu- soidal. y(x,t) = Acos(kx−ωt) (3.1) In the longitudinal wave the displacements are parallel to the directional of travel of the wave, so distances x and y are measuree parallel to each other, not perpendicular as in a transverse wave. The amplitude A is the maximum displace- ment of a particle in the medium from its equilibrium position. Sound waves from radio in air are compressed and decompressed pressure fluctuations between the amplitude device and human ears. This field is further described in biology or physics and is not a subject in electrical engineering, but we know that the human ear is sensitive to waves in the frequency range from about 20 to 20,000 Hz, the audible range, that can be reproduced on electronical devices as the pressure differences can be sensed on microphones and simular devices. For audio in uncompressed form (16-bit linear PCM) with a sample frequency of 48kHz the data transferred is equal to 48000 Hertz that equals 1536000 bits per 41 second or 192 kbits per second. 2Π Waves of shorter wavelength Λ (larger wave number k = have greater Λ pressure variations for a given displacement amplitude because the maxima and minima are squeezed closer together. In electrical engineering an audio receptor is a microphone, while an audio transmitter is a loudspeaker or a headset. The speed of sound in hot air (20 C) is 343 meters/second. The sound wave falls to 0 dB after the initial signal-to-air curve. With Internet radio there is very little or no delay in sound waves in the broad- casts between the listener and the presenter or musician in a live radio broadcast. 42 Chapter 4 Electrical fields Electrical fields are based and formed when a wire is ignited with power from a power generator such as a dynamo, turbin generator or chemical fluid in a battery such as 9 Volt batteries from Duracell, Energizer or VARTA. The duration of the electrical field is determined by the flow of electrical current and the flow of electrons from negative to positive charge measured in Coloumb. 43 44 Chapter 5 Electrical systems An electrical system consists of a wire, a circuit, a power source and a capacitor. There are three important kinds of electrical transmissions: conduction, in- duction and radiation. 5.1 Conduction Conduction means the sending of impulses through a medium capable of trans- mitting electricity - a wire, salt water, or the earth. 5.2 Induction Induction refers to the appearance of a current in one circuit when it is placed near another, already charged, circuit, without a physical connection. Induction can cause cross-talk on a telephone circuit, and induction coils permit the recording of telephone conversations without wire hookups. 5.3 Radiation Radiation means the generation of electromagnetic waves, generally sent out from an antenna. The radio transmissions of today use this last method, which became practical just before 1900. The major findings of Scottish mathematician and physicist James Clerk Maxwell, published in 1864, suggested that a signal could be sent out electromagnetically 45 that would be completely detached from the point of origin. Using mathematical equations, he demonstrated that electricity, light and heat are essentially the same and that all radiate at the same speed in free space. German physicist Heinrich Hertz demonstrated the correctness of Clerk Maxwell’s theories in a series of experiments in 1887 and 1888. The fundamental unit of frequency, the Hertz (Hz), is named for him. Hertz measured the speed of electro- magnetic radiation (the speed of light), the length of various waves, and similar parameters but did not promote the use of wireless for communication. In 1894, at the age of 20, Guglielmo Marconi read of Hertz’s experiments and aimed to apply this knowledge to communication. By 1896 he could transmit and receive two miles or more on his father’s estate near Bologna. On Christmas Eve 1906, Reginald Fessenden (1866-1932), the inventor of amplitude modulation (AM), transmitted a program of speech and music from Brant’s Rock, Massachusetts, in what was probably the first radio broadcast in the United States of America. Reginald A. Fessenden became a professor of electrical engineering at the University of Pittsburg after having worked for Thomas Alva Edison and with the U.S. Weather Bureau on a system of wireless transmission of forecasts. He wanted to develop a workable system of transoceanic wireless using continous waves rather than Marconi’s spark gap technique. Fessenden believed that this method would provide the power necessary for more effective Morse code trans- missions and simultaneously create the quieter carrier wave required for voice transmission. 46 Part III Audio 47 Chapter 6 Digital Audio Digital audio systems spread in the United Kingdom, when BBC research engi- neers developed a system for combining the television sound signal, known as send in syncs, still used by the BBC and independent UK television companies, according to Michael Talbot-Smith’s book "Sound Engineering explained" pub- lished by Focal Press in 2002. In the early 1970s, BBC radio adopted digital audio. According to Harry Nyquist, the sampling frequency R to reproduce the band- width B must be twice as large as the bandwidth B in cycles per second. 2R > B (6.1) Nyquist’s Law, named in 1933 after scientist Harry Nyquist, states that a sound must be sampled at least twice its highest analog frequency in order to extract all of the information from the bandwidth and accurately represent the original acoustic energy. Sampling at slightly more than twice the frequency will make up for imprecisions in filters and other components used for the conversion. For example, human hearing ranges from 20Hz to 20,000Hz, so to imprint sound to a CD, the frequency must be sampled at a rate of 40,000Hz to reproduce the 20,000Hz signal. The CD standard is to sample 44,100 times per second, or 44.1 kHz. The compact discs - the CD - used the principles of digital audio and was released in 1982. With digital audio, the original analogue signal is converted into a code of much more robust signals. These take the form of pulses of voltage of standard height and duration. 49 It is possible to reconstruct the height and duration of the pulse as digital audio. The analogue signal is split up into small sample, the ’height’ is known as the amplitude which is measured in the next stage. Sampling in CDs and modern digital audio systems is done with a rate of just over 44000 times a second. Each sample has to be measured, known as quantizing, the process of measuring the amplitude of each sample. Good quality digital audio needs at least 65000 quantizing levels, each mea- surement is a number between 0 and 65000! Digital audio systems store numbers thst can be anything up to 65000 and do it at a rate of just over 44000 each second, stored in binary arithmetic of only two digits, 1 and 0. 50 Chapter 7 Solid state recording 1 second of stereo sound contains about 1.4 megabits without taking into account bits for timing, error detection and correction. 2 megabits per second is a rea- sonable bare minimum, so a minute of good stereo audio needs about 14 or 15 megabytes as the unit of memory storage in computers is the byte, equivalent to 8 bits. 51 52 Chapter 8 Audio compression Compression of digital audio means reducing the number of bits in an audio sam- ple without a serious reduction in quality. It’s possible by fairly recent development in digital audio. There are many ’sounds’ that we cannot hear: frequencies in the region of 30 Hz unless at a high level, for example. The normal ear is about 70 dB less sensitive to 30 Hz than it is at around 3 kHz and not particularly sensitive to the higher audio frequenciew above about 3 kHz. 53 54 Chapter 9 MPEG 1.0 Audio Layer III, Ogg Vorbis and MPEG-4 AAC By running heavy audio compression algorithms in MPEG-1 Layer III (MP3), Ogg Vorbis and MPEG-4 Advanced Audio Codec (AAC), computers can store recorded audio from solid state recording for considerable durations on to a solid state storage card or in random access memory. 55 56 Chapter 10 Streaming audio The combination of digital audio, solid state recording, data compression and MPEG 2.0 Audio Layer III results in compressed audio streaming in the free and public internet radio client software gnome-internet-radio-locator documented in this thesis. 57 58 Part IV Computers 59 Chapter 11 Computer systems A computer system is a digital machine for computing numbers and performing binary arithmetic of the digits 1 and 0, producing printed papers, transmitting data between another computing system, visualizing graphics such as a map on a display system as described in Chapter 13 (“Graphical Display Interfaces”) and resonating audio. 61 62 Chapter 12 Computer storage Computers operate with temporary storage and solid-state storage. In this thesis the storage is temporary and the data is a stream of audio between two computers and a stream of map data as tiles. See Chapter 17 (“Mapping Systems”). Computers can store its physical location with GPS. The logical components read a stream of audio from the position of the GPS antenna and displays the public broadcasts nearby. The saturation will bring resonnance to the public spot and give a good record- ing of audio from all angels and balcony spots. The playback of the audio record- ing will be very precise. I propose MLAR, a format for multiple-location audio recording (MLAR). MLAR, built on software from Xiph.org, will enable record- ing from multiple device audio for playback and entertainment, with radio locator and absolute precision (up to 10 meters). 63 64 Chapter 13 Network systems A network system consists of three or more digital computer systems (see Section 3.1 on “Computer systems”) that can connect between separated physical space and fields (see Chapter 4 on “Electrical systems”). 65 66 Chapter 14 Network adressing Network adressing in IP is based on Internet Protocol adressing of computer net- work adressing (physical and logical link). 67 68 Part V Internet 69 Chapter 15 Internet systems (Internet Protocol) The Internet was built upon the Internet Protocol described in RFC 781 (1981) and RFC 8098 (2017), documents known as “Request for Comments”. 71 72 Chapter 16 Domain Name Systems for Internet systems The first Internet domain was symbolics.com introduced in 1985. The rationale behind Internet domains under .com were commercial, not in the public benefit like .org domains. When computers were set up in networks, the Internet Protocol addresses were at first static and stored in /etc/hosts on Unix. At some point ICANN, ISC and IETF decided that the DNS configuration should be hierarchical. Today we have a system where domain names expire 1 year after the registra- tion date which promotes the free market dynamics, but does not solve a technical problem, because the domains stop working when the network operators don’t receive the annual yearly fee for the domain from the domain registrant and com- petes against registrars. The root servers on different Internet servers are hierarchical. There are in- dications that domains should be dynamically configured, maintained and stored forever. There should be a public archive of domain name system records with historical records. GNOME Internet Radio Locator is such a public archive for live streams from 124 public radio station in the domain name system with locality annotation. 73 74 Chapter 17 Radio microphones Radio microphones are widely used in film, broadcasting, theater and other in- dustries, and it is not difficult to think of circumstances in which freedom from trailing microphone cables can be a considered advantage in all of the above. See “Sound and recording” by Francis Rumsey and Tim McCormick pub- lished by Focal Press for a discussion and a typical 48 volt phantom powering arrangement in an electronically balanced circuit. 75 76 Chapter 18 Audio systems Audio was previously recorded for the first time by Thomas Alva Edison on tin foil in 1878. Marconi invented long-distance transatlantic radio in 1901 and received the Nobel Prize in Physics for this work in 1909 with Karl Ferdinand Braun. The gramophone industry was built on recorded music, for private listeners, public spots and playback on radio. A public gramophone player, the jukebox, brought music to the public and private rooms. Radio kept playing songs on request and some still do. When the jukebox and audio amplification systems in homes became popular, radio still survived, even with the introduction of streaming audio systems in the early 2000 after the introduction of audio codecs with good compression. See Chapter 13 (“Audio codecs”). 77 78 Chapter 19 Audio codecs The supported audio codecs in GNOME Internet Radio Locator are based on the implementation of codecs in GStreamer such as MPEG, FLAC, Ogg Vorbis and Advanced Audio Codec (AAC). MLAR, proposed in Section 3.2 on Computer storage, will store recorded au- dio in locations, at historical moments and scale rooms from different view points. MLAR stands for Multi-Location Audio Recording. Picard from MetaBrainz Foundation is a cross-platform music tagger written in Python that uses AcoustID audio fingerprints, allowing files to be identified by the actual music, even if they have no metadata. 79 80 Chapter 20 Audio fingerprinting • Audio Fingerprinting software written in C .NET by Yvo Nelemans https://github.com/nelemans1971/AudioFingerprinting • Open source audio fingerprinting of broadcast mp3Open source audio fin- gerprinting of broadcast mp3 https://stackoverflow.com/questions/38566477/open-source-audio-fingerprinting-of-broadcast-mp3 • Echoprint - An open music identification service https://www.ee.columbia.edu/~dpwe/pubs/EllisWP11-echoprint.pdf • Codegen for Echoprint https://github.com/spotify/echoprint-codegen • Finding duplicate songs in your music collection with Echoprint https://musicmachinery.com/tag/echoprint/ • MusicBrainz Fingerprinting https://musicbrainz.org/doc/Fingerprinting • The Echo Nest http://the.echonest.com/ 81 82 Chapter 21 Audio response The response of audio is vital in any audio system. Radio broadcasts important messages that sometimes are location-sensitive to the public and it is crucial in saving lives with distance between the signal and location. The distance for audio broadcasted on radio is typical limited by the power of the radio transmit in FM. With radio broadcasted over the Internet, the distance is unlimited. 83 84 Chapter 22 Visual response The response of visual elements are essential in any graphical system. Quick visual response makes it easy to operate a computer system with a screen and a navigation device. See Chapter 22 (“Graphical User Interface systems”). 85 86 Chapter 23 Graphical Display interfaces The X Window System revolutionized the computing industry when it was in- troduced at Massachusetts Institute of Technology (M.I.T.) in 1984. GTK+, the GNU Image Manipulation Toolkit, announced at UC Berkeley in 1996, was the first free, LGPL widget toolkit for the X Window System and it made it possible to write Free Software programs with good graphical appearance for the X Window System in networks. The GNOME project, a free desktop for the X Window System built on the GTK+ library, was announced in 1997 at UNAM in Mexico City. The work on GNOME Internet Radio Locator began in 2002 at Norwegian Computing Center and continued after a visit to M.I.T. in Cambridge, MA in June 2014 as I became aware of OpenStreetMap, libchamplain and GNOME Maps. The initial 1.0 release was announced on gnome-announce-list@gnome.org and published on https://download.gnome.org/sources/gnome-internet-radio-locator/ Work on the GNOME 3 application gnome-internet-radio-locator began in 2017 and work on the GTK+ 4 application gtk-internet-radio-locator began in 2018. Work on writing the GNOME Radio application gnome-radio from scratch began on February 17, 2019. 87 88 Chapter 24 Operating systems The introduction of the Linux kernel by Linus Torvalds at University of Helsinki, after the delay of the GNU Hurd microkernel, written from scratch in machine assembler and published under the GNU General Public License, marked the next technical revolution in home computing and eventually saved the society from huge costs as server operating system. With Linux it was finally possible to install Free Unix on a personal computer. Alan Cox wrote large parts of the networking code and sound code at University of Wales Swansea in the early 1990s. Mac OS X from Apple, Inc. is a proprietary operating system shipped with Macs. The stability of the kernel in Mac OS X is due to work by Jordan Hubbard from the FreeBSD project and the maintenance of the Darwin kernel took many years of work between 2000-2018. The choice of UNIX by Apple made many developers switch from Linux to Mac OS X. 89 90 Chapter 25 Installation systems Debian GNU/Linux and Ubuntu Linux maintains a software installation package repository based on APT and dpkg. http://www.gnome.org/%7eole/debian/ http://www.gnome.org/%7eole/ubuntu/ Fedora Linux maintains a tree of software in the dhf installation system on top of RedHat Package Manager (RPM) packages. http://www.gnome.org/%7eole/fedora/ The MacPorts project makes it easy to install open-source/free software on Mac OS X with the port command in Terminal from a package repository based on FreeBSD ports. The MacPorts packages gnome-internet-radio-locator and gnome-radio contain the packaged software implemented and described in this thesis. https://ports.macports.org/port/gnome-internet-radio-locator/summary https://ports.macports.org/port/gnome-radio/summary 91 92 Chapter 26 Desktop Systems The rise of Linux in the late 1990s with the GTK+ and GNOME projects made people aware of the importance of free licenses and the consequences of bad li- censing. The Open Source Initiative was launched in 1998 and it was crucial in the public release of the Mozilla Web Browser source code from Netscape, Inc. Some supporters of Open Source were critical of the GNU General Public Li- cense. The next generation of the Library GPL was dubbed Lesser General Public License. Free Software developers kept working on GTK+, GIMP and GNOME and GStreamer. 93 94 Chapter 27 Mapping systems In mathematics, the four color theorem, or the four color map theorem, states that, given any separation of a plane into contiguous regions, producing a figure called a map, no more than four colors are required to color the regions of the map so that no two adjacent regions have the same color. The four color theorem reduces the number of colours that are required to produce maps into four colours. It was proved around 2004 by Steve Coast and the community began work on free geographical maps in the OpenStreetMap.org project. The project produces free maps of geographical sites, buildings and roads in a crowd-sourced project dubbed OSM. In 2013 the GNOME project released GNOME Maps. In 2017 support for OpenStreetMap in GNOME Internet Radio Locator as well as support for libchamplain and gst-player was implemented. In 2018 the work on the GTK+ 4.0 port began as gtk-internet-radio-locator that is published in https://download.gnome.org/sources/gtk-internet-radio-locator/ 95 96 Chapter 28 Graphical User Interface systems In 2017 libinput, a Free Software project to build graphical user interface cursors and device input systems for Wayland, the replacement display system after The X Window system, was presented at GUADEC 2017 (see chapter 13: Graphical Display Interfaces). It provides input support for mice, trackballs, and touch pads. Work on documenting GNOME Internet Radio Locator began at GUADEC 2017 at Manchester Metropolitan University in July 2017. 97 98 Chapter 29 Experiment With components from BuildCircuit in Australia the FM transmitter hardware was built by Adrian Szabo Aabech. The software gnome-internet-radio-locator was built by Ole Kr. Aamot. A breadboard with 5 resistors, 8 condensators, 1 inductor and 17 nodes was configured for the experiment Internet-to-FM. The transmitter works from 3 to 9 Volt for FM 92.1 Mhz. The range distance is 10 meters with 30 cm antenna. 29.1 Time-Dilation in Internet-to-FM Audio Signal An experiment in backward signal processing was performed successfully in 2017 by Adrian Szabo Aabech and Ole Kr. Aamot. Acomputer connected to the FMtransmitter hardware and Internet WiFi broad- casted international radio broadcasts from gnome-internet-radio-locator to the band- width FM 92.1 Mhz from remote audio sources broadcasted with HTTP/1.1 over the network stack TCP/IP, hereby known as “Internet-to-FM”. 29.2 Experiment Setup Details http://www.gnome.org/%7eole/HIOA2017.pdf 99 100 Chapter 30 Result of experiment Visual switching with audio feedback delay worked with Internet-to-FM for FM transmitter broadcasting to FM receiver wirelessly connected to a computer con- nected to WiFi and visually running gnome-internet-radio-locator and broadcast- ing audio over FM via live audio stream over Wireless Internet. We could hear the latency delay between FM 92.1 MHz and WiFi 2400 GHz. 101 102 Chapter 31 Final production system In 2001 Norwegian Computing Center built a full audio recording studio in the Kristen Nygaard Building in Forskningsparken and organized 01lab, a conference and meeting place for scientists and artists. A full studio was designed and built by Benum. In 2002 I began work on a XML DTD and the GNOME Internet Radio Locator program to stream audio from a FM radio connected to the Internet in the studio of Radio NOVA, Radio Tellus and radiOrakel to the GNOME desktop. 103 104 Chapter 32 Survey Two of three patients, the third who is my opponent who thinks that you should only listen to local radio stations, answered that they enjoyed listening to NRK P2 and NRK Alltid Klassisk. Two of three nurses prefer NRK P3, while the third who is my defender thinks that BBC World Service is the best radio station, because it’s from around the world. The patient subject Geir installed Ubuntu 20.04 and GNOME Internet Radio Locator 3.0.1 on his MacBook Air. The patient subject Anne prefers free walking in nature. The experiment with the patient was successful. The Corona epidemic in March 2020 led to isolation, while the nature of radio is social and less people meet each other. Radio as a medical technology is a tool in certain situations, but meeting other people is important. Radio can be an isolating facot in our lives, but is a social tool for people with social anxiety. 105 106 Chapter 33 Result The Internet-to-FM radio experiments with GNOME Internet Radio Locator soft- ware that finalizes the ideas explained in this thesis is available from https://www.gnome.org/%7eole/gnome-internet-radio-locator and https://download.gnome.org/sources/gnome-internet-radio-locator/3.0/gnome-internet-radio-locator-3.0.1.tar.xz 107 108 Chapter 34 Future work In May 2018 the work on the GTK+ 4.0 port began as gtk-internet-radio-locator that is published in https://download.gnome.org/sources/gtk-internet-radio-locator/ http://www.aamot.org/ole/thesis/aamot-thesis-20180929.zip In August 2019 I announced the GNOME Radio Project and published a con- ference talk on GNOMERadio during GUADEC2019 available from http://www.gnomeradio.org/GUADEC2019.pdf with source code available from http://www.gnomeradio.org/0.2/gnome-radio-0.2.0.tar.gz 109 110 Part VI Software 111 Chapter 35 Position of Radio in the 7 Layers of the OSI Model A Public Network Radio Software for accessing Free World Broadcasts on Inter- net such as GNOME Radio is positioned in the following 7 Layers of the OSI Model: • Application (End User Layer): HTTP, DNS • Presentation (Syntax Layer): MPEG, OGG • Session (Synchronization): GStreamer • Transport (End-to-end Connections): TCP, UDP • Network (Packets): IP, ICMP, IPSec, IGMP • Data Link (Frames): Ethernet • Physical (Physical Structure): Coax, Fiber, Wireless, Hubs, Repeaters) 35.1 Application Application | GUI systems | End User Layer | Protocol Name Radio | GTK+, GNOME | X, Wayland | HTTP, DNS 113 35.2 Presentation Presentation | Mapping systems | Syntax layer | Protocol Name Audio Map | Champlain, OpenStreetMap | MPEG, OGG | ASN.1 35.3 Session Session | Desktop systems | Synchronization | Protocol Name Synch | GStreamer | GstClock | PTP 35.4 Transport Transport | Operating systems | End-to-end connection | Protocol Name Linux | GNOME | TCP, UDP | TCP/IP 35.5 Network Network | Internet systems | Packets | Protocol Name Internet | INET | IP, ICMP, IPSec, IGMP | TCP/IP 35.6 Data Link Data Link | Computer systems | Frames | Ethernet WiFi | 802.11 | MAC | LAN 35.7 Physical Physical | Network systems | Physical structure | Protocol name Hardware | PC, Mac, Router, Switch, Patch Panel | PCB | Coax, Fiber, Wireless, 114 Hubs, Repeaters 115 116 Chapter 36 Source Code in gnome-internet- radio-locator-3.0.1.tar.xz http://download.gnome.org/sources/gnome-internet-radio-locator/3.0/gnome-internet-radio-locator-3.0.1.tar.xz 36.1 gnome-internet-radio-locator.c /* $Id$ * * GNOME Internet Radio Locator * * Copyright (C) 2014-2019 Aamot Software * * Author: Ole Aamot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License , or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, 117 * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include "gnome-internet-radio-locator.h" #include "gnome-internet-radio-locator-gui.h" #include "gnome-internet-radio-locator-markers.h" #include "gnome-internet-radio-locator-player.h" #define N_COLS 2 #define COL_ID 0 #define COL_NAME 1 static ChamplainPathLayer *path_layer; static ChamplainPathLayer *path; static gboolean destroying = FALSE; static ChamplainView *champlain_view; GApplication *app; GtkWidget *search_selector; GtkWidget *window; GtkWidget *statusbar; GNOMEInternetRadioLocatorData *gnome_internet_radio_locator; GtkWidget *input; GtkEntryCompletion *completion; 118 GList *gnome_internet_radio_locator_archivers; GList *gnome_internet_radio_locator_listeners; GList *gnome_internet_radio_locator_programs; GList *gnome_internet_radio_locator_stations; GList *gnome_internet_radio_locator_streams; GtkWidget *archivers_selector = NULL; GtkWidget *listeners_selector = NULL; GtkWidget *programs_selector = NULL; GtkWidget *stations_selector = NULL; GtkWidget *streams_selector = NULL; GtkWidget *search_selector = NULL; gchar *list_item_data_key ="list_item_data"; GtkWidget *gnome_internet_radio_locator_app; GstPlayer *player; ChamplainMarkerLayer *layer; ClutterActor *marker; gchar *world_station_xml_filename, *local_station_xml_file; extern GNOMEInternetRadioLocatorStationInfo *stationinfo, * localstation; extern struct GNOMEInternetRadioLocatorMedia *media; GStatBuf stats; ChamplainView *view; gchar * str_channels (GNOMEInternetRadioLocatorChannels type) { gchar *channels; if (type == GNOME_INTERNET_RADIO_LOCATOR_CHANNELS_MONO) { channels = g_strdup("Mono"); } if (type == GNOME_INTERNET_RADIO_LOCATOR_CHANNELS_STEREO) { channels = g_strdup("Stereo"); } if (type == GNOME_INTERNET_RADIO_LOCATOR_CHANNELS_5_1) { channels = g_strdup("Surround"); } 119 if (type == GNOME_INTERNET_RADIO_LOCATOR_CHANNELS_NONE) { channels = g_strdup("None"); } return channels; } /* * Terminate the main loop. */ static void on_destroy (GtkWidget *widget, gpointer data) { destroying = TRUE; gtk_main_quit (); } static void toggle_layer (GtkToggleButton *widget, ClutterActor *layer) { if (gtk_toggle_button_get_active (widget)) { champlain_path_layer_set_visible (path_layer, TRUE); champlain_path_layer_set_visible (path, TRUE); champlain_marker_layer_animate_in_all_markers ( CHAMPLAIN_MARKER_LAYER (layer)); } else { champlain_path_layer_set_visible (path_layer, FALSE); champlain_path_layer_set_visible (path, FALSE); champlain_marker_layer_animate_out_all_markers ( CHAMPLAIN_MARKER_LAYER (layer)); } } static gboolean mouse_click_cb (ClutterActor *actor, ClutterButtonEvent *event, ChamplainView *view) { GError **error; gdouble lat, lon; GeocodePlace *place_city, *place_country; 120 GeocodeLocation *location_city; GeocodeLocation *location_country; GeocodeReverse *reverse_city, *reverse_country; ClutterColor city_color = { 0x9a, 0x9b, 0x9c, 0x9d }; ClutterColor text_color = { 0xff, 0xff, 0xff, 0xff }; const char *name, *name_city, *name_country; /* GeocodeForward *fwd; */ /* GList *list; */ /* GError **err; */ lon = champlain_view_x_to_longitude (view, event->x); lat = champlain_view_y_to_latitude (view, event->y); /* champlain_view_center_on (CHAMPLAIN_VIEW (view), lat, lon ); */ location_city = geocode_location_new (lat, lon, GEOCODE_LOCATION_ACCURACY_CITY); location_country = geocode_location_new (lat, lon, GEOCODE_LOCATION_ACCURACY_COUNTRY); reverse_city = geocode_reverse_new_for_location ( location_city); reverse_country = geocode_reverse_new_for_location ( location_country); place_city = geocode_reverse_resolve (reverse_city, error); place_country = geocode_reverse_resolve (reverse_country, error); name_city = geocode_place_get_town (place_city); name_country = geocode_place_get_country (place_country); if (!g_strcmp0(name_country, "United␣States␣of␣America")) { name_country = geocode_place_get_state (place_country); } marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); name = g_strconcat(name_city, ",␣", name_country, NULL); champlain_label_set_text (CHAMPLAIN_LABEL (marker), (gchar *)name); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , lat, lon); if (g_strcmp0(name, NULL)) { champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER (marker)); 121 gtk_entry_set_text(GTK_ENTRY(input),(gchar *)name); g_signal_connect(CHAMPLAIN_LOCATION(marker), "button- press", G_CALLBACK(marker_function), NULL); } GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("Mouse␣click␣at:␣%f␣% f␣(%s)\n", lat, lon, name); return TRUE; } static void map_source_changed (GtkWidget *widget, ChamplainView *view) { gchar *id; ChamplainMapSource *source; GtkTreeIter iter; GtkTreeModel *model; if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (widget), &iter)) return; model = gtk_combo_box_get_model (GTK_COMBO_BOX (widget)); gtk_tree_model_get (model, &iter, COL_ID, &id, -1); ChamplainMapSourceFactory *factory = champlain_map_source_factory_dup_default (); source = champlain_map_source_factory_create_cached_source ( factory, id); g_object_set (G_OBJECT (view), "map-source", source, NULL); g_object_unref (factory); } static void zoom_changed (GtkSpinButton *spinbutton, ChamplainView *view) { gint zoom = gtk_spin_button_get_value_as_int (spinbutton); g_object_set (G_OBJECT (view), "zoom-level", zoom, NULL); } 122 static void volume_changed (GtkSpinButton *spinbutton) { gint volume = gtk_spin_button_get_value_as_int (spinbutton); g_object_set (G_OBJECT (player), "volume", volume, NULL); } static void map_zoom_changed (ChamplainView *view, GParamSpec *gobject, GtkSpinButton *spinbutton) { gint zoom; g_object_get (G_OBJECT (view), "zoom-level", &zoom, NULL); gtk_spin_button_set_value (spinbutton, zoom); } static void view_state_changed (ChamplainView *view, GParamSpec *gobject, GtkImage *image) { ChamplainState state; if (destroying) return; g_object_get (G_OBJECT (view), "state", &state, NULL); if (state == CHAMPLAIN_STATE_LOADING) { gtk_image_set_from_icon_name (image, "edit-find", GTK_ICON_SIZE_BUTTON); } else { gtk_image_clear (image); } } static void 123 zoom_in (GtkWidget *widget, ChamplainView *view) { champlain_view_zoom_in (view); } static void zoom_out (GtkWidget *widget, ChamplainView *view) { champlain_view_zoom_out (view); } static void toggle_wrap (GtkWidget *widget, ChamplainView *view) { gboolean wrap; wrap = champlain_view_get_horizontal_wrap (view); champlain_view_set_horizontal_wrap (view, !wrap); } static void build_combo_box (GtkComboBox *box) { ChamplainMapSourceFactory *factory; GSList *sources, *iter; GtkTreeStore *store; GtkTreeIter parent; GtkCellRenderer *cell; store = gtk_tree_store_new (N_COLS, G_TYPE_STRING, /* id */ G_TYPE_STRING, /* name */ -1); factory = champlain_map_source_factory_dup_default (); sources = champlain_map_source_factory_get_registered ( factory); iter = sources; while (iter != NULL) 124 { ChamplainMapSourceDesc *desc = CHAMPLAIN_MAP_SOURCE_DESC (iter->data); const gchar *id = champlain_map_source_desc_get_id (desc ); const gchar *name = champlain_map_source_desc_get_name ( desc); gtk_tree_store_append (store, &parent, NULL); gtk_tree_store_set (store, &parent, COL_ID, id, COL_NAME, name, -1); iter = g_slist_next (iter); } g_slist_free (sources); g_object_unref (factory); gtk_combo_box_set_model (box, GTK_TREE_MODEL (store)); cell = gtk_cell_renderer_text_new (); gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (box), cell, FALSE); gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (box), cell, "text", COL_NAME, NULL); } static void append_point (ChamplainPathLayer *layer, gdouble lon, gdouble lat) { ChamplainCoordinate *coord; coord = champlain_coordinate_new_full (lon, lat); champlain_path_layer_add_node (layer, CHAMPLAIN_LOCATION ( coord)); } static void add_clicked (GtkButton *button, ChamplainView *view) { 125 GtkWidget *window, *dialog, *vbox, *combo; GtkResponseType response; window = g_object_get_data (G_OBJECT (view), "window"); dialog = gtk_dialog_new_with_buttons ("Add␣secondary␣map␣ source", GTK_WINDOW (window), GTK_DIALOG_MODAL, "Add", GTK_RESPONSE_OK, "Cancel", GTK_RESPONSE_CANCEL, NULL); combo = gtk_combo_box_new (); build_combo_box (GTK_COMBO_BOX (combo)); gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0); vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog)); gtk_container_add (GTK_CONTAINER (vbox), combo); gtk_widget_show_all (dialog); response = gtk_dialog_run (GTK_DIALOG (dialog)); if (response == GTK_RESPONSE_OK) { GtkTreeModel *model; GtkTreeIter iter; ChamplainMapSource *source; ChamplainMapSourceFactory *factory; char *id; if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo ), &iter)) return; model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo)); gtk_tree_model_get (model, &iter, COL_ID, &id, -1); factory = champlain_map_source_factory_dup_default (); source = champlain_map_source_factory_create_memcached_source 126 (factory, id); champlain_view_add_overlay_source (view, source, 0.6 * 255); g_object_unref (factory); g_free (id); } gtk_widget_destroy (dialog); } static void new_station(GSimpleAction *simple, GVariant *parameter, gpointer user_data) { g_print(_("New␣Internet␣Radio␣Station\n")); return; } static void search_station(GSimpleAction *simple, GVariant *parameter, gpointer user_data) { g_print(_("Search␣Internet␣Radio␣Station\n")); return; } static void listen_station(GSimpleAction *simple, GVariant *parameter, gpointer user_data) { gnome_internet_radio_locator_player_stop(player); player = gst_player_new (NULL, gst_player_g_main_context_signal_dispatcher_new(NULL)); /* g_object_set_data(G_OBJECT(widget), "station_uri", g_value_get_string(&value)); */ if (!g_strcmp0(gnome_internet_radio_locator-> selected_station_uri, NULL)) { gnome_internet_radio_locator_player_new(player, _("http ://fm939.wnyc.org/wnycfm")); } else { gnome_internet_radio_locator_player_new(player, gnome_internet_radio_locator->selected_station_uri); } gst_player_play(player); return; } 127 static void stop_station(GSimpleAction *simple, GVariant *parameter, gpointer user_data) { guint context_id; gnome_internet_radio_locator_player_stop(player); context_id = gtk_statusbar_get_context_id (GTK_STATUSBAR ( statusbar), "Station␣Name"); gtk_statusbar_pop (GTK_STATUSBAR (statusbar), GPOINTER_TO_INT (context_id)); gtk_statusbar_push (GTK_STATUSBAR (statusbar), GPOINTER_TO_INT (context_id), _("Search␣by␣city␣or␣drag/ click␣on␣the␣zoomable␣map␣to␣listen␣to␣a␣radio␣broadcast" )); return; } static void pause_station(GSimpleAction *simple, GVariant *parameter, gpointer user_data) { /* FIXME: Removing Pause. Can’t quit after gst_player_pause is called. */ #if 0 gnome_internet_radio_locator_player_pause(player); #endif return; } static void prev_station(GSimpleAction *simple, GVariant *parameter, gpointer user_data) { g_print(_("Previous␣Internet␣Radio␣Station\n")); return; } static void stations_all(GSimpleAction *simple, GVariant *parameter, gpointer user_data) { return; } static void next_station(GSimpleAction *simple, GVariant *parameter, gpointer user_data) { 128 return; } static void about_station_cb(GSimpleAction *simple, GVariant *parameter, gpointer user_data) { return; } static void about_program_cb(GSimpleAction *simple, GVariant *parameter, gpointer user_data) { return; } static void quit_program(GSimpleAction *simple, GVariant *parameter, gpointer user_data) { /* gnome_internet_radio_locator_player_stop(player); */ /* g_application_quit(app); */ gst_player_stop(player); g_object_unref (player); gst_deinit(); gtk_main_quit (); return; } void on_new_station_changed(GtkWidget * a, gpointer user_data) { GNOMEInternetRadioLocatorStationInfo *stationinfo = NULL; /* GList *l = g_list_first( gnome_internet_radio_locator_stations); */ /* stationinfo = l->data; */ gnome_internet_radio_locator->selected_station_band = g_strdup(g_object_get_data(G_OBJECT(a), "station_band")) ; GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" on_new_station_changed:␣%s\n", gnome_internet_radio_locator->selected_station_band); gnome_internet_radio_locator->selected_station_description = g_strdup(g_object_get_data(G_OBJECT(a), " station_description")); 129 GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" on_new_station_changed:␣%s\n", gnome_internet_radio_locator-> selected_station_description); gnome_internet_radio_locator->selected_station_location = g_strdup(g_object_get_data(G_OBJECT(a), " station_location")); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" on_new_station_changed:␣%s\n", gnome_internet_radio_locator->selected_station_location) ; gnome_internet_radio_locator->selected_station_name = g_strdup(g_object_get_data(G_OBJECT(a), "station_name")) ; GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" on_new_station_changed:␣%s\n", gnome_internet_radio_locator->selected_station_name); gnome_internet_radio_locator->selected_station_uri = g_strdup(g_object_get_data(G_OBJECT(a), "station_uri")); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" on_new_station_changed:␣%s\n", gnome_internet_radio_locator->selected_station_uri); gnome_internet_radio_locator->selected_station_website = g_strdup(g_object_get_data(G_OBJECT(a), "station_website ")); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" on_new_station_changed:␣%s\n", gnome_internet_radio_locator-> selected_station_website); /* appbar_send_msg(_("Selected the radio station %s in %s: % s"), */ /* gnome_internet_radio_locator->selected_station_name, */ /* gnome_internet_radio_locator-> selected_station_location, */ /* selected_station_uri, */ /* gnome_internet_radio_locator->selected_station_band) ; */ gnome_internet_radio_locator_station_update(stationinfo, gnome_internet_radio_locator-> selected_station_band, gnome_internet_radio_locator-> selected_station_description, 130 gnome_internet_radio_locator-> selected_station_name, gnome_internet_radio_locator-> selected_station_location, gnome_internet_radio_locator-> selected_station_uri, gnome_internet_radio_locator-> selected_station_website); } void on_stations_selector_changed(GtkWidget * a, gpointer user_data) { GNOMEInternetRadioLocatorStationInfo *station = NULL; /* if (gnome_internet_radio_locator->selected_station_uri != NULL) */ /* g_free(gnome_internet_radio_locator-> selected_station_uri); */ gnome_internet_radio_locator->selected_station_uri = g_strdup(g_object_get_data(G_OBJECT(a), "station_uri")); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" on_station_select_changed:␣%s\n", gnome_internet_radio_locator->selected_station_uri); gnome_internet_radio_locator->selected_station_name = g_strdup(g_object_get_data(G_OBJECT(a), "station_name")) ; GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" on_station_select_changed:␣%s\n", gnome_internet_radio_locator->selected_station_name); gnome_internet_radio_locator->selected_station_location = g_strdup(g_object_get_data(G_OBJECT(a), " station_location")); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" on_station_select_changed:␣%s\n", gnome_internet_radio_locator->selected_station_location) ; gnome_internet_radio_locator->selected_station_band = 131 g_strdup(g_object_get_data(G_OBJECT(a), "station_band")) ; GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" on_station_select_changed:␣%s\n", gnome_internet_radio_locator->selected_station_band); gnome_internet_radio_locator->selected_station_description = g_strdup(g_object_get_data(G_OBJECT(a), " station_description")); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" on_station_select_changed:␣%s\n", gnome_internet_radio_locator-> selected_station_description); /* appbar_send_msg(_("Selected the radio station %s in %s: % s"), */ /* gnome_internet_radio_locator->selected_station_name, */ /* gnome_internet_radio_locator-> selected_station_location, */ /* selected_station_uri, */ /* gnome_internet_radio_locator->selected_station_band) ; */ gnome_internet_radio_locator->selected_station_name = g_strdup(g_object_get_data(G_OBJECT(a), "station_name")); /* gnome_internet_radio_locator_history = g_list_add(GLIST( gnome_internet_radio_locator_history), ( GNOMEInternetRadioLocatorStationInfo *)station); */ /* gnome_internet_radio_locator_helper_main( selected_station_uri); */ } static void gnome_internet_radio_locator_window_cb (GtkApplication *app, gpointer user_data) { GtkWidget *widget, *grid, *toolbar, *new, *search, *listen, *stop, *prev, *stations, *next, *station, *program, *quit ; window = gtk_application_window_new (app); widget = gtk_champlain_embed_new(); toolbar = gtk_toolbar_new(); 132 input = gtk_entry_new(); #if 0 search = gtk_tool_button_new(gtk_image_new_from_icon_name( NULL, GTK_ICON_SIZE_BUTTON), _("Search")); gtk_tool_item_set_is_important(GTK_TOOL_ITEM(search), TRUE); gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM( search), 1); gtk_widget_show (GTK_WIDGET(search)); gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM(search), _(" Search␣Internet␣Radio␣Station")); g_signal_connect(search, "clicked", G_CALLBACK ( search_station), GTK_WINDOW (window)); #endif #if 0 prev = gtk_tool_button_new(gtk_image_new_from_icon_name(NULL , GTK_ICON_SIZE_BUTTON), _("Prev")); gtk_tool_item_set_is_important(GTK_TOOL_ITEM(prev), TRUE); gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM( prev), 5); gtk_widget_show (GTK_WIDGET(prev)); gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM(prev), _("Prev ␣Internet␣Radio␣Station")); g_signal_connect(prev, "clicked", G_CALLBACK (prev_station), GTK_WINDOW (window)); stations = gtk_tool_button_new(gtk_image_new_from_icon_name( NULL, GTK_ICON_SIZE_BUTTON), _("Stations")); gtk_tool_item_set_is_important(GTK_TOOL_ITEM(stations), TRUE ); gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM( stations), 6); gtk_widget_show (GTK_WIDGET(stations)); gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM(stations), _(" Stations")); g_signal_connect(stations, "clicked", G_CALLBACK ( stations_all), GTK_WINDOW (window)); next = gtk_tool_button_new(gtk_image_new_from_icon_name(NULL , GTK_ICON_SIZE_BUTTON), _("Next")); gtk_tool_item_set_is_important(GTK_TOOL_ITEM(next), TRUE); gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM( next), 7); 133 gtk_widget_show (GTK_WIDGET(next)); gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM(next), _("Next ␣Internet␣Radio␣Station")); g_signal_connect(next, "clicked", G_CALLBACK (next_station), GTK_WINDOW (window)); station = gtk_tool_button_new(gtk_image_new_from_icon_name( NULL, GTK_ICON_SIZE_BUTTON), _("About␣Station")); gtk_tool_item_set_is_important(GTK_TOOL_ITEM(station), TRUE) ; gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM( station), 8); gtk_widget_show (GTK_WIDGET(station)); gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM(station), _(" About␣Station")); g_signal_connect(station, "clicked", G_CALLBACK ( about_station_cb), GTK_WINDOW (window)); program = gtk_tool_button_new(gtk_image_new_from_icon_name( NULL, GTK_ICON_SIZE_BUTTON), _("About␣Program")); gtk_tool_item_set_is_important(GTK_TOOL_ITEM(program), TRUE) ; gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM( program), 9); gtk_widget_show (GTK_WIDGET(program)); gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM(program), _(" About␣Program")); g_signal_connect(program, "clicked", G_CALLBACK ( about_program_cb), GTK_WINDOW (window)); #endif #if 0 grid = gtk_grid_new(); gtk_grid_attach (GTK_GRID(grid), GTK_WIDGET(toolbar), 0, 0, 1, 1); gtk_grid_attach (GTK_GRID(grid), GTK_WIDGET(widget), 0, 1, 1, 1); champlain_view = gtk_champlain_embed_get_view ( GTK_CHAMPLAIN_EMBED(widget)); gtk_widget_set_size_request(GTK_WIDGET(widget), 740, 580); gtk_container_add (GTK_CONTAINER(window), GTK_WIDGET(grid)); g_signal_connect (window, "destroy", G_CALLBACK( gtk_main_quit), NULL); #endif 134 gtk_window_set_title (GTK_WINDOW(window), _("GNOME␣Internet␣ Radio␣Locator")); gtk_window_set_default_size (GTK_WINDOW(window), 740, 580); gtk_window_maximize (GTK_WINDOW (window)); gnome_internet_radio_locator_app = create_gnome_internet_radio_locator_app(); gtk_widget_show(gnome_internet_radio_locator_app); /* stations_selector = create_stations_selector( selected_station_uri, "gnome_internet_radio_locator.xml") ; */ /* g_object_add_weak_pointer(G_OBJECT(stations_selector), */ /* (void **) &(stations_selector)); */ gtk_widget_show_all (window); } void on_new_station_clicked(GtkWidget *a, gpointer user_data) { GtkWidget *station; GNOMEInternetRadioLocatorStationInfo *stationinfo = NULL; /* GList *l = g_list_first( gnome_internet_radio_locator_stations); */ gchar *selected_station_uri, *selected_station_band, * selected_station_description, *selected_station_name, * selected_station_location, *selected_station_website; /* stationinfo = l->data; */ gint result; // appbar_send_msg(_("New radio station")); station = create_new_station_selector(user_data); result = gtk_dialog_run (GTK_DIALOG(station)); switch (result) { case GTK_RESPONSE_ACCEPT: GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("Squeak!\n\n"); selected_station_band = g_strdup(g_object_get_data( G_OBJECT(station), "station_band")); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" on_new_station_select_changed:␣%s\n", selected_station_band); selected_station_description = g_strdup( g_object_get_data(G_OBJECT(station), " 135 station_description")); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" on_new_station_select_changed:␣%s\n", selected_station_description); selected_station_location = g_strdup(g_object_get_data( G_OBJECT(station), "station_location")); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" on_new_station_select_changed:␣%s\n", selected_station_location); selected_station_name = g_strdup(g_object_get_data( G_OBJECT(station), "station_name")); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" on_new_station_select_changed:␣%s\n", selected_station_name); selected_station_uri = g_strdup(g_object_get_data( G_OBJECT(station), "station_uri")); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" on_new_station_select_changed:␣%s\n", selected_station_uri); selected_station_website = g_strdup(g_object_get_data( G_OBJECT(station), "station_website")); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" on_new_station_select_changed:␣%s\n", selected_station_website); gnome_internet_radio_locator_station_update (stationinfo , selected_station_band, selected_station_description , selected_station_name, selected_station_location, selected_station_uri, selected_station_website); break; default: g_print (_("Nothing\n\n")); break; } gtk_widget_destroy(station); /* gtk_widget_show(station); */ } #if 0 static gboolean on_location_matches(GtkEntryCompletion *widget, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data) { 136 GValue value = {0, }; gtk_tree_model_get_value(model, iter, STATION_LOCATION, & value); gnome_internet_radio_locator->selected_station_location = g_strdup(g_value_get_string(&value)); g_value_unset(&value); /* appbar_send_msg(_("Found location %s"), */ /* gnome_internet_radio_locator-> selected_station_location); */ /* gnome_internet_radio_locator_helper_run( selected_station_uri, */ /* gnome_internet_radio_locator->selected_station_name, */ /* GNOME_INTERNET_RADIO_LOCATOR_STREAM_SHOUTCAST, */ /* GNOME_INTERNET_RADIO_LOCATOR_STREAM_PLAYER); */ return FALSE; } #endif gboolean on_search_matches(GtkEntryCompletion *widget, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data) { /* GeocodeNominatim *geocode_nominatim; */ GeocodePlace *place; GeocodeLocation *geocode_location; GeocodePlace *place_city, *place_country; GeocodeLocation *location_city; GeocodeLocation *location_country; GeocodeReverse *reverse_city, *reverse_country; glong lat, lon; GValue city = {0, }; GValue value = {0, }; GValue station_name = {0, }; gchar *location; gchar *town; gchar *country; gchar *state; GError **err; 137 guint context_id; gtk_tree_model_get_value(model, iter, STATION_LOCATION, & city); gtk_tree_model_get_value(model, iter, STATION_URI, &value); gtk_tree_model_get_value(model, iter, STATION_NAME, & station_name); /* g_print ("on_search_matches: %s\n", (gchar *) g_value_get_string(&city)); */ /* location = (gchar *)g_value_get_string(&city); */ /* town = strtok(location, ", "); */ /* country = strtok(NULL, " "); */ /* /\* Handle U.S. states */ /* geocode_place_set_country (place, "United States of America "); */ /* country = geocode_place_get_state (country); */ /* *\/ */ /* place = geocode_place_new((gchar *)g_value_get_string(& station_name), GEOCODE_PLACE_TYPE_MISCELLANEOUS); */ /* g_print ("geocode_place_new:town: %s\n", geocode_place_get_town(place)); */ /* g_print ("geocode_place_new:country: %s\n", geocode_place_get_country(place)); */ /* geocode_place_set_town (place, town); */ /* geocode_place_set_country(place, country); */ /* geocode_nominatim = geocode_nominatim_new ("https:// nominatim.gnome.org/", "ole@gnome.org"); */ /* g_print ("geocode_place_get_town: %s\n", geocode_place_get_town(place)); */ /* g_print ("geocode_place_get_country: %s\n", geocode_place_get_country(place)); */ /* /\* g_print ("%s\n", geocode_nominatim_get_city( geocode_nominatim)); *\/ */ /* reverse_city = geocode_reverse_new_for_location( geocode_location); */ /* place = geocode_reverse_resolve(reverse_city, err); */ /* geocode_location = geocode_place_get_location(place); */ 138 /* g_print ("%f7.3\n", geocode_location_get_latitude( geocode_location)); */ /* lat = geocode_location_get_latitude(geocode_location); */ /* lon = geocode_location_get_longitude(geocode_location); */ /* g_print ("lat: %ld\n", lat); */ /* g_print ("lon: %ld\n", lon); */ /* location_city = geocode_location_new (lat, lon, GEOCODE_LOCATION_ACCURACY_CITY); location_country = geocode_location_new (lat, lon, GEOCODE_LOCATION_ACCURACY_COUNTRY); reverse_city = geocode_reverse_new_for_location ( location_city); reverse_country = geocode_reverse_new_for_location ( location_country); place_city = geocode_reverse_resolve (reverse_city, error); place_country = geocode_reverse_resolve (reverse_country, error); name_city = geocode_place_get_town (place_city); name_country = geocode_place_get_country (place_country); */ /* champlain_view_center_on (CHAMPLAIN_VIEW (view),lat,lon); */ gnome_internet_radio_locator_player_stop(player); player = gst_player_new (NULL, gst_player_g_main_context_signal_dispatcher_new(NULL)); /* g_object_set_data(G_OBJECT(widget), "station_uri", g_value_get_string(&value)); */ gnome_internet_radio_locator_player_new(player, g_value_get_string(&value)); stationinfo = gnome_internet_radio_locator_station_load_from_file( localstation, world_station_xml_filename); while (stationinfo != NULL) { if (strcasecmp(stationinfo->stream->uri, g_value_get_string(&value))==0) { gchar *statusmsg = g_strconcat(stationinfo->name, "␣ (", stationinfo->uri, ")␣in␣", stationinfo-> location, "␣(", stationinfo->band, ",␣", g_strdup_printf("%li", stationinfo->stream-> samplerate), "␣Hz,␣", g_strdup_printf("%li", stationinfo->stream->bitrate), "␣kbps)", NULL); 139 context_id = gtk_statusbar_get_context_id ( GTK_STATUSBAR (statusbar), "Station␣Name"); gtk_statusbar_pop (GTK_STATUSBAR (statusbar), GPOINTER_TO_INT (context_id)); gtk_statusbar_push (GTK_STATUSBAR (statusbar), GPOINTER_TO_INT (context_id), statusmsg); } stationinfo = stationinfo->next; } gst_player_play(player); return FALSE; } int main (int argc, char **argv) { GtkWidget *window; GtkWidget *widget, *vbox, *bbox, *button, *viewport, *image; ClutterActor *scale; ChamplainLicense *license_actor; GtkListStore *model; GtkTreeIter iter; GNOMEInternetRadioLocatorStationInfo *stationinfo, * localstation; guint context_id; bindtextdomain (GETTEXT_PACKAGE, GNOME_INTERNET_RADIO_LOCATOR_LOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); if (gtk_clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) return 1; window = gtk_window_new (GTK_WINDOW_TOPLEVEL); /* give the window a 10px wide border */ gtk_container_set_border_width (GTK_CONTAINER (window), 10); /* give it the title */ gtk_window_set_title (GTK_WINDOW (window), _("GNOME␣Internet ␣Radio␣Locator")); /* Connect the destroy event of the window with our on_destroy function * When the window is about to be destroyed we get a notificaiton and * stop the main GTK loop */ 140 g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK ( on_destroy), NULL); vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10); widget = gtk_champlain_embed_new (); view = gtk_champlain_embed_get_view (GTK_CHAMPLAIN_EMBED ( widget)); clutter_actor_set_reactive (CLUTTER_ACTOR (view), TRUE); g_signal_connect (view, "button-release-event", G_CALLBACK ( mouse_click_cb), view); g_object_set (G_OBJECT (view), "kinetic-mode", TRUE, "zoom-level", 2, NULL); g_object_set_data (G_OBJECT (view), "window", window); scale = champlain_scale_new (); champlain_scale_connect_view (CHAMPLAIN_SCALE (scale), view) ; /* champlain_view_ensure_visible(G_OBJECT (view), NULL, TRUE ); */ /* champlain_view_set_keep_center_on_resize(G_OBJECT (view), TRUE); */ /* align to the bottom left */ clutter_actor_set_x_expand (scale, TRUE); clutter_actor_set_y_expand (scale, TRUE); clutter_actor_set_x_align (scale, CLUTTER_ACTOR_ALIGN_START) ; clutter_actor_set_y_align (scale, CLUTTER_ACTOR_ALIGN_END); clutter_actor_add_child (CLUTTER_ACTOR (view), scale); license_actor = champlain_view_get_license_actor (view); champlain_license_set_extra_text (license_actor, "Free␣ Internet␣Radio"); champlain_view_center_on (CHAMPLAIN_VIEW (view), 42.3617430, -71.0839082); layer = create_marker_layer (view, &path); champlain_view_add_layer (view, CHAMPLAIN_LAYER (path)); champlain_view_add_layer (view, CHAMPLAIN_LAYER (layer)); 141 path_layer = champlain_path_layer_new (); /* Cheap approx of Highway 10 */ append_point (path_layer, 45.4095, -73.3197); append_point (path_layer, 45.4104, -73.2846); append_point (path_layer, 45.4178, -73.2239); append_point (path_layer, 45.4176, -73.2181); append_point (path_layer, 45.4151, -73.2126); append_point (path_layer, 45.4016, -73.1926); append_point (path_layer, 45.3994, -73.1877); append_point (path_layer, 45.4000, -73.1815); append_point (path_layer, 45.4151, -73.1218); champlain_view_add_layer (view, CHAMPLAIN_LAYER (path_layer) ); gtk_widget_set_size_request (widget, 640, 520); bbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10); button = gtk_button_new(); image = gtk_image_new_from_icon_name("media-playback-start", GTK_ICON_SIZE_BUTTON); gtk_button_set_image (GTK_BUTTON (button), image); gtk_button_set_label (GTK_BUTTON (button), _("New")); g_signal_connect(button, "clicked", G_CALLBACK ( on_new_station_clicked), view); gtk_container_add (GTK_CONTAINER (bbox), button); memset(&stats, 0, sizeof(stats)); input = gtk_entry_new(); completion = gtk_entry_completion_new(); gtk_entry_completion_set_text_column(completion, STATION_NAME); gtk_entry_completion_set_text_column(completion, STATION_LOCATION); gtk_entry_set_completion(GTK_ENTRY(input), completion); g_signal_connect(G_OBJECT(completion), "match-selected", G_CALLBACK(on_search_matches), NULL); model = gtk_list_store_new(11, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, 142 G_TYPE_STRING); world_station_xml_filename = g_strconcat( GNOME_INTERNET_RADIO_LOCATOR_DATADIR, "/gnome-internet- radio-locator.xml", NULL); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" world_station_xml_filename␣=␣%s\n", world_station_xml_filename); if (world_station_xml_filename == NULL) { g_warning(("Failed␣to␣open␣%s.␣␣Please␣install␣it.\n"), world_station_xml_filename); } local_station_xml_file = g_strconcat(g_get_home_dir(), "/.gnome-internet-radio- locator/gnome-internet-radio-locator.xml", NULL); if (!g_stat(local_station_xml_file, &stats)) { localstation = gnome_internet_radio_locator_station_load_from_file( NULL, local_station_xml_file); } else { localstation = NULL; } if (localstation == NULL) { printf(_("Failed␣to␣open␣%s\n"), local_station_xml_file) ; } /* g_free (local_station_xml_file); */ stationinfo = gnome_internet_radio_locator_station_load_from_file( localstation, world_station_xml_filename); gnome_internet_radio_locator_stations = NULL; while (stationinfo != NULL) { gtk_list_store_append(model, &iter); gtk_list_store_set(model, &iter, STATION_NAME, 143 stationinfo->name, STATION_LOCATION, stationinfo->location, STATION_URI, stationinfo->stream->uri, STATION_DESCRIPTION, stationinfo->description, STATION_FREQUENCY, stationinfo->frequency, STATION_BAND, stationinfo->band, STATION_TYPE, stationinfo->type, STATION_RANK, stationinfo->rank, STATION_BITRATE, stationinfo->bitrate, STATION_SAMPLERATE, stationinfo->samplerate, STATION_ID, stationinfo->id, -1); stationinfo = stationinfo->next; } gtk_entry_completion_set_model(completion, GTK_TREE_MODEL( model)); gtk_widget_show(input); gtk_container_add (GTK_CONTAINER (bbox), input); #if 0 button = gtk_button_new(); image = gtk_image_new_from_icon_name("media-playback-start", GTK_ICON_SIZE_BUTTON); gtk_button_set_image (GTK_BUTTON (button), image); gtk_button_set_label (GTK_BUTTON (button), "Listen"); g_signal_connect(button, "clicked", G_CALLBACK ( listen_station), view); gtk_container_add (GTK_CONTAINER (bbox), button); #endif 144 button = gtk_button_new(); image = gtk_image_new_from_icon_name("media-playback-stop", GTK_ICON_SIZE_BUTTON); gtk_button_set_image (GTK_BUTTON (button), image); gtk_button_set_label (GTK_BUTTON (button), _("Stop")); g_signal_connect(button, "clicked", G_CALLBACK (stop_station ), view); gtk_container_add (GTK_CONTAINER (bbox), button); button = gtk_button_new (); image = gtk_image_new_from_icon_name ("zoom-in", GTK_ICON_SIZE_BUTTON); gtk_button_set_image (GTK_BUTTON (button), image); gtk_button_set_label (GTK_BUTTON (button), _("Zoom␣In")); g_signal_connect (button, "clicked", G_CALLBACK (zoom_in), view); gtk_container_add (GTK_CONTAINER (bbox), button); button = gtk_spin_button_new_with_range (0, 20, 1); gtk_spin_button_set_value (GTK_SPIN_BUTTON (button), champlain_view_get_zoom_level (view)); g_signal_connect (button, "changed", G_CALLBACK ( zoom_changed), view); g_signal_connect (view, "notify::zoom-level", G_CALLBACK ( map_zoom_changed), button); gtk_container_add (GTK_CONTAINER (bbox), button); button = gtk_button_new (); image = gtk_image_new_from_icon_name ("zoom-out", GTK_ICON_SIZE_BUTTON); gtk_button_set_image (GTK_BUTTON (button), image); gtk_button_set_label (GTK_BUTTON (button), _("Zoom␣Out")); g_signal_connect (button, "clicked", G_CALLBACK (zoom_out), view); gtk_container_add (GTK_CONTAINER (bbox), button); #if 0 button = gtk_toggle_button_new_with_label (_("Markers")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE); g_signal_connect (button, "toggled", G_CALLBACK ( toggle_layer), layer); gtk_container_add (GTK_CONTAINER (bbox), button); #endif /* button = gtk_combo_box_new (); */ 145 /* build_combo_box (GTK_COMBO_BOX (button)); */ /* gtk_combo_box_set_active (GTK_COMBO_BOX (button), 0); */ /* g_signal_connect (button, "changed", G_CALLBACK ( map_source_changed), view); */ /* gtk_container_add (GTK_CONTAINER (bbox), button); */ #if 0 button = gtk_button_new (); image = gtk_image_new_from_icon_name ("list-add", GTK_ICON_SIZE_BUTTON); gtk_button_set_image (GTK_BUTTON (button), image); g_signal_connect (button, "clicked", G_CALLBACK (add_clicked ), view); gtk_container_add (GTK_CONTAINER (bbox), button); #endif button = gtk_button_new(); image = gtk_image_new_from_icon_name("stop", GTK_ICON_SIZE_BUTTON); gtk_button_set_image (GTK_BUTTON (button), image); gtk_button_set_label (GTK_BUTTON (button), _("Exit")); g_signal_connect(button, "clicked", G_CALLBACK(quit_program) , view); gtk_container_add (GTK_CONTAINER (bbox), button); button = gtk_image_new (); gtk_widget_set_size_request (button, 22, -1); g_signal_connect (view, "notify::state", G_CALLBACK ( view_state_changed), button); gtk_box_pack_end (GTK_BOX (bbox), button, FALSE, FALSE, 0); viewport = gtk_frame_new (NULL); gtk_container_add (GTK_CONTAINER (viewport), widget); gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, FALSE, 0); statusbar = gtk_statusbar_new (); context_id = gtk_statusbar_get_context_id (GTK_STATUSBAR ( statusbar), "Station␣Name"); gtk_statusbar_pop (GTK_STATUSBAR (statusbar), GPOINTER_TO_INT (context_id)); gtk_statusbar_push (GTK_STATUSBAR (statusbar), GPOINTER_TO_INT (context_id), _("Search␣by␣city␣or␣drag/ click␣on␣the␣zoomable␣map␣to␣listen␣to␣a␣radio␣broadcast" )); 146 gtk_box_pack_end (GTK_BOX (vbox), statusbar, FALSE, FALSE, 0); gtk_widget_show (statusbar); gtk_container_add (GTK_CONTAINER (vbox), viewport); /* and insert it into the main window */ gtk_container_add (GTK_CONTAINER (window), vbox); /* make sure that everything, window and label, are visible */ gtk_widget_show_all (window); gst_init(&argc, &argv); /* start the main loop */ gtk_main (); return 0; #if 0 app = gtk_application_new ("org.gnome.gnome-internet-radio- locator", G_APPLICATION_FLAGS_NONE); g_signal_connect (app, "activate", G_CALLBACK ( gnome_internet_radio_locator_window_cb), NULL); status = g_application_run (G_APPLICATION (app), argc, argv) ; g_object_unref (app); return status; #endif } 36.2 gnome-internet-radio-locator-gui.c /* $Id$ 147 * * GNOME Internet Radio Locator * * Copyright (C) 2014-2019 Aamot Software * * Author: Ole Aamot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License , or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include "gnome-internet-radio-locator.h" #include "gnome-internet-radio-locator-gui.h" #include "gnome-internet-radio-locator-keys.h" 148 #include "gnome-internet-radio-locator-player.h" #include "gnome-internet-radio-locator-program.h" #include "gnome-internet-radio-locator-station.h" #include "gnome-internet-radio-locator-streams.h" #include "gnome-internet-radio-locator-tz.h" extern GtkWidget *gnome_internet_radio_locator_app; extern GtkWidget *search_selector; extern GtkWidget *input; extern GtkWidget *statusbar; extern GstPlayer *player; GNOMEInternetRadioLocatorStationInfo *stationinfo, *localstation ; GtkWidget *create_stations_selector(char *selected_station_uri, char *filename) { GtkWidget *stations_selector; GtkWidget *align, *menu, *drop_down, *item; gchar *station_uri, *station_name, *station_location, * station_band, *station_description, *station_website; gchar *label, *world_station_xml_filename, * local_station_xml_file; int i = 0, selection = -1; GStatBuf stats; memset(&stats, 0, sizeof(stats)); /* The Stations dialog */ /* stations_selector = gtk_dialog_new_with_buttons("Select a station", */ /* GTK_WINDOW( gnome_internet_radio_locator_app), */ /* 0, /\* flags *\/ */ /* NULL, */ /* GTK_RESPONSE_ACCEPT, */ /* NULL); */ /* gtk_container_set_border_width */ /* (GTK_CONTAINER(GTK_DIALOG(stations_selector)->vbox), 6); */ /* align = gtk_alignment_new(0.5, 0.5, 0, 0); */ /* gtk_container_add(GTK_CONTAINER */ /* (GTK_DIALOG(stations_selector)->vbox), align); */ 149 /* gtk_container_set_border_width(GTK_CONTAINER(align), 6); */ /* gtk_widget_show(align); */ menu = gtk_menu_new(); gtk_widget_show(menu); /* creating the menu items */ /* world_station_xml_filename = gnome_program_locate_file( NULL, */ /* GNOME_FILE_DOMAIN_APP_DATADIR , */ /* "gnome-internet-radio-locator /gnome-internet-radio-locator.xml", */ /* FALSE, */ /* NULL); */ /* world_station_xml_filename = g_strdup("https://people. gnome.org/~ole/gnome-internet-radio-locator/gnome- internet-radio-locator.xml"); */ world_station_xml_filename = g_strconcat( GNOME_INTERNET_RADIO_LOCATOR_DATADIR, "/gnome-internet- radio-locator.xml", NULL); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" world_station_xml_filename␣=␣%s\n", world_station_xml_filename); if (world_station_xml_filename == NULL) { g_warning(_("Failed␣to␣open␣%s\n"), world_station_xml_filename); } local_station_xml_file = g_strconcat(g_get_home_dir(), "/.gnome-internet-radio- locator/gnome-internet-radio-locator.xml", NULL); if (!g_stat(local_station_xml_file, &stats)) { localstation = gnome_internet_radio_locator_station_load_from_file( NULL, local_station_xml_file); } else { localstation = NULL; } if (localstation == NULL) { g_warning(_("Failed␣to␣open␣%s\n"), local_station_xml_file); } /* g_free (local_station_xml_file); */ 150 stationinfo = gnome_internet_radio_locator_station_load_from_file( localstation, world_station_xml_filename); gnome_internet_radio_locator_stations = NULL; while (stationinfo != NULL) { label = g_strconcat(stationinfo->name, "␣(", stationinfo->location, ")", NULL); station_uri = g_strdup(stationinfo->stream->uri); station_name = g_strdup(stationinfo->name); station_location = g_strdup(stationinfo->location); station_band = g_strdup(stationinfo->band); station_description = g_strdup(stationinfo->description) ; station_website = g_strdup(stationinfo->uri); gnome_internet_radio_locator_stations = g_list_append( gnome_internet_radio_locator_stations,( GNOMEInternetRadioLocatorStationInfo *)stationinfo); if (label != NULL) { item = gtk_menu_item_new_with_label(label); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK (on_stations_selector_changed), NULL); g_object_set_data(G_OBJECT(item), "station_uri", (gpointer) station_uri); g_object_set_data(G_OBJECT(item), "station_name", (gpointer) station_name); g_object_set_data(G_OBJECT(item), "station_location", (gpointer) station_location); g_object_set_data(G_OBJECT(item), "station_band", (gpointer) station_band); g_object_set_data(G_OBJECT(item), "station_description", (gpointer) station_description); g_object_set_data(G_OBJECT(item), "station_website", 151 (gpointer) station_website); gtk_widget_show(item); g_free(label); /* selection */ if (selected_station_uri != NULL && !strcmp(selected_station_uri, station_uri)) selection = i; } else { g_free(station_uri); g_free(station_name); g_free(station_location); g_free(station_band); g_free(station_description); } i++; stationinfo = stationinfo->next; } /* drop_down = gtk_combo_box_new(); */ /* gtk_widget_show(drop_down); */ /* gtk_combo_box_popdown(GTK_OPTION_MENU(drop_down), menu); */ /* gtk_container_add(GTK_CONTAINER(align), drop_down); */ if (selection != -1) gtk_combo_box_set_active(GTK_COMBO_BOX(drop_down), selection); g_signal_connect(G_OBJECT(stations_selector), "response", G_CALLBACK(gtk_widget_hide), (gpointer) stations_selector); g_signal_connect(G_OBJECT(stations_selector), "delete-event" , G_CALLBACK(gtk_widget_hide), (gpointer) stations_selector); return stations_selector; } static gboolean on_location_matches(GtkEntryCompletion *widget, GtkTreeModel *model, GtkTreeIter *iter, 152 gpointer user_data) { GValue value = {0, }; gtk_tree_model_get_value(model, iter, STATION_LOCATION, & value); gnome_internet_radio_locator->selected_station_location = g_strdup(g_value_get_string(&value)); g_value_unset(&value); /* appbar_send_msg(_("Found location %s"), */ /* gnome_internet_radio_locator-> selected_station_location); */ /* gnome_internet_radio_locator_helper_run( gnome_internet_radio_locator->selected_station_uri, */ /* gnome_internet_radio_locator->selected_station_name, */ /* GNOME_INTERNET_RADIO_LOCATOR_STREAM_SHOUTCAST, */ /* GNOME_INTERNET_RADIO_LOCATOR_STREAM_PLAYER); */ return FALSE; } void save_cb (GtkWidget *widget, gpointer data) { /* g_print("%s\n", data); */ gint context_id; char *nameentry, *locationentry, *urientry, * websiteentry, *descriptionentry, *statusmsg; nameentry = g_object_get_data(G_OBJECT(widget), " station_name"); locationentry = g_object_get_data(G_OBJECT(widget), " station_location"); urientry = g_object_get_data(G_OBJECT(widget), "station_uri" ); websiteentry = g_object_get_data(G_OBJECT(widget), " station_website"); descriptionentry = g_object_get_data(G_OBJECT(widget), " station_description"); player = gst_player_new (NULL, gst_player_g_main_context_signal_dispatcher_new(NULL)); gnome_internet_radio_locator_player_new(GST_PLAYER(player), urientry); 153 context_id = gtk_statusbar_get_context_id (GTK_STATUSBAR ( statusbar), "Station␣Name"); statusmsg = g_strconcat(_("Added␣"), nameentry, _("␣in␣"), locationentry, NULL); gtk_statusbar_push (GTK_STATUSBAR (statusbar), GPOINTER_TO_INT (context_id), statusmsg); gst_player_stop(player); gst_player_play(player); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("%s\n", nameentry); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("%s\n", locationentry ); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("%s\n", urientry); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("%s\n", websiteentry) ; GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("%s\n", descriptionentry); } GtkWidget *create_new_station_selector(gchar *location) { GtkWidget *station_selector, *content_area; GtkWidget *align; GtkWidget *bandentry, *descriptionentry, *nameentry, * locationentry, *urientry, *websiteentry; GtkEntryCompletion *completion; GtkListStore *location_model; GtkTreeIter iter; TzDB *db; GPtrArray *locs; guint i; char *pixmap_dir = NULL; gchar *path = NULL; GtkWidget *item = NULL; setlocale (LC_ALL, "C"); gchar *world_station_xml_filename, *local_station_xml_file; gint retval; /* int i = 0, search_selection = -1; */ GStatBuf stats; memset(&stats, 0, sizeof(stats)); 154 /* The Stations dialog */ station_selector = gtk_dialog_new_with_buttons(_("New␣ Internet␣Radio␣Station"), GTK_WINDOW( gnome_internet_radio_locator_app ), 0, (_("_Save")), GTK_RESPONSE_ACCEPT, NULL); content_area = gtk_dialog_get_content_area (GTK_DIALOG ( station_selector)); g_signal_connect(G_OBJECT(station_selector), "response", G_CALLBACK(save_cb), G_OBJECT(station_selector)); /* gtk_container_set_border_width */ /* (GTK_CONTAINER(GTK_DIALOG(station_selector)->vbox), 6); */ /* align = gtk_alignment_new(0.5, 0.5, 0, 0); */ /* gtk_container_add(GTK_CONTAINER */ /* (GTK_DIALOG(station_selector)->vbox), align); */ /* gtk_container_set_border_width(GTK_CONTAINER(align), 6); */ /* gtk_widget_show(align); */ bandentry = gtk_entry_new(); nameentry = gtk_entry_new(); locationentry = gtk_entry_new(); urientry = gtk_entry_new(); websiteentry = gtk_entry_new(); descriptionentry = gtk_entry_new(); gtk_entry_set_text(GTK_ENTRY(nameentry), _("Station␣name")); gtk_entry_set_text(GTK_ENTRY(bandentry), _("Bandwidth")); if (!g_strcmp0(gtk_entry_get_text(GTK_ENTRY(input)),"")) { gtk_entry_set_text(GTK_ENTRY(locationentry), _("City␣ name")); } else { gtk_entry_set_text(GTK_ENTRY(locationentry), (gpointer) gtk_entry_get_text(GTK_ENTRY(input))); } gtk_entry_set_text(GTK_ENTRY(urientry), _("http://uri-to- stream/")); 155 gtk_entry_set_text(GTK_ENTRY(descriptionentry), _(" Description")); gtk_entry_set_text(GTK_ENTRY(websiteentry), _("http://uri-to -website/")); completion = gtk_entry_completion_new(); gtk_entry_completion_set_text_column(completion, STATION_LOCATION); gtk_entry_set_completion(GTK_ENTRY(locationentry), completion); g_signal_connect(G_OBJECT(completion), "match-selected", G_CALLBACK(on_location_matches), NULL); location_model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING); world_station_xml_filename = g_strconcat( GNOME_INTERNET_RADIO_LOCATOR_DATADIR, "/gnome-internet- radio-locator.xml", NULL); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" world_station_xml_filename␣=␣%s\n", world_station_xml_filename); if (world_station_xml_filename == NULL) { g_warning((_("Failed␣to␣open␣%s.␣␣Please␣install␣it.\n") ), world_station_xml_filename); } local_station_xml_file = g_strconcat(g_get_home_dir(), "/. gnome_internet_radio_locator/ gnome_internet_radio_locator.xml", NULL); if (!g_stat(local_station_xml_file, &stats)) { localstation = gnome_internet_radio_locator_station_load_from_file( NULL, local_station_xml_file); } else { localstation = NULL; } if (localstation == NULL) { g_warning(_("Failed␣to␣open␣%s\n"), local_station_xml_file); } stationinfo = gnome_internet_radio_locator_station_load_from_file( localstation, world_station_xml_filename ); 156 gtk_container_add(GTK_CONTAINER(content_area), nameentry); gtk_container_add(GTK_CONTAINER(content_area), bandentry); gtk_container_add(GTK_CONTAINER(content_area), locationentry ); gtk_container_add(GTK_CONTAINER(content_area), urientry); gtk_container_add(GTK_CONTAINER(content_area), descriptionentry); gtk_container_add(GTK_CONTAINER(content_area), websiteentry) ; gtk_widget_show(nameentry); gtk_widget_show(bandentry); gtk_widget_show(locationentry); gtk_widget_show(urientry); gtk_widget_show(descriptionentry); gtk_widget_show(websiteentry); /* g_signal_connect(G_OBJECT(station_selector), GTK_RESPONSE_ACCEPT, */ /* G_CALLBACK(on_new_station_selector_changed), */ /* NULL); */ g_object_set_data(G_OBJECT(station_selector), "station_name" , (gchar *) gtk_entry_get_text(GTK_ENTRY(nameentry)) ); g_object_set_data(G_OBJECT(station_selector), "station_band" , (gchar *) gtk_entry_get_text(GTK_ENTRY(bandentry)) ); g_object_set_data(G_OBJECT(station_selector), " station_location", (gchar *) gtk_entry_get_text(GTK_ENTRY( locationentry))); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("LOCATIONENTRY:␣%s\n" , (gchar *) gtk_entry_get_text(GTK_ENTRY(locationentry))) ; g_object_set_data(G_OBJECT(station_selector), "station_uri", (gchar *) gtk_entry_get_text(GTK_ENTRY(urientry))) ; GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("URIENTRY:␣%s\n", ( gchar *) gtk_entry_get_text(GTK_ENTRY(urientry))); g_object_set_data(G_OBJECT(station_selector), " station_description", (gchar *) gtk_entry_get_text(GTK_ENTRY( descriptionentry))); 157 g_object_set_data(G_OBJECT(station_selector), " station_website", (gchar *) gtk_entry_get_text(GTK_ENTRY( websiteentry))); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("WEBSITEENTRY:␣%s\n", (gchar *) gtk_entry_get_text(GTK_ENTRY(websiteentry))); #if 0 /* FIXME: Add input fields */ g_object_set_data(G_OBJECT(station_selector), " station_description", (gchar *) station_description); g_object_set_data(G_OBJECT(station_selector), " station_website", (gchar *) station_website); #endif // gtk_widget_show(station_selector); // g_free(label); g_signal_connect(G_OBJECT(station_selector), "response", G_CALLBACK(gtk_widget_hide), (gpointer) station_selector); g_signal_connect(G_OBJECT(station_selector), "delete-event", G_CALLBACK(gtk_widget_hide), (gpointer) station_selector); /* tz_db_free (db); */ /* g_free (pixmap_dir); */ /* g_free (filename); */ /* g_free (path); */ return station_selector; } GtkWidget *create_gnome_internet_radio_locator_app(void) { GtkWidget *gnome_internet_radio_locator_app; GtkWidget *vbox1; GtkWidget *gnome_internet_radio_locator_pixmap; GtkWidget *appbar; GtkWidget *progress; gsize length; const gchar *selected_station, *selected_station_uri, * selected_station_name, *selected_station_location, * selected_station_description; GNOMEInternetRadioLocatorData * gnome_internet_radio_locator_data = g_new0( GNOMEInternetRadioLocatorData, 1); char *pmf; 158 gtk_window_set_title(GTK_WINDOW( gnome_internet_radio_locator_app), "GNOME␣Internet␣Radio␣ Locator"); gnome_internet_radio_locator = gnome_internet_radio_locator_data; gnome_internet_radio_locator_data->settings = g_settings_new (GNOME_INTERNET_RADIO_LOCATOR_UI); selected_station_uri = g_variant_get_string( g_settings_get_value (gnome_internet_radio_locator_data-> settings, "selected_station_uri"), &length); selected_station = g_variant_get_string(g_settings_get_value (gnome_internet_radio_locator_data->settings, "station"), &length); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG ("SELECTED␣STATION␣=␣ %s\n", selected_station); /* gnome_internet_radio_locator->selected_station_uri = selected_station_uri; */ selected_station_name = g_variant_get_string( g_settings_get_value (gnome_internet_radio_locator_data-> settings, "selected_station_name"), &length); /* gnome_internet_radio_locator->selected_station_name = selected_station_name; */ selected_station_location = g_variant_get_string( g_settings_get_value (gnome_internet_radio_locator_data-> settings, "selected_station_location"), &length); /* gnome_internet_radio_locator->selected_station_location = selected_station_location; */ selected_station_description = g_variant_get_string( g_settings_get_value (gnome_internet_radio_locator_data-> settings, "selected_station_description"), &length); /* gnome_internet_radio_locator-> selected_station_description = selected_station_description; */ #if GNOME_INTERNET_RADIO_LOCATOR_CFG_GNOME_CONFIG gnome_config_push_prefix("/gnome-internet-radio-locator/ General/"); gnome_internet_radio_locator->selected_listener_uri = gnome_config_get_string("selected_listener_uri="); gnome_internet_radio_locator->selected_listener_name = gnome_config_get_string("selected_listener_name="); gnome_internet_radio_locator->selected_listener_location = gnome_config_get_string("selected_listener_location="); gnome_internet_radio_locator->selected_listener_description = 159 gnome_config_get_string("selected_listener_description=" ); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" gnome_internet_radio_locator->selected_listener_uri:␣%s\n ", gnome_internet_radio_locator->selected_listener_uri); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" gnome_internet_radio_locator->selected_listener_name:␣%s\ n", gnome_internet_radio_locator->selected_listener_name) ; GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" gnome_internet_radio_locator->selected_listener_location: ␣%s\n", gnome_internet_radio_locator-> selected_listener_location); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" gnome_internet_radio_locator->selected_listener_band:␣%s\ n", gnome_internet_radio_locator->selected_listener_band) ; GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" gnome_internet_radio_locator-> selected_listener_description:␣%s\n", gnome_internet_radio_locator-> selected_listener_description); gnome_internet_radio_locator->selected_station_uri = gnome_config_get_string("selected_station_uri="); gnome_internet_radio_locator->selected_station_name = gnome_config_get_string("selected_station_name="); gnome_internet_radio_locator->selected_station_location = gnome_config_get_string("selected_station_location="); gnome_internet_radio_locator->selected_station_description = gnome_config_get_string("selected_station_description=") ; gnome_internet_radio_locator->selected_station_name = gnome_config_get_string("selected_station_name="); gnome_internet_radio_locator->selected_station_location = gnome_config_get_string("selected_station_location="); gnome_internet_radio_locator->selected_station_description = gnome_config_get_string("selected_station_description=") ; GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" gnome_internet_radio_locator->selected_station_uri:␣%s\n" 160 , gnome_internet_radio_locator->selected_station_uri); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" gnome_internet_radio_locator->selected_station_name:␣%s\n ", gnome_internet_radio_locator->selected_station_name); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" gnome_internet_radio_locator->selected_station_location:␣ %s\n", gnome_internet_radio_locator-> selected_station_location); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" gnome_internet_radio_locator-> selected_station_description:␣%s\n", gnome_internet_radio_locator-> selected_station_description); if (strcmp(gnome_internet_radio_locator-> selected_station_uri,"")==0) { gnome_internet_radio_locator->selected_station_uri = g_strdup(_("http://fm939.wnyc.org/wnycfm")); } if (strcmp(gnome_internet_radio_locator-> selected_station_name,"")==0) { gnome_internet_radio_locator->selected_station_name = g_strdup(_("WNYC")); } if (strcmp(gnome_internet_radio_locator-> selected_station_location,"")==0) { gnome_internet_radio_locator->selected_station_location = g_strdup(_("New␣York␣City,␣NY")); } if (strcmp(gnome_internet_radio_locator-> selected_station_band,"")==0) { gnome_internet_radio_locator->selected_station_band = g_strdup(_("Online")); } if (strcmp(gnome_internet_radio_locator-> selected_station_description,"")==0) { gnome_internet_radio_locator-> selected_station_description = g_strdup(_("WNYC␣93.9␣ FM␣and␣AM␣820␣are␣New␣York’s␣flagship␣public␣radio␣ stations,␣broadcasting␣the␣finest␣programs␣from␣NPR,␣ American␣Public␣Media,␣Public␣Radio␣International␣and ␣the␣BBC␣World␣Service,␣as␣well␣as␣a␣wide␣range␣of␣ 161 award-winning␣local␣programming.")); } gnome_internet_radio_locator->selected_streams_uri = gnome_config_get_string("selected_streams_uri="); gnome_internet_radio_locator->selected_streams_mime = gnome_config_get_string("selected_streams_mime="); gnome_internet_radio_locator->selected_streams_codec = gnome_config_get_string("selected_streams_codec="); gnome_internet_radio_locator->selected_streams_bitrate = gnome_config_get_string("selected_streams_bitrate="); gnome_internet_radio_locator->selected_streams_samplerate = gnome_config_get_string("selected_streams_samplerate="); gnome_internet_radio_locator->selected_streams_channels = (Gnome_Internet_Radio_LocatorChannels) gnome_config_get_string("selected_streams_channels=") ; GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" gnome_internet_radio_locator->selected_streams_uri:␣%s\n" , gnome_internet_radio_locator->selected_streams_uri); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" gnome_internet_radio_locator->selected_streams_mime:␣%s\n ", gnome_internet_radio_locator->selected_streams_mime); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" gnome_internet_radio_locator->selected_streams_codec:␣%s\ n", gnome_internet_radio_locator->selected_streams_codec) ; GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" gnome_internet_radio_locator->selected_streams_bitrate:␣% s\n", gnome_internet_radio_locator-> selected_streams_bitrate); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" gnome_internet_radio_locator->selected_streams_samplerate :␣%s\n", gnome_internet_radio_locator-> selected_streams_samplerate); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" gnome_internet_radio_locator->selected_channels:␣%0x\n", gnome_internet_radio_locator-> selected_streams_channels); gnome_config_pop_prefix(); 162 #endif return gnome_internet_radio_locator_app; } 36.3 gnome-internet-radio-locator-listener.c 36.4 gnome-internet-radio-locator-markers.c /* $id$ * * GNOME Internet Radio Locator * * Copyright (C) 2019 Aamot Software * * Author: Ole Aamot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License , or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * 163 * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /* * Copyright (C) 2008 Pierre-Luc Beaudoin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include "gnome-internet-radio-locator.h" #include "gnome-internet-radio-locator-markers.h" #include "gnome-internet-radio-locator-player.h" extern GtkWidget *statusbar; extern GtkWidget *input; extern GtkEntryCompletion *completion; 164 extern GNOMEInternetRadioLocatorStationInfo *stationinfo, * localstation; extern gchar *world_station_xml_filename; extern GstPlayer *player; extern ChamplainMarkerLayer *layer; extern GtkWidget *window; extern ChamplainView *view; typedef struct { ChamplainView *view; ChamplainMarker *marker; } LocationCallbackData; static gboolean location_callback (LocationCallbackData *data) { /* champlain_view_center_on (data->view, lat, lon); */ /* champlain_location_set_location (CHAMPLAIN_LOCATION (data ->marker), lat, lon); */ g_print("%s\n", __FUNCTION__); return TRUE; } void marker_function (ChamplainMarker *self, gdouble dx, gdouble dy, ClutterEvent *event, gpointer user_data) { gchar *station, *station_link; gchar *markup; guint context_id; station = (gchar *)champlain_label_get_text (CHAMPLAIN_LABEL (self)); station_link = strtok(station, "\n"); gtk_entry_set_text(GTK_ENTRY(input),(gchar *)station_link); gst_player_stop(player); player = gst_player_new (NULL, gst_player_g_main_context_signal_dispatcher_new(NULL)); stationinfo = gnome_internet_radio_locator_station_load_from_file( localstation, world_station_xml_filename); 165 while (stationinfo != NULL) { if (strcasecmp(stationinfo->location, station_link) ==0) { gchar *statusmsg = g_strconcat(stationinfo->name, "␣ (", stationinfo->uri, ")␣in␣", stationinfo-> location, "␣(", stationinfo->band, ",␣", g_strdup_printf("%li", stationinfo->stream-> samplerate), "␣Hz,␣", g_strdup_printf("%li", stationinfo->stream->bitrate), "␣kbps)", NULL); gnome_internet_radio_locator_player_new(GST_PLAYER( player), stationinfo->stream->uri); context_id = gtk_statusbar_get_context_id ( GTK_STATUSBAR (statusbar), "Station␣Name"); gtk_statusbar_pop (GTK_STATUSBAR (statusbar), GPOINTER_TO_INT (context_id)); gtk_statusbar_push (GTK_STATUSBAR (statusbar), GPOINTER_TO_INT (context_id), statusmsg); } stationinfo = stationinfo->next; } gst_player_play(player); if (user_data != NULL) { champlain_label_set_text (CHAMPLAIN_LABEL (self), user_data); } /* g_signal_connect(CHAMPLAIN_LOCATION(self), "button-press ", G_CALLBACK (on_new_station_clicked), user_data); */ return; } ChamplainMarkerLayer * create_marker_layer (G_GNUC_UNUSED ChamplainView *view, ChamplainPathLayer **path) { ClutterActor *marker; ClutterActor *layer_actor; ClutterColor city_color = { 0xf3, 0x94, 0x07, 0xbb }; ClutterColor city_a_color = { 0x83, 0xa6, 0x7f, 0xbb }; ClutterColor city_b_color = { 0xc1, 0x66, 0x5a, 0xbb }; ClutterColor city_c_color = { 0x88, 0x7f, 0xa3, 0xbb }; ClutterColor city_d_color = { 0x34, 0x65, 0xa4, 0xbb }; ClutterColor city_e_color = { 0x75, 0x90, 0xae, 0xbb }; ClutterColor city_f_color = { 0xe0, 0xc3, 0x93, 0xbb }; ClutterColor text_color = { 0xff, 0xff, 0xff, 0xff }; 166 LocationCallbackData callback_data; gchar *station = NULL; *path = champlain_path_layer_new (); layer = champlain_marker_layer_new_full ( CHAMPLAIN_SELECTION_SINGLE); layer_actor = CLUTTER_ACTOR (layer); /* Create callback that updates the map periodically */ /* callback_data.view = CHAMPLAIN_VIEW (view); */ /* callback_data.marker = CHAMPLAIN_MARKER (layer); */ /* g_timeout_add (1000, (GSourceFunc) location_callback, & callback_data); */ /* marker = champlain_point_new (); */ /* champlain_location_set_location (CHAMPLAIN_LOCATION ( marker), 37.873093, -122.303769); */ /* champlain_location_set_location (CHAMPLAIN_LOCATION ( marker), 37.873093, -122.303769); */ /* champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER (marker)); */ /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ #if 0 marker = champlain_label_new_with_text ("Norway\nOslo", "Helvetica␣14", NULL, NULL); champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_alignment (CHAMPLAIN_LABEL (marker), PANGO_ALIGN_RIGHT); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_a_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 37.873093, -122.303769); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION ( marker)); #endif marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Aalborg,␣Denmark\n ANR"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; 167 champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_b_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 57.0482206, 9.9193939); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Alta,␣Norway\nRadio ␣Alta"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_e_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 70.04962755, 23.0825349565332); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Ayr,␣Scotland\nUWS␣ Radio"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); 168 champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_b_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 55.4594119, -4.6326702); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Barcelona,␣Catalonia\nBarcelona␣City␣FM"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_b_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 41.3828939, 2.1774322); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Bergen,␣Norway\n SRIB"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_c_color); 169 champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 60.3943034, 5.3258117); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Berkeley,␣California\nKALX"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_d_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 37.873093, -122.303769); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Berlin,␣Germany\n Radio␣Eins"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_d_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); 170 champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 52.5170365, 13.3888599); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Bern,␣Switzerland\n Radio␣NRJ␣Bern"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_c_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 46.9482713, 7.4514512); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("WBUR,␣Boston,␣Massachusetts\nWBUR"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_e_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 42.3516603, -71.1226348); 171 champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("WTBU,␣Boston,␣Massachusetts\nWTBU"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_f_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 42.3602534, -71.0582912); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Bruxelles,␣Belgium\nRadio␣Campus"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_a_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 50.84404145, 4.36720169448285); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); 172 champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Buskerud,␣Norway\n NRK␣P1␣Buskerud"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_d_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 60.2497876, 8.96278676790604); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Calgary,␣Canada\n CJSW"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_b_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 51.0534234, -114.0625892); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); 173 /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("WHRB-FM,␣Cambridge,␣Massachusetts\nWHRB"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_c_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 42.3723191, -71.1186638); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("WMBR-FM,␣Cambridge,␣Massachusetts\nWMBR"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_d_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 42.3617430, -71.0839082); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ 174 g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Cambridge,␣United␣Kingdom\nCam␣FM"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_e_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 52.2033051, 0.124862); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Cape␣Town,␣South␣Africa\nUCT␣Radio"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_f_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , -33.928992, 18.417396); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); 175 marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Copenhagen,␣Denmark\nDanmarks␣Radio␣Nyheder"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_a_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 55.6867243, 12.5700724); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Chicago,␣Illinois\n WHPK"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_b_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 41.8755546, -87.6244212); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); 176 g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Dubai,␣Saudi␣Arabia\nMiddle␣East␣Broadcasting␣Center␣FM"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_c_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 21.4146056, 39.8227432); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Dublin,␣Ireland\n DCUfm"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_c_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 53.3497645, -6.2602732); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); 177 station = g_strdup("Finnmark,␣Norway\n NRK␣P1␣Finnmark"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_b_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 69.86993469999999, 21.827278548625912); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Guatemala␣City,␣Guatemala\nRadio␣Universidad"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_a_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 14.6417889, -90.5132239); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Honolulu,␣Hawaii\n Hawaii␣Public␣Radio"); 178 champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_e_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 21.304547, -157.8556764); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Hordaland,␣Norway\n NRK␣P1␣Hordaland"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_e_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 60.2570766, 6.06249778348651); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("K r johka,␣Norway\nNRK␣Spmi"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; 179 champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_f_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 68.7718259, 24.2803624); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Kingston,␣Canada\n CFRC"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_f_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 44.230687, -76.481323); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Kristiansand,␣Norway\nNRK␣Srlandet"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); 180 champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_a_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 58.14615, 7.9957333); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Houston,␣Texas\n Coog␣Radio,␣University␣of␣Houston"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_b_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 29.7589382, -95.3676974); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Innlandet,␣Norway\n NRK␣P1␣Innlandet"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_a_color); 181 champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 61.26810555, 10.485458802304304); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("London,␣United␣Kingdom\nImperial␣College␣Radio"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_c_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 51.5073219, -0.1276474); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Los␣Angeles,␣California\nKXSC"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_d_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); 182 champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 34.1430079, -118.14176172581); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Lyon,␣France\nRadio ␣Brume"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_e_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 45.7544734, 4.8122242); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Mxico␣City,␣Mxico\nRadio␣UNAM"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_f_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 19.647012, -101.22900565); 183 champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Moscow,␣Russia\n Echo␣of␣Moscow"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_a_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 55.4792046, 37.3273304); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("M re␣og␣Romsdal,␣Norway\nNRK␣P1␣M re␣og␣Romsdal"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_d_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 62.8452777, 7.51819407263736); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); 184 champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Newcastle,␣Australia\n2NURFM"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_b_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , -32.9272881, 151.7812534); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("New␣Orleans,␣Louisiana\nWWNO"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_c_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 29.9499323, -90.0701156); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); 185 /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("New␣York␣City,␣New␣York\nWKCR"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_d_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 40.7306458, -73.9866136); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Nordkapp,␣Norway\n Radio␣Nordkapp"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_d_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 71.1699506, 25.7858893); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ 186 g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Nordland,␣Norway\n NRK␣P1␣Nordland"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_b_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 67.27564050000001, 13.862360639913621); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Norway\nRadio␣ Norwegian"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_e_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 60.133054099999995, 7.531103018917516); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); 187 marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Ontario,␣Canada\n RadioWaterloo"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_d_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 43.466874, -80.524635); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Oslo,␣Norway\nNRK␣ Sport"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_e_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 59.9132694, 10.7391112); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); 188 station = g_strdup("Oxford,␣United␣Kingdom\nOxide␣Radio"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_f_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 51.7520131, -1.2578499); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Ottawa,␣Canada\n CHUO"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_a_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 45.421106, -75.690308); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Paris,␣France\n Radio␣Campus␣Paris"); 189 champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_b_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 48.8566101, 2.3514992); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Phoenix,␣Arizona\n KASC"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_c_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 33.4485866, -112.0773456); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Pisa,␣Italy\nRadio␣ Eco"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; 190 champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_d_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 43.7159395, 10.4018624); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Portland,␣Oregon\n KPSU"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_d_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 45.5202471,-122.6741949); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Rogaland,␣Norway\n NRK␣P1␣Rogaland"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); 191 champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_d_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 58.93631375, 5.80587864304024); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("San␣Francisco,␣California\nSomaFM"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_e_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 37.7792808, -122.4192363); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Seattle,␣Washington\nKSUB"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_f_color); 192 champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 47.6038321, -122.3300624); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Sogn␣og␣Fjordane,␣Norway\nNRK␣P1␣Sogn␣og␣Fjordane"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_b_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 61.53093745, 6.10242908066871); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Stanford,␣California\nKZSU"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_a_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); 193 champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 37.4248398, -122.1677058); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Stockholm,␣Sweden\n Sveriges␣Radio␣P1"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_b_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 59.3251172, 18.0710935); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Sydney,␣Canada\n Caper␣Radio"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_c_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 46.1654766, -60.1735637935906); 194 champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Tampere,␣Finland\n Radio␣Moreeni"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_d_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 61.4980214, 23.7603118); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Thessaloniki,␣Greece\n1431␣AM"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_d_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 40.6403167, 22.9352716); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); 195 champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Toronto,␣Canada\n CIUT"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_e_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 43.653963, -79.387207); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Trshavn,␣Faroe␣Islands\nMidlar"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_f_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 62.012, -6.768); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); 196 /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Troms,␣Norway\nNRK␣ P1␣Troms"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_a_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 64.5731537, 11.52803643954819); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Trondheim,␣Norway\n Radio␣Revolt"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_a_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 63.4305658, 10.3951929); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ 197 g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Trndelag,␣Norway\nNRK␣P1␣Trndelag"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_c_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 63.87759235, 10.195050547141093); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Warsaw,␣Poland\n Radio␣Aktywne"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_b_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 52.2319237, 21.0067265); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); 198 marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup("Washington,␣District␣of␣Columbia\nWAMU"); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_c_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 38.8949549, -77.0366456); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); station = g_strdup(" stfold ,␣Norway\n NRK␣P1␣ stfold "); champlain_label_set_text (CHAMPLAIN_LABEL (marker), station) ; champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_d_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 59.20313315, 10.9535037948529); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_marker_animate_in(CHAMPLAIN_MARKER (marker)); /* champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION (marker)); */ g_signal_connect(CHAMPLAIN_LOCATION(marker), "button-press", G_CALLBACK(marker_function), station); marker = champlain_label_new_from_file ("icons/emblem- generic.png", NULL); 199 #if 0 marker = champlain_label_new_from_file ("icons/emblem- important.png", NULL); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_e_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 37.873093, -122.303769); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION ( marker)); marker = champlain_point_new (); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_f_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 37.873093, -122.303769); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION ( marker)); marker = champlain_label_new_from_file ("icons/emblem- favorite.png", NULL); champlain_label_set_draw_background (CHAMPLAIN_LABEL (marker ), FALSE); champlain_label_set_color (CHAMPLAIN_LABEL (marker), & city_a_color); champlain_label_set_text_color (CHAMPLAIN_LABEL (marker), & text_color); champlain_location_set_location (CHAMPLAIN_LOCATION (marker) , 37.873093, -122.303769); champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( marker)); champlain_path_layer_add_node (*path, CHAMPLAIN_LOCATION ( marker)); #endif champlain_marker_layer_set_all_markers_draggable (layer); clutter_actor_show (layer_actor); return layer; } 200 36.5 gnome-internet-radio-locator-player.c /* GStreamer command line playback testing utility * * Copyright (C) 2013-2014 Tim-Philipp Mller * Copyright (C) 2013 Collabora Ltd. * Copyright (C) 2014 Sebastian Dr ge * Copyright (C) 2015 Brijesh Singh * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include 201 #include #include "gnome-internet-radio-locator.h" #include "gnome-internet-radio-locator-player.h" #include "gnome-internet-radio-locator-player-kb.h" #define VOLUME_STEPS 20 GST_DEBUG_CATEGORY (play_debug); #define GST_CAT_DEFAULT play_debug extern GstPlay *player; #if 0 static gboolean play_next (GstPlay * play); static gboolean play_prev (GstPlay * play); static void play_reset (GstPlay * play); static void play_set_relative_volume (GstPlay * play, gdouble volume_step); #endif void gnome_internet_radio_locator_player_main(gchar *streamuri, gchar *name) { gchar *uri = g_strdup(streamuri); /* if (argc > 1) { */ /* if (g_strrstr (argv[1],"rtsp://") || g_strrstr (argv [1],"http://") || g_strrstr (argv[1],"file://")) */ /* uri = g_strdup (argv[1]); */ /* else */ /* uri = g_strdup_printf ("file://%s", argv[1]); */ /* } */ /* else { */ /* g_message ("Specify the media file name..< gnome_internet_radio_locator-playerplayer filename>"); */ /* return 0; */ /* } */ gnome_internet_radio_locator->player_loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (gnome_internet_radio_locator->player_loop); gst_deinit(); 202 gnome_internet_radio_locator->player_status = GNOME_INTERNET_RADIO_LOCATOR_PLAYER_TRUE; exit (0); } #if 0 static void end_of_stream_cb (GstPlayer * player, GstPlay * play) { g_print ("\n"); /* and switch to next item in list */ if (!play_next (play)) { g_print ("Reached␣end␣of␣play␣list.\n"); g_main_loop_quit (play->loop); } } #endif #if 0 static void error_cb (GstPlayer * player, GError * err, GstPlay * play) { g_printerr ("ERROR␣%s␣for␣%s\n", err->message, play->uris[ play->cur_idx]); /* if looping is enabled, then disable it else will keep looping forever */ play->repeat = FALSE; /* try next item in list then */ if (!play_next (play)) { g_print ("Reached␣end␣of␣play␣list.\n"); g_main_loop_quit (play->loop); } } #endif static void position_updated_cb (GstPlayer * player, GstClockTime pos, GstPlay * play) { GstClockTime dur = -1; gchar status[64] = { 0, }; g_object_get (play->player, "duration", &dur, NULL); memset (status, ’␣’, sizeof (status) - 1); if (pos != -1 && dur > 0 && dur != -1) { gchar dstr[32], pstr[32]; /* FIXME: pretty print in nicer format */ 203 g_snprintf (pstr, 32, "%" GST_TIME_FORMAT, GST_TIME_ARGS (pos)); pstr[9] = ’\0’; g_snprintf (dstr, 32, "%" GST_TIME_FORMAT, GST_TIME_ARGS (dur)); dstr[9] = ’\0’; g_print ("%s␣/␣%s␣%s\r", pstr, dstr, status); } } static void state_changed_cb (GstPlayer * player, GstPlayerState state, GstPlay * play) { g_print ("State␣changed:␣%s\n", gst_player_state_get_name ( state)); } static void buffering_cb (GstPlayer * player, gint percent, GstPlay * play) { g_print ("Buffering:␣%d\n", percent); } static void print_one_tag (const GstTagList * list, const gchar * tag, gpointer user_data) { gint i, num; num = gst_tag_list_get_tag_size (list, tag); for (i = 0; i < num; ++i) { const GValue *val; val = gst_tag_list_get_value_index (list, tag, i); if (G_VALUE_HOLDS_STRING (val)) { g_print ("␣␣␣␣%s␣:␣%s␣\n", tag, g_value_get_string ( val)); } else if (G_VALUE_HOLDS_UINT (val)) { g_print ("␣␣␣␣%s␣:␣%u␣\n", tag, g_value_get_uint ( val)); } else if (G_VALUE_HOLDS_DOUBLE (val)) { g_print ("␣␣␣␣%s␣:␣%g␣\n", tag, g_value_get_double ( val)); } else if (G_VALUE_HOLDS_BOOLEAN (val)) { g_print ("␣␣␣␣%s␣:␣%s␣\n", tag, 204 g_value_get_boolean (val) ? "true" : "false"); } else if (GST_VALUE_HOLDS_DATE_TIME (val)) { GstDateTime *dt = g_value_get_boxed (val); gchar *dt_str = gst_date_time_to_iso8601_string (dt) ; g_print ("␣␣␣␣%s␣:␣%s␣\n", tag, dt_str); g_free (dt_str); } else { g_print ("␣␣␣␣%s␣:␣tag␣of␣type␣’%s’␣\n", tag, G_VALUE_TYPE_NAME (val)); } } } static void print_video_info (GstPlayerVideoInfo * info) { gint fps_n, fps_d; guint par_n, par_d; if (info == NULL) return; g_print ("␣␣width␣:␣%d\n", gst_player_video_info_get_width ( info)); g_print ("␣␣height␣:␣%d\n", gst_player_video_info_get_height (info)); g_print ("␣␣max_bitrate␣:␣%d\n", gst_player_video_info_get_max_bitrate (info)); g_print ("␣␣bitrate␣:␣%d\n", gst_player_video_info_get_bitrate (info)); gst_player_video_info_get_framerate (info, &fps_n, &fps_d); g_print ("␣␣framerate␣:␣%.2f\n", (gdouble) fps_n / fps_d); gst_player_video_info_get_pixel_aspect_ratio (info, &par_n, &par_d); g_print ("␣␣pixel-aspect-ratio␣␣%u:%u\n", par_n, par_d); } static void print_audio_info (GstPlayerAudioInfo * info) { if (info == NULL) return; g_print ("␣␣sample␣rate␣:␣%d\n", gst_player_audio_info_get_sample_rate (info)); 205 g_print ("␣␣channels␣:␣%d\n", gst_player_audio_info_get_channels (info)); g_print ("␣␣max_bitrate␣:␣%d\n", gst_player_audio_info_get_max_bitrate (info)); g_print ("␣␣bitrate␣:␣%d\n", gst_player_audio_info_get_bitrate (info)); g_print ("␣␣language␣:␣%s\n", gst_player_audio_info_get_language (info)); } static void print_subtitle_info (GstPlayerSubtitleInfo * info) { if (info == NULL) return; g_print ("␣␣language␣:␣%s\n", gst_player_subtitle_info_get_language (info)); } static void print_all_stream_info (GstPlayerMediaInfo * media_info) { guint count = 0; GList *list, *l; g_print ("URI␣:␣%s\n", gst_player_media_info_get_uri ( media_info)); g_print ("Duration:␣%" GST_TIME_FORMAT "\n", GST_TIME_ARGS (gst_player_media_info_get_duration ( media_info))); g_print ("Global␣taglist:\n"); if (gst_player_media_info_get_tags (media_info)) gst_tag_list_foreach (gst_player_media_info_get_tags ( media_info), print_one_tag, NULL); else g_print ("␣␣(nil)␣\n"); list = gst_player_media_info_get_stream_list (media_info); if (!list) return; g_print ("All␣Stream␣information\n"); for (l = list; l != NULL; l = l->next) { GstTagList *tags = NULL; GstPlayerStreamInfo *stream = (GstPlayerStreamInfo *) l ->data; 206 g_print ("␣Stream␣#␣%u␣\n", count++); g_print ("␣␣type␣:␣%s_%u\n", gst_player_stream_info_get_stream_type (stream), gst_player_stream_info_get_index (stream)); tags = gst_player_stream_info_get_tags (stream); g_print ("␣␣taglist␣:␣\n"); if (tags) { gst_tag_list_foreach (tags, print_one_tag, NULL); } if (GST_IS_PLAYER_VIDEO_INFO (stream)) print_video_info ((GstPlayerVideoInfo *) stream); else if (GST_IS_PLAYER_AUDIO_INFO (stream)) print_audio_info ((GstPlayerAudioInfo *) stream); else print_subtitle_info ((GstPlayerSubtitleInfo *) stream); } } static void print_all_video_stream (GstPlayerMediaInfo * media_info) { GList *list, *l; list = gst_player_get_video_streams (media_info); if (!list) return; g_print ("All␣video␣streams\n"); for (l = list; l != NULL; l = l->next) { GstPlayerVideoInfo *info = (GstPlayerVideoInfo *) l-> data; GstPlayerStreamInfo *sinfo = (GstPlayerStreamInfo *) info; g_print ("␣%s_%d␣#\n", gst_player_stream_info_get_stream_type (sinfo), gst_player_stream_info_get_index (sinfo)); print_video_info (info); } } static void print_all_subtitle_stream (GstPlayerMediaInfo * media_info) { GList *list, *l; list = gst_player_get_subtitle_streams (media_info); 207 if (!list) return; g_print ("All␣subtitle␣streams:\n"); for (l = list; l != NULL; l = l->next) { GstPlayerSubtitleInfo *info = (GstPlayerSubtitleInfo *) l->data; GstPlayerStreamInfo *sinfo = (GstPlayerStreamInfo *) info; g_print ("␣%s_%d␣#\n", gst_player_stream_info_get_stream_type (sinfo), gst_player_stream_info_get_index (sinfo)); print_subtitle_info (info); } } static void print_all_audio_stream (GstPlayerMediaInfo * media_info) { GList *list, *l; list = gst_player_get_audio_streams (media_info); if (!list) return; g_print ("All␣audio␣streams:␣\n"); for (l = list; l != NULL; l = l->next) { GstPlayerAudioInfo *info = (GstPlayerAudioInfo *) l-> data; GstPlayerStreamInfo *sinfo = (GstPlayerStreamInfo *) info; g_print ("␣%s_%d␣#\n", gst_player_stream_info_get_stream_type (sinfo), gst_player_stream_info_get_index (sinfo)); print_audio_info (info); } } static void print_current_tracks (GstPlay * play) { GstPlayerAudioInfo *audio = NULL; GstPlayerVideoInfo *video = NULL; GstPlayerSubtitleInfo *subtitle = NULL; g_print ("Current␣video␣track:␣\n"); video = gst_player_get_current_video_track (play->player); print_video_info (video); 208 g_print ("Current␣audio␣track:␣\n"); audio = gst_player_get_current_audio_track (play->player); print_audio_info (audio); g_print ("Current␣subtitle␣track:␣\n"); subtitle = gst_player_get_current_subtitle_track (play-> player); print_subtitle_info (subtitle); if (audio) g_object_unref (audio); if (video) g_object_unref (video); if (subtitle) g_object_unref (subtitle); } static void print_media_info (GstPlayerMediaInfo * media_info) { print_all_stream_info (media_info); g_print ("\n"); print_all_video_stream (media_info); g_print ("\n"); print_all_audio_stream (media_info); g_print ("\n"); print_all_subtitle_stream (media_info); } static void media_info_cb (GstPlayer * player, GstPlayerMediaInfo * info, GstPlay * play) { static int once = 0; if (!once) { print_media_info (info); print_current_tracks (play); once = 1; } } #if 0 static GstPlay * play_new (gchar ** uris, gdouble initial_volume) { GstPlay *play; 209 play = g_new0 (GstPlay, 1); play->uris = uris; play->num_uris = g_strv_length (uris); play->cur_idx = -1; play->player = gst_player_new (NULL, gst_player_g_main_context_signal_dispatcher_new (NULL)); g_signal_connect (play->player, "position-updated", G_CALLBACK (position_updated_cb), play); g_signal_connect (play->player, "state-changed", G_CALLBACK (state_changed_cb), play); g_signal_connect (play->player, "buffering", G_CALLBACK ( buffering_cb), play); g_signal_connect (play->player, "end-of-stream", G_CALLBACK (end_of_stream_cb), play); g_signal_connect (play->player, "error", G_CALLBACK ( error_cb), play); g_signal_connect (play->player, "media-info-updated", G_CALLBACK (media_info_cb), play); play->loop = g_main_loop_new (NULL, FALSE); play->desired_state = GST_STATE_PLAYING; play_set_relative_volume (play, initial_volume - 1.0); return play; } static void play_free (GstPlay * play) { play_reset (play); gst_object_unref (play->player); g_main_loop_unref (play->loop); g_strfreev (play->uris); g_free (play); } #endif /* reset for new file/stream */ static void play_reset (GstPlay * play) { } static void play_set_relative_volume (GstPlay * play, gdouble volume_step) 210 { gdouble volume; g_object_get (play->player, "volume", &volume, NULL); volume = round ((volume + volume_step) * VOLUME_STEPS) / VOLUME_STEPS; volume = CLAMP (volume, 0.0, 10.0); g_object_set (play->player, "volume", volume, NULL); g_print ("Volume:␣%.0f%%␣␣␣␣␣␣␣␣␣␣␣␣␣␣␣␣␣␣\n", volume * 100) ; } static gdouble get_volume (GtkWidget *widget, GstPlay *play) { gdouble volume; g_object_get (player, "volume", &volume, NULL); return volume; } #if 0 static gchar * play_uri_get_display_name (GstPlayer * player, const gchar * uri ) { gchar *loc; if (gst_uri_has_protocol (uri, "file")) { loc = g_filename_from_uri (uri, NULL, NULL); } else if (gst_uri_has_protocol (uri, "pushfile")) { loc = g_filename_from_uri (uri + 4, NULL, NULL); } else { loc = g_strdup (uri); } /* Maybe additionally use glib’s filename to display name function */ return loc; } void play_uri (GstPlayer *player, const gchar * next_uri) { gchar *loc; play_reset (player); loc = play_uri_get_display_name (player, next_uri); g_print ("Now␣playing␣%s\n", loc); 211 g_free (loc); g_object_set (player, "uri", next_uri, NULL); gst_player_play (player); } /* returns FALSE if we have reached the end of the playlist */ #if 0 static gboolean play_next (GstPlay * play) { if ((play->cur_idx + 1) >= play->num_uris) { if (play->repeat) { g_print ("Looping␣playlist␣\n"); play->cur_idx = -1; } else return FALSE; } play_uri (play, play->uris[++play->cur_idx]); return TRUE; } /* returns FALSE if we have reached the beginning of the playlist */ static gboolean play_prev (GstPlay * play) { if (play->cur_idx == 0 || play->num_uris <= 1) return FALSE; play_uri (play, play->uris[--play->cur_idx]); return TRUE; } static void do_play (GstPlay * play) { gint i; /* dump playlist */ for (i = 0; i < play->num_uris; ++i) GST_INFO ("%4u␣:␣%s", i, play->uris[i]); if (!play_next (play)) return; g_main_loop_run (play->loop); } 212 static void add_to_playlist (GPtrArray * playlist, const gchar * filename) { GDir *dir; gchar *uri; if (gst_uri_is_valid (filename)) { g_ptr_array_add (playlist, g_strdup (filename)); return; } if ((dir = g_dir_open (filename, 0, NULL))) { const gchar *entry; /* FIXME: sort entries for each directory? */ while ((entry = g_dir_read_name (dir))) { gchar *path; path = g_strconcat (filename, G_DIR_SEPARATOR_S, entry, NULL); add_to_playlist (playlist, path); g_free (path); } g_dir_close (dir); return; } uri = gst_filename_to_uri (filename, NULL); if (uri != NULL) g_ptr_array_add (playlist, uri); else g_warning ("Could␣not␣make␣URI␣out␣of␣filename␣’%s’", filename); } static void shuffle_uris (gchar ** uris, guint num) { gchar *tmp; guint i, j; if (num < 2) return; for (i = 0; i < num; i++) { /* gets equally distributed random number in 0..num-1 [0;num[ */ j = g_random_int_range (0, num); tmp = uris[j]; uris[j] = uris[i]; uris[i] = tmp; 213 } } static void restore_terminal (void) { gst_play_kb_set_key_handler (NULL, NULL); } static void toggle_paused (GstPlay * play) { if (play->desired_state == GST_STATE_PLAYING) { play->desired_state = GST_STATE_PAUSED; gst_player_pause (play->player); } else { play->desired_state = GST_STATE_PLAYING; gst_player_play (play->player); } } static void relative_seek (GstPlay * play, gdouble percent) { gint64 dur = -1, pos = -1; g_return_if_fail (percent >= -1.0 && percent <= 1.0); g_object_get (play->player, "position", &pos, "duration", & dur, NULL); if (dur <= 0) { g_print ("\nCould␣not␣seek.\n"); return; } pos = pos + dur * percent; if (pos < 0) pos = 0; gst_player_seek (play->player, pos); } static void keyboard_cb (const gchar * key_input, gpointer user_data) { GstPlay *play = (GstPlay *) user_data; switch (g_ascii_tolower (key_input[0])) { case ’i’: 214 { GstPlayerMediaInfo *media_info = gst_player_get_media_info (play->player); if (media_info) { print_media_info (media_info); g_object_unref (media_info); print_current_tracks (play); } break; } case ’␣’: toggle_paused (play); break; case ’q’: case ’Q’: g_main_loop_quit (play->loop); break; case ’>’: if (!play_next (play)) { g_print ("\nReached␣end␣of␣play␣list.\n"); g_main_loop_quit (play->loop); } break; case ’<’: play_prev (play); break; case 27: /* ESC */ if (key_input[1] == ’\0’) { g_main_loop_quit (play->loop); break; } /* fall through */ default: if (strcmp (key_input, GST_PLAY_KB_ARROW_RIGHT) == 0) { relative_seek (play, +0.08); } else if (strcmp (key_input, GST_PLAY_KB_ARROW_LEFT) == 0) { relative_seek (play, -0.01); } else if (strcmp (key_input, GST_PLAY_KB_ARROW_UP) == 0) { play_set_relative_volume (play, +1.0 / VOLUME_STEPS) ; } else if (strcmp (key_input, GST_PLAY_KB_ARROW_DOWN) == 0) { 215 play_set_relative_volume (play, -1.0 / VOLUME_STEPS) ; } else { GST_INFO ("keyboard␣input:"); for (; *key_input != ’\0’; ++key_input) GST_INFO ("␣␣code␣%3d", *key_input); } break; } } #endif #endif void gnome_internet_radio_locator_player_new (GstPlayer * player, const gchar * next_uri) { gst_player_set_uri(player, next_uri); } void gnome_internet_radio_locator_player_stop (GstPlayer *player) { if (player != NULL) { gst_player_stop(GST_PLAYER(player)); } } void gnome_internet_radio_locator_player_pause (GstPlayer *player) { /* FIXME: Unable to quit after pause is called for the first time. */ #if 0 gst_player_pause(player); #endif } #if 0 int main (int argc, char **argv) { GstPlay *play; GPtrArray *playlist; 216 gboolean print_version = FALSE; gboolean interactive = FALSE; /* FIXME: maybe enable by default? */ gboolean shuffle = FALSE; gboolean repeat = FALSE; gdouble volume = 1.0; gchar **filenames = NULL; gchar **uris; guint num, i; GError *err = NULL; GOptionContext *ctx; gchar *playlist_file = NULL; GOptionEntry options[] = { {"version", 0, 0, G_OPTION_ARG_NONE, &print_version, "Print␣version␣information␣and␣exit", NULL}, {"shuffle", 0, 0, G_OPTION_ARG_NONE, &shuffle, "Shuffle␣playlist", NULL}, {"interactive", 0, 0, G_OPTION_ARG_NONE, &interactive, "Interactive␣control␣via␣keyboard", NULL}, {"volume", 0, 0, G_OPTION_ARG_DOUBLE, &volume, "Volume", NULL}, {"playlist", 0, 0, G_OPTION_ARG_FILENAME, &playlist_file , "Playlist␣file␣containing␣input␣media␣files", NULL}, {"loop", 0, 0, G_OPTION_ARG_NONE, &repeat, "Repeat␣all", NULL}, {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, NULL}, {NULL} }; g_set_prgname ("gst-play"); ctx = g_option_context_new ("FILE1|URI1␣[FILE2|URI2]␣[FILE3| URI3]␣..."); g_option_context_add_main_entries (ctx, options, NULL); g_option_context_add_group (ctx, gst_init_get_option_group ()); if (!g_option_context_parse (ctx, &argc, &argv, &err)) { g_print ("Error␣initializing:␣%s\n", GST_STR_NULL (err-> message)); g_clear_error (&err); g_option_context_free (ctx); return 1; } g_option_context_free (ctx); 217 GST_DEBUG_CATEGORY_INIT (play_debug, "play", 0, "gst-play"); if (print_version) { gchar *version_str; version_str = gst_version_string (); g_print ("%s␣version␣%s\n", g_get_prgname (), "1.0"); g_print ("%s\n", version_str); g_free (version_str); g_free (playlist_file); return 0; } playlist = g_ptr_array_new (); if (playlist_file != NULL) { gchar *playlist_contents = NULL; gchar **lines = NULL; if (g_file_get_contents (playlist_file, & playlist_contents, NULL, &err)) { lines = g_strsplit (playlist_contents, "\n", 0); num = g_strv_length (lines); for (i = 0; i < num; i++) { if (lines[i][0] != ’\0’) { GST_LOG ("Playlist[%d]:␣%s", i + 1, lines[i ]); add_to_playlist (playlist, lines[i]); } } g_strfreev (lines); g_free (playlist_contents); } else { g_printerr ("Could␣not␣read␣playlist:␣%s\n", err-> message); g_clear_error (&err); } g_free (playlist_file); playlist_file = NULL; } if (playlist->len == 0 && (filenames == NULL || *filenames == NULL)) { g_printerr ("Usage:␣%s␣FILE1|URI1␣[FILE2|URI2]␣[FILE3| URI3]␣...", "gst-play"); g_printerr ("\n\n"), g_printerr ("%s\n\n", "You␣must␣provide␣at␣least␣one␣filename␣or␣ URI␣to␣play."); 218 /* No input provided. Free array */ g_ptr_array_free (playlist, TRUE); return 1; } /* fill playlist */ if (filenames != NULL && *filenames != NULL) { num = g_strv_length (filenames); for (i = 0; i < num; ++i) { GST_LOG ("command␣line␣argument:␣%s", filenames[i]); add_to_playlist (playlist, filenames[i]); } g_strfreev (filenames); } num = playlist->len; g_ptr_array_add (playlist, NULL); uris = (gchar **) g_ptr_array_free (playlist, FALSE); if (shuffle) shuffle_uris (uris, num); /* prepare */ play = play_new (uris, volume); play->repeat = repeat; if (interactive) { if (gst_play_kb_set_key_handler (keyboard_cb, play)) { atexit (restore_terminal); } else { g_print ("Interactive␣keyboard␣handling␣in␣terminal␣ not␣available.\n"); } } /* play */ do_play (play); /* clean up */ play_free (play); g_print ("\n"); gst_deinit (); return 0; } #endif 36.6 gnome-internet-radio-locator-program.c 219 36.7 gnome-internet-radio-locator-runners.c 36.8 gnome-internet-radio-locator-station.c /* $id$ * * GNOME Internet Radio Locator * * Copyright (C) 2014-2019 Aamot Software * * Author: Ole Aamot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License , or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * 220 * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "gnome-internet-radio-locator.h" #include "gnome-internet-radio-locator-station.h" extern GNOMEInternetRadioLocatorData * gnome_internet_radio_locator; extern GNOMEInternetRadioLocatorStationInfo *stationinfo, * localstation; extern gchar *world_station_xml_filename, * local_station_xml_file; extern GStatBuf stats; extern GtkEntryCompletion *completion; GtkListStore *model = NULL; GtkTreeIter iter; void gnome_internet_radio_locator_helper_run(gchar *url, gchar * name, GNOMEInternetRadioLocatorStreamType type, GNOMEInternetRadioLocatorHelperType helper) { GError *err = NULL; GTimeVal mtime; /* const char *mime_info = NULL; */ 221 /* GnomeVFSMimeApplication *app; */ char *app = NULL, *command = NULL, *msg = NULL; char **argv = NULL; gint argc; gboolean ret; GError *error = NULL; GCancellable *player_cancellable; GCancellable *record_cancellable; if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) { perror(0); exit(1); } g_return_if_fail(url != NULL); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("%s", url); /* mime_info = gnome_vfs_get_mime_type(url); */ g_get_current_time(&mtime); /* app = (gchar *)gnome_vfs_mime_get_default_application ( mime_info); */ // gnome_internet_radio_locator_player_main(url, gnome_internet_radio_locator->selected_station_name); if (helper == GNOME_INTERNET_RADIO_LOCATOR_STREAM_PLAYER) { /* gnome_internet_radio_locator_player_main(url, gnome_internet_radio_locator->selected_station_name); */ } if (helper == GNOME_INTERNET_RADIO_LOCATOR_STREAM_RECORD) { /* gnome_internet_radio_locator_record_main(url, gnome_internet_radio_locator->selected_station_name); */ } return; #if 0 if (g_strcmp0(app,"no")!=0) { command = g_strconcat(app, "␣", url, NULL); 222 GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("Helper␣ application␣is␣%s\n", command); if (type == GNOME_INTERNET_RADIO_LOCATOR_STREAM_SHOUTCAST) { if (helper == GNOME_INTERNET_RADIO_LOCATOR_STREAM_PLAYER) { command = g_strconcat(app, "␣", url, NULL); /* argv[0] = g_strdup(app); */ /* argv[1] = g_strdup(url); */ } if (helper == GNOME_INTERNET_RADIO_LOCATOR_STREAM_RECORD) { GtkWidget *dialog; char *filename, *default_filename; GDate gdate; time_t t; struct tm *tmp; char outstr[200]; t = time(NULL); tmp = localtime(&t); strftime(outstr, sizeof(outstr), "%a,␣%d␣%b␣%Y␣% T␣%z", tmp); dialog = gtk_file_chooser_dialog_new ("Save␣ Recorded␣Broadcast␣File", GTK_WINDOW( gnome_internet_radio_locator_app ), GTK_FILE_CHOOSER_ACTION_SAVE , GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); default_filename = g_strconcat( gnome_internet_radio_locator-> selected_station_name, "␣-␣Broadcast␣ Recording␣-␣", outstr, ".mp3", NULL); gtk_file_chooser_set_current_name ( GTK_FILE_CHOOSER (dialog), default_filename); if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) { 223 filename = gtk_file_chooser_get_filename ( GTK_FILE_CHOOSER (dialog)); gnome_internet_radio_locator-> selected_archive_file = g_strconcat( filename, NULL); } gtk_widget_destroy (dialog); /* printf("Archiving program at %s\n", archive); */ appbar_send_msg(_("Recording␣from␣%s␣in␣%s␣to␣%s "), gnome_internet_radio_locator-> selected_station_name, gnome_internet_radio_locator-> selected_station_location, gnome_internet_radio_locator-> selected_archive_file); command = g_strconcat(app, "␣", url, "␣-d␣", g_get_home_dir(), "/. gnome_internet_radio_locator/␣-D␣%D", NULL); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("%s\n", command); // gnome_internet_radio_locator_archive_new(" Archive", gnome_internet_radio_locator-> selected_archive_file); /* " -d ", g_get_home_dir(), "/. gnome_internet_radio_locator -D \"", name, "\" -s -a -u gnome_internet_radio_locator/", VERSION, NULL); */ /* command = g_strconcat(command, " -d ", g_get_home_dir(), "/. gnome_internet_radio_locator/", name, " -D %S %A%T -t 10 -u gnome_internet_radio_locator/", VERSION, NULL); */ } GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("Helper␣ command␣is␣%s\n", command); } /* gnome_vfs_mime_application_free (app); */ 224 } else { if (helper == GNOME_INTERNET_RADIO_LOCATOR_STREAM_PLAYER ) { msg = g_strdup_printf(_("An␣error␣happened␣trying␣to ␣play␣" "%s\nEither␣the␣file␣doesn’t␣exist,␣or␣ you␣" "don’t␣have␣a␣player␣for␣it."), url); } if (helper == GNOME_INTERNET_RADIO_LOCATOR_STREAM_RECORD ) { msg = g_strdup_printf(_("An␣error␣happened␣trying␣to ␣record␣" "%s\nEither␣the␣file␣doesn’t␣exist,␣or␣ you␣" "don’t␣have␣a␣recorder␣for␣it."), url); } if (msg != NULL) { show_error(msg); g_free(msg); } return; } if (helper == GNOME_INTERNET_RADIO_LOCATOR_STREAM_PLAYER) { #if 0 g_shell_parse_argv(command, &argc, &argv, NULL); ret = g_spawn_async_with_pipes (".", argv, NULL, G_SPAWN_SEARCH_PATH| G_SPAWN_STDOUT_TO_DEV_NULL| G_SPAWN_STDERR_TO_DEV_NULL| G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &gnome_internet_radio_locator-> player_pid, NULL, 225 NULL, NULL, &err); if( ! ret ) { msg = g_strdup_printf(_("Failed␣to␣run␣%s␣(%i)\n"), command, gnome_internet_radio_locator->player_pid ); show_error(msg); g_free(msg); return; } /* Add watch function to catch termination of the process. This function * will clean any remnants of process. */ g_child_watch_add( gnome_internet_radio_locator-> player_pid, (GChildWatchFunc)cb_child_watch_player, gnome_internet_radio_locator); /* gnome_internet_radio_locator->player_pid = pid; */ gnome_internet_radio_locator->player_status = GNOME_INTERNET_RADIO_LOCATOR_PLAYER_TRUE; /* Install timeout fnction that will move the progress bar */ gnome_internet_radio_locator->timeout_id = g_timeout_add (100,(GSourceFunc)cb_timeout, gnome_internet_radio_locator); /* #endif */ /* #if 0 */ ret = g_spawn_async_with_pipes( NULL, /* command */ argv , NULL, G_SPAWN_DO_NOT_REAP_CHILD| G_SPAWN_DEFAULT, NULL, NULL, &gnome_internet_radio_locator-> player_pid, NULL, &out, &error, NULL ); if( ! ret ) { msg = g_strdup_printf(_("Failed␣to␣run␣%s␣(%i)\n"), command, gnome_internet_radio_locator->player_pid ); show_error(msg); g_free(msg); return; 226 } /* Add watch function to catch termination of the process. This function * will clean any remnants of process. */ g_child_watch_add( gnome_internet_radio_locator-> player_pid, (GChildWatchFunc)cb_child_watch_player, gnome_internet_radio_locator ); /* Create channels that will be used to read gnome_internet_radio_locator from pipes. * #ifdef G_OS_WIN32 out_ch = g_io_channel_win32_new_fd( out ); err_ch = g_io_channel_win32_new_fd( error ); #else out_ch = g_io_channel_unix_new( out ); err_ch = g_io_channel_unix_new( error ); #endif */ /* Add watches to channels */ g_io_add_watch( out_ch, G_IO_IN | G_IO_HUP, (GIOFunc) cb_out_watch, gnome_internet_radio_locator ); g_io_add_watch( err_ch, G_IO_IN | G_IO_HUP, (GIOFunc) cb_err_watch, gnome_internet_radio_locator ); /* Install timeout fnction that will move the progress bar */ gnome_internet_radio_locator->timeout_id = g_timeout_add ( 100, (GSourceFunc)cb_timeout, gnome_internet_radio_locator ); /* #endif */ #if 0 if (!g_spawn_command_line_sync(command, stdout, stderr, status, &err)) { msg = g_strdup_printf(_("Failed␣to␣open␣URL:␣’%s’\n" "Status␣code:␣%i\n" "Details:␣%s"), url, status, err-> message); show_error(msg); g_error_free(err); g_free(msg); } else { GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("Launching␣%s \n", command); } 227 /* Add watch function to catch termination of the process. This function * will clean any remnants of process. */ g_child_watch_add( gnome_internet_radio_locator-> player_pid, (GChildWatchFunc)cb_child_watch_player, gnome_internet_radio_locator ); #endif /* Original async player code */ gnome_internet_radio_locator->player_launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE); gnome_internet_radio_locator->player_subprocess = g_subprocess_launcher_spawn ( gnome_internet_radio_locator->player_launcher, &error , app, url, NULL); if (gnome_internet_radio_locator->player_subprocess == NULL) { msg = g_strdup_printf(_("Failed␣to␣open␣URL:␣’%s’\n" "Details:␣%s"), url, error->message); show_error(msg); g_error_free(error); g_free(msg); goto quit_player; } else { gnome_internet_radio_locator->player_status = GNOME_INTERNET_RADIO_LOCATOR_PLAYER_TRUE; GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("Launching␣%s ␣player\n", command); } #endif #if 0 if (!g_spawn_command_line_async(command, &err)) { msg = g_strdup_printf(_("Failed␣to␣open␣URL:␣’%s’\n" "Details:␣%s"), url, err->message); show_error(msg); g_error_free(err); g_free(msg); } else { gnome_internet_radio_locator->player_status = GNOME_INTERNET_RADIO_LOCATOR_PLAYER_TRUE; GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("Launching␣%s ␣player\n", command); 228 g_subprocess_wait_async ( gnome_internet_radio_locator->player_subprocess, player_cancellable, (GAsyncReadyCallback) cb_subprocess_player, NULL); } #endif } if (helper == GNOME_INTERNET_RADIO_LOCATOR_STREAM_RECORD) { /* #if 0 */ /* gchar *argv[] = { command, NULL }; */ /* Spawn child process */ gchar *recording_path_name = g_strconcat(g_get_home_dir (), "/.gnome_internet_radio_locator/", NULL); gchar *formatting_argument = g_strdup("-D␣%D"); gnome_internet_radio_locator->record_launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE); /* gnome_internet_radio_locator->record_subprocess = g_subprocess_launcher_spawn ( gnome_internet_radio_locator->record_launcher, &error , GNOME_INTERNET_RADIO_LOCATOR_HELPER_RECORD, url, "- d", recording_path_name, "-D", "%D", NULL); */ if (gnome_internet_radio_locator->record_subprocess == NULL) { /* msg = g_strdup_printf(_("Failed to run ’%s’\n" */ /* "Details: %s"), GNOME_INTERNET_RADIO_LOCATOR_HELPER_RECORD, error ->message); */ show_error(msg); g_error_free(error); g_free(msg); goto quit_record; } else { GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("Launching␣%s \n", command); g_subprocess_wait_async ( gnome_internet_radio_locator->record_subprocess, record_cancellable, (GAsyncReadyCallback) cb_subprocess_record, NULL); 229 } #if 0 g_shell_parse_argv(command, &argc, &argv, NULL); ret = g_spawn_async_with_pipes (".", argv, NULL, G_SPAWN_SEARCH_PATH| G_SPAWN_STDOUT_TO_DEV_NULL| G_SPAWN_STDERR_TO_DEV_NULL| G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &gnome_internet_radio_locator-> record_pid, NULL, NULL, NULL, &err); if( ! ret ) { msg = g_strdup_printf(_("Failed␣to␣run␣%s␣(%i)\n"), command, gnome_internet_radio_locator->record_pid ); show_error(msg); g_free(msg); return; } /* Add watch function to catch termination of the process. This function * will clean any remnants of process. */ g_child_watch_add( gnome_internet_radio_locator-> record_pid, (GChildWatchFunc)cb_child_watch_record, gnome_internet_radio_locator); /* gnome_internet_radio_locator->record_pid = pid; */ gnome_internet_radio_locator->record_status = GNOME_INTERNET_RADIO_LOCATOR_RECORD_TRUE; gnome_internet_radio_locator_archive_new("Archive", gnome_internet_radio_locator->selected_archive_file, 230 gnome_internet_radio_locator->selected_streams_codec) ; /* Install timeout fnction that will move the progress bar */ gnome_internet_radio_locator->timeout_id = g_timeout_add (100,(GSourceFunc)cb_timeout, gnome_internet_radio_locator); /* #endif */ #if 0 ret = g_spawn_async_with_pipes( NULL, /* command */ argv , NULL, G_SPAWN_DO_NOT_REAP_CHILD| G_SPAWN_DEFAULT, NULL, NULL, &gnome_internet_radio_locator-> record_pid, NULL, &out, &error, NULL ); if( ! ret ) { msg = g_strdup_printf(_("Failed␣to␣run␣%s␣(%i)\n"), command, gnome_internet_radio_locator->record_pid ); show_error(msg); g_free(msg); return; } /* Add watch function to catch termination of the process. This function * will clean any remnants of process. */ g_child_watch_add( gnome_internet_radio_locator-> record_pid, (GChildWatchFunc)cb_child_watch_record, gnome_internet_radio_locator ); /* Create channels that will be used to read gnome_internet_radio_locator from pipes. */ #ifdef G_OS_WIN32 out_ch = g_io_channel_win32_new_fd( out ); err_ch = g_io_channel_win32_new_fd( error ); #else out_ch = g_io_channel_unix_new( out ); err_ch = g_io_channel_unix_new( error ); #endif /* Add watches to channels */ g_io_add_watch( out_ch, G_IO_IN | G_IO_HUP, (GIOFunc) cb_out_watch, gnome_internet_radio_locator ); 231 g_io_add_watch( err_ch, G_IO_IN | G_IO_HUP, (GIOFunc) cb_err_watch, gnome_internet_radio_locator ); /* Install timeout fnction that will move the progress bar */ gnome_internet_radio_locator->timeout_id = g_timeout_add ( 100, (GSourceFunc)cb_timeout, gnome_internet_radio_locator ); #endif #if 0 if (!g_spawn_command_line_sync(command, stdout, stderr, status, &err)) { msg = g_strdup_printf(_("Failed␣to␣open␣URL:␣’%s’\n" "Status␣code:␣%i\n" "Details:␣%s"), url, status, err-> message); show_error(msg); g_error_free(err); g_free(msg); } else { GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("Launching␣%s \n", command); } /* Add watch function to catch termination of the process. This function * will clean any remnants of process. */ g_child_watch_add( gnome_internet_radio_locator-> record_pid, (GChildWatchFunc)cb_child_watch_record, gnome_internet_radio_locator ); #endif #endif } quit_player: if (gnome_internet_radio_locator->player_subprocess) g_object_unref(gnome_internet_radio_locator-> player_subprocess); if (gnome_internet_radio_locator->player_launcher) g_object_unref(gnome_internet_radio_locator-> player_launcher); quit_record: if (gnome_internet_radio_locator->record_subprocess) g_object_unref(gnome_internet_radio_locator-> record_subprocess); 232 if (gnome_internet_radio_locator->record_launcher) g_object_unref(gnome_internet_radio_locator-> record_launcher); #endif } static void gnome_internet_radio_locator_station_parser( GNOMEInternetRadioLocatorStationInfo * station, xmlDocPtr doc , xmlNodePtr cur) { xmlNodePtr sub; char *chans; g_return_if_fail(station != NULL); g_return_if_fail(doc != NULL); g_return_if_fail(cur != NULL); station->id = (gchar *)xmlGetProp(cur, (const xmlChar *)"id" ); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("station->id␣=␣%s\n", station->id); station->name = (gchar *)xmlGetProp(cur, (const xmlChar *)" name"); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("station->name␣=␣%s\n ", station->name); station->rank = (gchar *)xmlGetProp(cur, (const xmlChar *)" rank"); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("station->rank␣=␣%s\n ", station->rank); station->type = (gchar *)xmlGetProp(cur, (const xmlChar *)" type"); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("station->type␣=␣%s\n ", station->type); station->band = (gchar *)xmlGetProp(cur, (const xmlChar *)" band"); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("station->band␣=␣%s\n ", station->band); sub = cur->xmlChildrenNode; while (sub != NULL) { 233 if ((!xmlStrcmp(sub->name, (const xmlChar *) "frequency" ))) { station->frequency = (gchar *) xmlNodeListGetString(doc, sub->xmlChildrenNode, 1); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("station-> frequency␣=␣%s\n", station->frequency); } if ((!xmlStrcmp(sub->name, (const xmlChar *) "location") )) { station->location = (gchar *) xmlNodeListGetString(doc, sub->xmlChildrenNode, 1); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("station-> location␣=␣%s\n", station->location); } if ((!xmlStrcmp (sub->name, (const xmlChar *) "description"))) { station->description = (gchar *) xmlNodeListGetString(doc, sub->xmlChildrenNode, 1); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("station-> description␣=␣%s\n", station->description); } if ((!xmlStrcmp(sub->name, (const xmlChar *) "uri"))) { station->uri = (gchar *) xmlNodeListGetString(doc, sub->xmlChildrenNode, 1); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("station->uri ␣=␣%s\n", station->uri); /* fprintf(stdout, "%s (%s)\n\n", station->uri, station->name, station->location); */ } if ((!xmlStrcmp(sub->name, (const xmlChar *) "stream"))) { 234 GNOMEInternetRadioLocatorStreamInfo *stream = g_new0 (GNOMEInternetRadioLocatorStreamInfo, 1); /* gnome_internet_radio_locator->stream_count++; */ station->stream = stream; station->stream->mimetype = (gchar *) xmlGetProp(sub, (const xmlChar *)"mime"); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("station-> stream->mimetype␣=␣%s\n", station->stream->mimetype); if (xmlGetProp(sub, (const xmlChar *)"bitrate") != NULL) { station->stream->bitrate = (glong)atol((char *)xmlGetProp(sub, (const xmlChar *)"bitrate")); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("station ->stream->bitrate␣=␣%li\n", station->stream->bitrate); } if (xmlGetProp(sub, (const xmlChar *)"samplerate") != NULL) { station->stream->samplerate = (glong) atol((char *)xmlGetProp(sub, (const xmlChar *)" samplerate")); } GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("station-> stream->samplerate␣=␣%li\n", station->stream->samplerate); station->stream->uri = (gchar *)xmlGetProp(sub, ( const xmlChar *)"uri"); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("station-> stream->uri␣=␣%s\n", station->stream->uri); chans = (gchar *)xmlGetProp(sub, (const xmlChar *)" stations"); if (chans != NULL) { if (strcmp(chans, "stereo") == 0) { station->stream->channels = 235 GNOME_INTERNET_RADIO_LOCATOR_CHANNELS_STEREO ; GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" station->stream->channels␣=␣%d\n", station->stream->channels); } else if (strcmp(chans, "mono") == 0) { station->stream->channels = GNOME_INTERNET_RADIO_LOCATOR_CHANNELS_MONO ; GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" station->stream->channels␣=␣%d\n", station->stream->channels); } else if (strcmp(chans, "5:1") == 0) { station->stream->channels = GNOME_INTERNET_RADIO_LOCATOR_CHANNELS_5_1 ; GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" station->stream->channels␣=␣%d\n", station->stream->channels); } g_free(chans); } } /* if... "stream" */ sub = sub->next; } /* gnome_internet_radio_locator->station_count++; */ return; } GNOMEInternetRadioLocatorStationInfo * gnome_internet_radio_locator_station_load_from_http( GNOMEInternetRadioLocatorStationInfo * head, gpointer data) { GNOMEInternetRadioLocatorStationInfo *gstation; gstation = gnome_internet_radio_locator_station_load_from_file (head , "https://people.gnome.org/~ole/gnome-internet-radio- locator/gnome_internet_radio_locator.xml"); return gstation; } 236 GNOMEInternetRadioLocatorStationInfo * gnome_internet_radio_locator_station_load_from_file( GNOMEInternetRadioLocatorStationInfo * head, char *filename) { xmlDocPtr doc = NULL; xmlNodePtr cur = NULL; GNOMEInternetRadioLocatorStationInfo *curr = NULL; char *version; GNOMEInternetRadioLocatorStationInfo *mem_station; g_return_val_if_fail(filename != NULL, NULL); doc = xmlReadFile(filename, NULL, 0); if (doc == NULL) { perror("xmlParseFile"); xmlFreeDoc(doc); return NULL; } cur = xmlDocGetRootElement(doc); if (cur == NULL) { fprintf(stderr, "Empty␣document\n"); xmlFreeDoc(doc); return NULL; } if (xmlStrcmp(cur->name, (const xmlChar *) " gnome_internet_radio_locator")) { fprintf(stderr, "Document␣of␣wrong␣type,␣root␣node␣!=␣ gnome_internet_radio_locator\n"); xmlFreeDoc(doc); return NULL; } version = (gchar *)xmlGetProp(cur, (const xmlChar *)"version "); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("Valid␣ GNOMEInternetRadioLocator␣%s␣XML␣document...␣Parsing␣ stations...\n", 237 version); free(version); cur = cur->xmlChildrenNode; while (cur != NULL) { if ((!xmlStrcmp(cur->name, (const xmlChar *) "station")) ) { GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("Found␣a␣new␣ station.\n"); curr = g_new0(GNOMEInternetRadioLocatorStationInfo, 1); mem_station = g_new0( GNOMEInternetRadioLocatorStationInfo, 1); gnome_internet_radio_locator_station_parser(curr, doc, cur); curr->next = head; head = curr; mem_station = head; gnome_internet_radio_locator_stations = g_list_append( gnome_internet_radio_locator_stations, ( GNOMEInternetRadioLocatorStationInfo *) mem_station); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("Done␣with␣ parsing␣the␣station.\n"); } cur = cur->next; } GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG("Finished␣parsing␣XML ␣document.\n"); 238 xmlFreeDoc(doc); return curr; } gint gnome_internet_radio_locator_station_update ( GNOMEInternetRadioLocatorStationInfo *head, gchar * station_band, gchar *station_description, gchar *station_name , gchar *station_location, gchar *station_uri, gchar * station_website) { gchar msg[256]; gchar *msg1, *msg2; /* Open ~/.gnome_internet_radio_locator/ gnome_internet_radio_locator.xml. Parse structure. Insert new item. Save structure. */ GNOMEInternetRadioLocatorStationInfo *new_station; GNOMEInternetRadioLocatorStationInfo *stationinfo; /* GList *gnome_internet_radio_locator_local_stations = NULL ; */ gchar *local_station_uri, *local_station_name, * local_station_location, *local_station_band, * local_station_description, *local_station_website; gchar *stations = g_strconcat(g_get_home_dir(), "/.gnome- internet-radio-locator/gnome-internet-radio-locator.xml", NULL); gboolean local_gnome_internet_radio_locator_file = g_file_test (".gnome-internet-radio-locator/gnome- internet-radio-locator.xml", G_FILE_TEST_EXISTS); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" local_gnome_internet_radio_locator_file␣=␣%i\n", local_gnome_internet_radio_locator_file); if (local_gnome_internet_radio_locator_file == 0) { gchar *local_gnome_internet_radio_locator_directory = g_strconcat(g_get_home_dir(), "/.gnome-internet-radio -locator", NULL); g_mkdir_with_parents ( local_gnome_internet_radio_locator_directory, 0700); } 239 FILE *fp; stationinfo = gnome_internet_radio_locator_station_load_from_file(NULL, stations); new_station = g_new0(GNOMEInternetRadioLocatorStationInfo, 1); new_station->name = g_strdup(station_name); new_station->band = g_strdup(station_band); new_station->description = g_strdup(station_description); new_station->location = g_strdup(station_location); new_station->stream = g_new0( GNOMEInternetRadioLocatorStreamInfo, 1); new_station->stream->uri = g_strdup(station_uri); new_station->uri = g_strdup(station_website); fp = g_fopen(stations, "w+"); g_fprintf(fp, "\n\n< gnome_internet_radio_locator␣version=’%s’>\n", VERSION); // stationinfo-> = l->data; while (stationinfo != NULL) { local_station_uri = g_strdup(stationinfo->stream->uri); local_station_name = g_strdup(stationinfo->name); local_station_location = g_strdup(stationinfo->location) ; local_station_band = g_strdup(stationinfo->band); local_station_description = g_strdup(stationinfo-> description); local_station_website = g_strdup(stationinfo->uri); /* FIXME: Save mime=’audio/mp3’ uri=’%s’ codec=’MPEG 1 Audio, Layer 3 (MP3)’ samplerate=’24000 Hz’ channels =’Mono’ bitrate=’32 kbps’ */ g_fprintf(fp, "␣␣\n␣␣␣␣< frequency␣uri=\"%s\">%s␣in␣%s\n␣␣␣␣< location>%s\n␣␣␣␣%s\n␣␣␣␣\n␣␣␣␣< uri>%s\n␣␣\n", local_station_band, local_station_name, local_station_name, local_station_website, local_station_band, local_station_location, local_station_location, local_station_description, local_station_uri, 240 local_station_website); stationinfo = stationinfo->next; } g_fprintf(fp, "␣␣\n␣␣␣␣%s␣in␣%s\n␣␣␣␣%s\n␣␣␣␣%s\ n␣␣␣␣\n␣␣␣␣%s\n␣␣\n", new_station->band, new_station->name, new_station->name, new_station->uri, new_station->band, new_station->location, new_station->location, new_station ->description, new_station->stream->uri, new_station->uri ); g_fprintf(fp, "\n"); fclose(fp); gnome_internet_radio_locator_stations = g_list_append( gnome_internet_radio_locator_stations, ( GNOMEInternetRadioLocatorStationInfo *)new_station); g_free(stations); g_free(new_station); g_free(stationinfo); model = gtk_list_store_new(11, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); world_station_xml_filename = g_strconcat( GNOME_INTERNET_RADIO_LOCATOR_DATADIR, "/gnome-internet- radio-locator.xml", NULL); GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(" world_station_xml_filename␣=␣%s\n", world_station_xml_filename); if (world_station_xml_filename == NULL) { g_warning(("Failed␣to␣open␣%s.␣␣Please␣install␣it.\n"), world_station_xml_filename); } local_station_xml_file = 241 g_strconcat(g_get_home_dir(), "/.gnome-internet-radio- locator/gnome-internet-radio-locator.xml", NULL); if (!g_stat(local_station_xml_file, &stats)) { localstation = gnome_internet_radio_locator_station_load_from_file( NULL, local_station_xml_file); } else { localstation = NULL; } if (localstation == NULL) { printf("Failed␣to␣open␣%s.\n", local_station_xml_file); } /* g_free (local_station_xml_file); */ stationinfo = gnome_internet_radio_locator_station_load_from_file( localstation, world_station_xml_filename); gnome_internet_radio_locator_stations = NULL; while (stationinfo != NULL) { gtk_list_store_append(model, &iter); gtk_list_store_set(model, &iter, STATION_NAME, stationinfo->name, STATION_LOCATION, stationinfo->location, STATION_URI, stationinfo->stream->uri, STATION_DESCRIPTION, stationinfo->description, STATION_FREQUENCY, stationinfo->frequency, STATION_BAND, stationinfo->band, STATION_TYPE, stationinfo->type, STATION_RANK, stationinfo->rank, 242 STATION_BITRATE, stationinfo->bitrate, STATION_SAMPLERATE, stationinfo->samplerate, STATION_ID, stationinfo->id, -1); stationinfo = stationinfo->next; } gtk_entry_completion_set_model(completion, GTK_TREE_MODEL( model)); return (0); } 36.9 gnome-internet-radio-locator-stations-map.c 36.10 gnome-internet-radio-locator-streams.c 36.11 gnome-internet-radio-locator-tz.c 243 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic- offset: 8 -*- */ /* $Id$ * * GNOME Internet Radio Locator * * Copyright (C) 2015, 2018, 2019 Aamot Software * * Author: Ole Aamot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License , or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /* * Essential parts of the source code below was based on * gnome-control-center/panels/datetime/tz.c * */ /* Generic timezone utilities. * * Copyright (C) 2000-2001 Ximian, Inc. * * Authors: Hans Petter Jansson * * Largely based on Michael Fulbright’s work on Anaconda. 244 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License , or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ #include #include #include #include #include #include #include #include #include "gnome-internet-radio-locator-tz.h" /* Forward declarations for private functions */ static float convert_pos (gchar *pos, int digits); static int compare_country_names (const void *a, const void *b); static void sort_locations_by_country (GPtrArray *locations); static gchar * tz_data_file_get (void); static void load_backward_tz (TzDB *tz_db); /* ---------------- * * Public interface * * ---------------- */ 245 TzDB * tz_load_db (void) { gchar *tz_data_file; TzDB *tz_db; FILE *tzfile; char buf[4096]; tz_data_file = tz_data_file_get (); if (!tz_data_file) { g_warning ("Could␣not␣get␣the␣TimeZone␣data␣file␣name"); return NULL; } tzfile = fopen (tz_data_file, "r"); if (!tzfile) { g_warning ("Could␣not␣open␣*%s*\n", tz_data_file); g_free (tz_data_file); return NULL; } tz_db = g_new0 (TzDB, 1); tz_db->locations = g_ptr_array_new (); while (fgets (buf, sizeof(buf), tzfile)) { gchar **tmpstrarr; gchar *latstr, *lngstr, *p; TzLocation *loc; if (*buf == ’#’) continue; g_strchomp(buf); tmpstrarr = g_strsplit(buf,"\t", 6); latstr = g_strdup (tmpstrarr[1]); p = latstr + 1; while (*p != ’-’ && *p != ’+’) p++; lngstr = g_strdup (p); *p = ’\0’; loc = g_new0 (TzLocation, 1); loc->country = g_strdup (tmpstrarr[0]); loc->zone = g_strdup (tmpstrarr[2]); loc->latitude = convert_pos (latstr, 2); 246 loc->longitude = convert_pos (lngstr, 3); #ifdef __sun if (tmpstrarr[3] && *tmpstrarr[3] == ’-’ && tmpstrarr [4]) loc->comment = g_strdup (tmpstrarr[4]); if (tmpstrarr[3] && *tmpstrarr[3] != ’-’ && !islower(loc ->zone)) { TzLocation *locgrp; /* duplicate entry */ locgrp = g_new0 (TzLocation, 1); locgrp->country = g_strdup (tmpstrarr[0]); locgrp->zone = g_strdup (tmpstrarr[3]); locgrp->latitude = convert_pos (latstr, 2); locgrp->longitude = convert_pos (lngstr, 3); locgrp->comment = (tmpstrarr[4]) ? g_strdup ( tmpstrarr[4]) : NULL; g_ptr_array_add (tz_db->locations, (gpointer) locgrp ); } #else loc->comment = (tmpstrarr[3]) ? g_strdup(tmpstrarr[3]) : NULL; #endif g_ptr_array_add (tz_db->locations, (gpointer) loc); g_free (latstr); g_free (lngstr); g_strfreev (tmpstrarr); } fclose (tzfile); /* now sort by country */ sort_locations_by_country (tz_db->locations); g_free (tz_data_file); /* Load up the hashtable of backward links */ load_backward_tz (tz_db); 247 return tz_db; } static void tz_location_free (TzLocation *loc) { g_free (loc->country); g_free (loc->zone); g_free (loc->comment); g_free (loc); } void tz_db_free (TzDB *db) { g_ptr_array_foreach (db->locations, (GFunc) tz_location_free , NULL); g_ptr_array_free (db->locations, TRUE); g_hash_table_destroy (db->backward); g_free (db); } GPtrArray * tz_get_locations (TzDB *db) { return db->locations; } gchar * tz_location_get_country (TzLocation *loc) { return loc->country; } gchar * tz_location_get_zone (TzLocation *loc) { return loc->zone; } 248 gchar * tz_location_get_comment (TzLocation *loc) { return loc->comment; } void tz_location_get_position (TzLocation *loc, double *longitude, double *latitude) { *longitude = loc->longitude; *latitude = loc->latitude; } glong tz_location_get_utc_offset (TzLocation *loc) { TzInfo *tz_info; glong offset; tz_info = tz_info_from_location (loc); offset = tz_info->utc_offset; tz_info_free (tz_info); return offset; } TzInfo * tz_info_from_location (TzLocation *loc) { TzInfo *tzinfo; time_t curtime; struct tm *curzone; gchar *tz_env_value; g_return_val_if_fail (loc != NULL, NULL); g_return_val_if_fail (loc->zone != NULL, NULL); tz_env_value = g_strdup (getenv ("TZ")); setenv ("TZ", loc->zone, 1); #if 0 tzset (); 249 #endif tzinfo = g_new0 (TzInfo, 1); curtime = time (NULL); curzone = localtime (&curtime); #ifndef __sun /* Currently this solution doesnt seem to work - I get that */ /* America/Phoenix uses daylight savings, which is wrong */ tzinfo->tzname_normal = g_strdup (curzone->tm_zone); if (curzone->tm_isdst) tzinfo->tzname_daylight = g_strdup (&curzone->tm_zone[curzone->tm_isdst]); else tzinfo->tzname_daylight = NULL; tzinfo->utc_offset = curzone->tm_gmtoff; #else tzinfo->tzname_normal = NULL; tzinfo->tzname_daylight = NULL; tzinfo->utc_offset = 0; #endif tzinfo->daylight = curzone->tm_isdst; if (tz_env_value) setenv ("TZ", tz_env_value, 1); else unsetenv ("TZ"); g_free (tz_env_value); return tzinfo; } void tz_info_free (TzInfo *tzinfo) { g_return_if_fail (tzinfo != NULL); if (tzinfo->tzname_normal) g_free (tzinfo->tzname_normal); 250 if (tzinfo->tzname_daylight) g_free (tzinfo->tzname_daylight ); g_free (tzinfo); } struct { const char *orig; const char *dest; } aliases[] = { { "Asia/Istanbul", "Europe/Istanbul" }, /* Istanbul is in both Europe and Asia */ { "Europe/Nicosia", "Asia/Nicosia" }, /* Ditto */ { "EET", "Europe/Istanbul" }, /* Same tz as the 2 above */ { "HST", "Pacific/Honolulu" }, { "WET", "Europe/Brussels" }, /* Other name for the mainland Europe tz */ { "CET", "Europe/Brussels" }, /* ditto */ { "MET", "Europe/Brussels" }, { "Etc/Zulu", "Etc/GMT" }, { "Etc/UTC", "Etc/GMT" }, { "GMT", "Etc/GMT" }, { "Greenwich", "Etc/GMT" }, { "Etc/UCT", "Etc/GMT" }, { "Etc/GMT0", "Etc/GMT" }, { "Etc/GMT+0", "Etc/GMT" }, { "Etc/GMT-0", "Etc/GMT" }, { "Etc/Universal", "Etc/GMT" }, { "PST8PDT", "America/Los_Angeles" }, /* Other name for the Atlantic tz */ { "EST", "America/New_York" }, /* Other name for the Eastern tz */ { "EST5EDT", "America/New_York" }, /* ditto */ { "CST6CDT", "America/Chicago" }, /* Other name for the Central tz */ { "MST", "America/Denver" }, /* Other name for the mountain tz */ { "MST7MDT", "America/Denver" }, /* ditto */ }; static gboolean compare_timezones (const char *a, const char *b) { 251 if (g_str_equal (a, b)) return TRUE; if (strchr (b, ’/’) == NULL) { char *prefixed; prefixed = g_strdup_printf ("/%s", b); if (g_str_has_suffix (a, prefixed)) { g_free (prefixed); return TRUE; } g_free (prefixed); } return FALSE; } char * tz_info_get_clean_name (TzDB *tz_db, const char *tz) { char *ret; const char *timezone; guint i; gboolean replaced; /* Remove useless prefixes */ if (g_str_has_prefix (tz, "right/")) tz = tz + strlen ("right/"); else if (g_str_has_prefix (tz, "posix/")) tz = tz + strlen ("posix/"); /* Here start the crazies */ replaced = FALSE; for (i = 0; i < G_N_ELEMENTS (aliases); i++) { if (compare_timezones (tz, aliases[i].orig)) { replaced = TRUE; timezone = aliases[i].dest; break; } } /* Try again! */ if (!replaced) { 252 /* Ignore crazy solar times from the ’80s */ if (g_str_has_prefix (tz, "Asia/Riyadh") || g_str_has_prefix (tz, "Mideast/Riyadh")) { timezone = "Asia/Riyadh"; replaced = TRUE; } } if (!replaced) timezone = tz; ret = g_hash_table_lookup (tz_db->backward, timezone); if (ret == NULL) return g_strdup (timezone); return g_strdup (ret); } /* ----------------- * * Private functions * * ----------------- */ static gchar * tz_data_file_get (void) { gchar *file; file = g_strdup (TZ_DATA_FILE); return file; } static float convert_pos (gchar *pos, int digits) { gchar whole[10]; gchar *fraction; gint i; float t1, t2; if (!pos || strlen(pos) < 4 || digits > 9) return 0.0; for (i = 0; i < digits + 1; i++) whole[i] = pos[i]; whole[i] = ’\0’; fraction = pos + digits + 1; 253 t1 = g_strtod (whole, NULL); t2 = g_strtod (fraction, NULL); if (t1 >= 0.0) return t1 + t2/pow (10.0, strlen(fraction)); else return t1 - t2/pow (10.0, strlen(fraction)); } #if 0 /* Currently not working */ static void free_tzdata (TzLocation *tz) { if (tz->country) g_free(tz->country); if (tz->zone) g_free(tz->zone); if (tz->comment) g_free(tz->comment); g_free(tz); } #endif static int compare_country_names (const void *a, const void *b) { const TzLocation *tza = * (TzLocation **) a; const TzLocation *tzb = * (TzLocation **) b; return strcmp (tza->zone, tzb->zone); } static void sort_locations_by_country (GPtrArray *locations) { qsort (locations->pdata, locations->len, sizeof (gpointer), compare_country_names); } 254 static void load_backward_tz (TzDB *tz_db) { GError *error = NULL; char **lines, *contents; guint i; tz_db->backward = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); if (g_file_get_contents (GNOME_INTERNET_RADIO_LOCATOR_DATADIR "/stations/backward", &contents, NULL, &error) == FALSE) { g_warning ("Failed␣to␣load␣’backward’␣file:␣%s", error-> message); return; } lines = g_strsplit (contents, "\n", -1); g_free (contents); for (i = 0; lines[i] != NULL; i++) { char **items; guint j; char *real, *alias; if (g_ascii_strncasecmp (lines[i], "Link\t", 5) != 0) continue; items = g_strsplit (lines[i], "\t", -1); real = NULL; alias = NULL; /* Skip the "Link" part */ for (j = 1; items[j] != NULL; j++) { if (items[j][0] == ’\0’) continue; if (real == NULL) { real = items[j]; continue; } alias = items[j]; break; 255 } if (real == NULL || alias == NULL) g_warning ("Could␣not␣parse␣line:␣%s", lines[i]); /* We don’t need more than one name for it */ if (g_str_equal (real, "Etc/UTC") || g_str_equal (real, "Etc/UCT")) real = "Etc/GMT"; g_hash_table_insert (tz_db->backward, g_strdup (alias), g_strdup (real)); g_strfreev (items); } g_strfreev (lines); } 36.12 gnome-internet-radio-locator-gui.h /* $Id$ */ #ifndef GNOME_INTERNET_RADIO_LOCATOR_GUI_H #define GNOME_INTERNET_RADIO_LOCATOR_GUI_H GtkWidget *create_gnome_internet_radio_locator_app(void); GtkWidget *create_listeners_selector(char *selected_listener_uri , char *filename); GtkWidget *create_stations_selector(char *selected_station_uri, char *filename); GtkWidget *create_streams_selector(char *selected_streams_uri, char *filename); GtkWidget *create_search_selector(void); GtkWidget *create_new_station_selector(char *location); GtkWidget *create_gnome_internet_radio_locator_app(void); 256 #endif /* GNOME_INTERNET_RADIO_LOCATOR_GUI_H */ 36.13 gnome-internet-radio-locator.h /* $Id$ * * GNOME Internet Radio Locator * * Copyright (C) 2014-2019 Aamot Software * * Author: Ole Aamot * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License , or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef GNOME_INTERNET_RADIO_LOCATOR_H #define GNOME_INTERNET_RADIO_LOCATOR_H 1 257 #include #include typedef enum { GNOME_INTERNET_RADIO_LOCATOR_CHANNELS_MONO = 0x0001, GNOME_INTERNET_RADIO_LOCATOR_CHANNELS_STEREO = 0x0002, GNOME_INTERNET_RADIO_LOCATOR_CHANNELS_5_1 = 0x0005, GNOME_INTERNET_RADIO_LOCATOR_CHANNELS_NONE = 0xffff } GNOMEInternetRadioLocatorChannels; typedef enum { GNOME_INTERNET_RADIO_LOCATOR_STREAM_SHOUTCAST = 0x0001, GNOME_INTERNET_RADIO_LOCATOR_STREAM_OGG = 0x0002, GNOME_INTERNET_RADIO_LOCATOR_STREAM_AAC = 0x0003 } GNOMEInternetRadioLocatorStreamType; typedef enum { GNOME_INTERNET_RADIO_LOCATOR_STREAM_PLAYER = 0x0001, GNOME_INTERNET_RADIO_LOCATOR_STREAM_RECORD = 0x0002 } GNOMEInternetRadioLocatorHelperType; #include "gnome-internet-radio-locator-listener.h" #include "gnome-internet-radio-locator-program.h" #include "gnome-internet-radio-locator-runners.h" #include "gnome-internet-radio-locator-streams.h" #include "gnome-internet-radio-locator-station.h" #if GNOME_INTERNET_RADIO_LOCATOR_DEBUG == 0 #define GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(x...) g_message(x ) #else #define GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG(x...) #endif #define GNOME_INTERNET_RADIO_LOCATOR_RECORD_TRUE 1 #define GNOME_INTERNET_RADIO_LOCATOR_RECORD_FALSE 0 #define GNOME_INTERNET_RADIO_LOCATOR_PLAYER_TRUE 1 #define GNOME_INTERNET_RADIO_LOCATOR_PLAYER_FALSE 0 gchar *str_channels (GNOMEInternetRadioLocatorChannels type); void show_error(gchar * msg); void statusbar_send_msg(const char *a, ...); 258 void appbar_send_msg(const char *a, ...); gint gnome_internet_radio_locator_archive_new(gchar *title, gchar *file, gchar *codec); /* Fetcher for the channels */ void gnome_internet_radio_locator_helper_run(char *url, char * name, GNOMEInternetRadioLocatorStreamType type, GNOMEInternetRadioLocatorHelperType gnome_internet_radio_locator); void on_search_button_clicked(GtkWidget * button, gpointer user_data); void on_listen_button_clicked(GtkWidget * button, gpointer user_data); void on_record_button_clicked(GtkWidget * button, gpointer user_data); void on_stop_button_clicked(GtkWidget *a, gpointer user_data); void on_next_station_click(GtkWidget *, gpointer user_data); void on_new_station_clicked(GtkWidget *a, gpointer user_data); void on_new_station_selector_changed(GtkWidget *a, gpointer user_data); void on_previous_station_click(GtkWidget *, gpointer user_data); void on_listeners_selector_button_clicked(GtkWidget *, gpointer user_data); void on_listeners_selector_changed(GtkWidget * a, gpointer user_data); void on_programs_selector_button_clicked(GtkWidget *, gpointer user_data); void on_programs_selector_changed(GtkWidget * a, gpointer user_data); void on_stations_selector_button_clicked(GtkWidget *, gpointer user_data); void on_stations_selector_changed(GtkWidget * a, gpointer user_data); void on_streams_selector_button_clicked(GtkWidget *, gpointer user_data); void on_streams_selector_changed(GtkWidget * a, gpointer user_data); void quit_app(GtkWidget *, gpointer user_data); void about_app(GtkWidget *, gpointer user_data); void about_listener(GtkWidget *, gpointer user_data); void about_station(GSimpleAction *simple, GVariant *parameter, gpointer user_data); 259 void about_program(GSimpleAction *simple, GVariant *parameter, gpointer user_data); gboolean on_search_matches(GtkEntryCompletion *widget, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data); struct _GNOMEInternetRadioLocatorData { GtkImage *pixmap; GtkProgressBar *progress; GSettings *settings; GtkAboutDialog *window; GtkStatusbar *statusbar; GtkWidget *player_window; GtkWidget *about_station; gchar *selected_archive_file; GNOMEInternetRadioLocatorListenerInfo *selected_listener; gchar *selected_listener_uri; gchar *selected_listener_name; gchar *selected_listener_location; gchar *selected_listener_band; gchar *selected_listener_description; GNOMEInternetRadioLocatorProgramInfo *selected_program; gchar *selected_program_uri; gchar *selected_program_name; gchar *selected_program_location; gchar *selected_program_band; gchar *selected_program_description; GNOMEInternetRadioLocatorRunnersInfo *selected_runners; gint timeout_id; gint current_station_number; GNOMEInternetRadioLocatorStationInfo *previous_station; GNOMEInternetRadioLocatorStationInfo *selected_station; gchar *selected_station_uri; gchar *selected_station_name; gchar *selected_station_location; gchar *selected_station_band; gchar *selected_station_description; gchar *selected_station_website; gint selected_bitrate; GNOMEInternetRadioLocatorStreamsInfo *selected_streams; gchar *selected_streams_mime; gchar *selected_streams_uri; 260 gchar *selected_streams_codec; gchar *selected_streams_samplerate; gchar *selected_streams_stations; gchar *selected_streams_bitrate; GNOMEInternetRadioLocatorChannels selected_streams_channels; gint selected_samplerate; GdkPixbuf *icon; gint player_status; GPid player_pid; GSubprocess *player_subprocess; GSubprocess *record_subprocess; GSubprocessLauncher *player_launcher; GSubprocessLauncher *record_launcher; gint record_status; GPid record_pid; gint station_count; gint stream_count; GMainLoop *player_loop; GMainLoop *record_loop; }; typedef struct _GNOMEInternetRadioLocatorData GNOMEInternetRadioLocatorData; void about_station(GSimpleAction *simple, GVariant *parameter, gpointer user_data); extern GNOMEInternetRadioLocatorData * gnome_internet_radio_locator; extern GList *gnome_internet_radio_locator_listeners; extern GList *gnome_internet_radio_locator_programs; extern GList *gnome_internet_radio_locator_stations; extern GList *gnome_internet_radio_locator_streams; #endif /* GNOME_INTERNET_RADIO_LOCATOR_H */ 36.14 gnome-internet-radio-locator-keys.h 261 /* $Id$ * * GNOME Internet Radio Locator * * Copyright (C) 2014-2019 Aamot Software * * Author: Ole Aamot * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License , or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef GNOME_INTERNET_RADIO_LOCATOR_KEYS_H #define GNOME_INTERNET_RADIO_LOCATOR_KEYS_H #define GNOME_INTERNET_RADIO_LOCATOR_DOMAIN "org.gnome.gnome- internet-radio-locator" #define GNOME_INTERNET_RADIO_LOCATOR_UI GNOME_INTERNET_RADIO_LOCATOR_DOMAIN".ui" #define GNOME_INTERNET_RADIO_LOCATOR_STATION "station" #endif /* GNOME_INTERNET_RADIO_LOCATOR_KEYS_H */ 262 36.15 gnome-internet-radio-locator-listener.h /* $Id$ * * GNOME Internet Radio Locator * * Copyright (C) 2014-2019 Aamot Software * * Author: Ole Aamot * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License , or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef GNOME_INTERNET_RADIO_LOCATOR_LISTENER_H #define GNOME_INTERNET_RADIO_LOCATOR_LISTENER_H #include #include #include "gnome-internet-radio-locator.h" 263 typedef struct _GNOMEInternetRadioLocatorListenerInfo GNOMEInternetRadioLocatorListenerInfo; typedef struct _GNOMEInternetRadioLocatorLocationInfo GNOMEInternetRadioLocatorLocationInfo; struct _GNOMEInternetRadioLocatorListenerInfo { gchar *id; gchar *location; gchar *mail; gchar *name; gchar *pass; gchar *uri; gchar *band; gchar *description; GNOMEInternetRadioLocatorLocationInfo *locationinfo; GNOMEInternetRadioLocatorListenerInfo *next; }; struct _GNOMEInternetRadioLocatorLocationInfo { gchar *name; gchar *link; gchar *glat; gchar *glon; gchar *grad; gchar *vote; gchar *rack; }; GNOMEInternetRadioLocatorListenerInfo * gnome_internet_radio_locator_listener_load_from_file( GNOMEInternetRadioLocatorListenerInfo * head, char *filename); GNOMEInternetRadioLocatorListenerInfo * gnome_internet_radio_locator_listener_load_from_http( GNOMEInternetRadioLocatorListenerInfo * head, gpointer data); #endif /* GNOME_INTERNET_RADIO_LOCATOR_LISTENER_H */ 36.16 gnome-internet-radio-locator-markers.h 264 /* $id$ * * GNOME Internet Radio Locator * * Copyright (C) 2019 Aamot Software * * Author: Ole Aamot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License , or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /* * Copyright (C) 2008 Pierre-Luc Beaudoin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, 265 * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #ifndef GNOME_INTERNET_RADIO_LOCATOR_MARKERS_H #define GNOME_INTERNET_RADIO_LOCATOR_MARKERS_H 1 ChamplainMarkerLayer *create_marker_layer (ChamplainView *view, ChamplainPathLayer **path); void marker_function (ChamplainMarker *self, gdouble dx, gdouble dy, ClutterEvent *event, gpointer user_data); #endif 36.17 gnome-internet-radio-locator-player.h /* $Id$ * * GNOME Internet Radio Locator * * Copyright (C) 2014-2019 Aamot Software * * Author: Ole Aamot * * This program is free software; you can redistribute it and/or modify 266 * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License , or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef GNOME_INTERNET_RADIO_LOCATOR_PLAYER_H #define GNOME_INTERNET_RADIO_LOCATOR_PLAYER_H #include #include typedef struct { gchar **uris; guint num_uris; gint cur_idx; GstPlayer *player; GstState desired_state; gboolean repeat; GMainLoop *loop; } GstPlay; void play_uri (GstPlayer *player, const gchar * next_uri); void gnome_internet_radio_locator_player_new (GstPlayer * player , const gchar * next_uri); 267 void gnome_internet_radio_locator_player_new (GstPlayer * player , const gchar * next_uri); void gnome_internet_radio_locator_player_quit (GstPlayer *player ); void gnome_internet_radio_locator_player_pause (GstPlayer * player); void gnome_internet_radio_locator_player_stop (GstPlayer *player ); static gdouble get_volume (GtkWidget *widget, GstPlay *play); #endif /* GNOME_INTERNET_RADIO_LOCATOR_PLAYER_H */ 36.18 gnome-internet-radio-locator-kb.h /* GStreamer command line playback testing utility - keyboard handling helpers * * Copyright (C) 2013 Tim-Philipp Mller * Copyright (C) 2013 Centricular Ltd * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. 268 * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef __GST_PLAY_KB_INCLUDED__ #define __GST_PLAY_KB_INCLUDED__ #include #define GST_PLAY_KB_ARROW_UP "\033[A" #define GST_PLAY_KB_ARROW_DOWN "\033[B" #define GST_PLAY_KB_ARROW_RIGHT "\033[C" #define GST_PLAY_KB_ARROW_LEFT "\033[D" typedef void (*GstPlayKbFunc) (const gchar * kb_input, gpointer user_data); gboolean gst_play_kb_set_key_handler (GstPlayKbFunc kb_func, gpointer user_data); #endif /* __GST_PLAY_KB_INCLUDED__ */ 36.19 gnome-internet-radio-locator-player-renderer.h /* GStreamer * * Copyright (C) 2015 Sebastian Dr ge * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * 269 * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef __GTK_VIDEO_RENDERER_H__ #define __GTK_VIDEO_RENDERER_H__ #include #include G_BEGIN_DECLS typedef struct _GstPlayerGtkVideoRenderer GstPlayerGtkVideoRenderer; typedef struct _GstPlayerGtkVideoRendererClass GstPlayerGtkVideoRendererClass; #define GST_TYPE_PLAYER_GTK_VIDEO_RENDERER ( gst_player_gtk_video_renderer_get_type ()) #define GST_IS_PLAYER_GTK_VIDEO_RENDERER(obj) ( G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PLAYER_GTK_VIDEO_RENDERER)) #define GST_IS_PLAYER_GTK_VIDEO_RENDERER_CLASS(klass) ( G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PLAYER_GTK_VIDEO_RENDERER)) #define GST_PLAYER_GTK_VIDEO_RENDERER_GET_CLASS(obj) ( G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_PLAYER_GTK_VIDEO_RENDERER, GstPlayerGtkVideoRendererClass)) #define GST_PLAYER_GTK_VIDEO_RENDERER(obj) ( G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PLAYER_GTK_VIDEO_RENDERER, GstPlayerGtkVideoRenderer )) 270 #define GST_PLAYER_GTK_VIDEO_RENDERER_CLASS(klass) ( G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_PLAYER_GTK_VIDEO_RENDERER, GstPlayerGtkVideoRendererClass)) #define GST_PLAYER_GTK_VIDEO_RENDERER_CAST(obj) (( GstPlayerGtkVideoRenderer*)(obj)) GType gst_player_gtk_video_renderer_get_type (void); GstPlayerVideoRenderer * gst_player_gtk_video_renderer_new (void ); GtkWidget * gst_player_gtk_video_renderer_get_widget ( GstPlayerGtkVideoRenderer * self); G_END_DECLS #endif /* __GTK_VIDEO_RENDERER_H__ */ 36.20 gnome-internet-radio-locator-player-resourcer.h #ifndef __RESOURCE_as_H__ #define __RESOURCE_as_H__ #include extern GResource *as_get_resource (void); #endif 36.21 gnome-internet-radio-locator-program.h /* $Id$ * 271 * GNOME Internet Radio Locator * * Copyright (C) 2014-2019 Aamot Software * * Author: Ole Aamot * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License , or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef GNOME_INTERNET_RADIO_LOCATOR_PROGRAM_H #define GNOME_INTERNET_RADIO_LOCATOR_PROGRAM_H #include #include "gnome-internet-radio-locator.h" typedef struct _GNOMEInternetRadioLocatorProgramInfo GNOMEInternetRadioLocatorProgramInfo; typedef struct _GNOMEInternetRadioLocatorArchiveInfo GNOMEInternetRadioLocatorArchiveInfo; struct _GNOMEInternetRadioLocatorProgramInfo { GtkWidget *widget; gchar *id; gchar *name; gchar *rank; 272 gchar *type; gchar *band; gchar *frequency; gchar *location; gchar *description; gchar *bitrate; gchar *samplerate; gchar *uri; /* gchar *category; */ GNOMEInternetRadioLocatorArchiveInfo *archive; GNOMEInternetRadioLocatorProgramInfo *next; GNOMEInternetRadioLocatorProgramInfo *prev; }; struct _GNOMEInternetRadioLocatorArchiveInfo { gchar *id; gchar *name; GNOMEInternetRadioLocatorArchiveInfo *next; gchar *mimetype; glong bitrate; glong samplerate; GNOMEInternetRadioLocatorChannels channels; gchar *uri; }; GNOMEInternetRadioLocatorProgramInfo * gnome_internet_radio_locator_program_new ( GNOMEInternetRadioLocatorProgramInfo * head, gchar *id, gchar *name, gchar *date, gchar *time, gchar *file); void gnome_internet_radio_locator_program_free( GNOMEInternetRadioLocatorProgramInfo * info); GNOMEInternetRadioLocatorProgramInfo * gnome_internet_radio_locator_program_load_from_file( GNOMEInternetRadioLocatorProgramInfo * head, char *filename); GNOMEInternetRadioLocatorProgramInfo * gnome_internet_radio_locator_program_load_from_http( GNOMEInternetRadioLocatorProgramInfo * head, gpointer data); 273 #endif /* GNOME_INTERNET_RADIO_LOCATOR_PROGRAM_H */ 36.22 gnome-internet-radio-locator-runners.h /* $Id$ * * GNOME Internet Radio Locator * * Copyright (C) 2014-2019 Aamot Software * * Author: Ole Aamot * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License , or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef GNOME_INTERNET_RADIO_LOCATOR_RUNNERS_H #define GNOME_INTERNET_RADIO_LOCATOR_RUNNERS_H 274 typedef struct _GNOMEInternetRadioLocatorRunnersInfo GNOMEInternetRadioLocatorRunnersInfo; struct _GNOMEInternetRadioLocatorRunnersInfo { GtkWidget *widget; GMutex *mutex; pid_t pid; gchar *name; gchar *date; gchar *time; gchar *file; gchar *command; }; GNOMEInternetRadioLocatorRunnersInfo * gnome_internet_radio_locator_runners_new (pid_t pid, gchar *name, gchar *date, gchar *time, gchar *file); void gnome_internet_radio_locator_runners_free( GNOMEInternetRadioLocatorRunnersInfo * info); void gnome_internet_radio_locator_runners_mutex_get( GNOMEInternetRadioLocatorRunnersInfo *info); void gnome_internet_radio_locator_runners_mutex_release( GNOMEInternetRadioLocatorRunnersInfo *info); void gnome_internet_radio_locator_runners_mutex_lock( GNOMEInternetRadioLocatorRunnersInfo *info); void gnome_internet_radio_locator_runners_mutex_unlock( GNOMEInternetRadioLocatorRunnersInfo *info); void cb_record_execute(GtkButton *button); #endif /* GNOME_INTERNET_RADIO_LOCATOR_RUNNERS_H */ 36.23 gnome-internet-radio-locator-station.h 275 /* $Id$ * * GNOME Internet Radio Locator * * Copyright (C) 2014-2019 Aamot Software * * Author: Ole Aamot * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License , or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef GNOME_INTERNET_RADIO_LOCATOR_STATION_H #define GNOME_INTERNET_RADIO_LOCATOR_STATION_H #include "gnome-internet-radio-locator.h" typedef struct _GNOMEInternetRadioLocatorStationInfo GNOMEInternetRadioLocatorStationInfo; typedef struct _GNOMEInternetRadioLocatorStreamInfo GNOMEInternetRadioLocatorStreamInfo; typedef enum { STATION_LANG = 11, STATION_ID = 10, STATION_NAME = 0, 276 STATION_RANK = 7, STATION_TYPE = 6, STATION_BAND = 5, STATION_FREQUENCY = 4, STATION_LOCATION = 1, STATION_DESCRIPTION = 3, STATION_BITRATE = 8, STATION_SAMPLERATE = 9, STATION_URI = 2 } GNOMEInternetRadioLocatorStationColumn; struct _GNOMEInternetRadioLocatorStationInfo { GtkWidget *widget; gchar *id; gchar *name; gchar *rank; gchar *type; gchar *band; gchar *frequency; gchar *location; gchar *description; gchar *bitrate; gchar *samplerate; gchar *uri; gchar *lang; /* gchar *category; */ GNOMEInternetRadioLocatorStreamInfo *stream; GNOMEInternetRadioLocatorStationInfo *next; GNOMEInternetRadioLocatorStationInfo *prev; }; struct _GNOMEInternetRadioLocatorStreamInfo { gchar *id; gchar *name; GNOMEInternetRadioLocatorStreamInfo *next; gchar *mimetype; glong bitrate; glong samplerate; GNOMEInternetRadioLocatorChannels channels; gchar *uri; }; void show_error(gchar * msg); 277 void gnome_internet_radio_locator_station_free( GNOMEInternetRadioLocatorStationInfo * info); GNOMEInternetRadioLocatorStationInfo * gnome_internet_radio_locator_station_load_from_file( GNOMEInternetRadioLocatorStationInfo * head, char *filename); GNOMEInternetRadioLocatorStationInfo * gnome_internet_radio_locator_station_load_from_http( GNOMEInternetRadioLocatorStationInfo * head, gpointer data); void gnome_internet_radio_locator_helper_run(char *url, char * name, GNOMEInternetRadioLocatorStreamType type, GNOMEInternetRadioLocatorHelperType gnome_internet_radio_locator); gint gnome_internet_radio_locator_station_update ( GNOMEInternetRadioLocatorStationInfo *head, gchar * station_band, gchar *station_description, gchar *station_name , gchar *station_location, gchar *station_uri, gchar * station_website); #endif /* GNOME_INTERNET_RADIO_LOCATOR_STATION_H */ 36.24 gnome-internet-radio-locator-stations-map.h /* $Id$ * * GNOME Internet Radio Locator * * Copyright (C) 2015-2019 Aamot Software * * Author: Ole Aamot * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License , or 278 * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * */ /* * Essential parts of the source code below was based on * gnome-control-center/panels/datetime/cc-timezone-map.h * * Copyright (C) 2010 Intel, Inc * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License , or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * * Author: Thomas Wood 279 * */ #ifndef _GNOME_INTERNET_RADIO_LOCATOR_STATIONS_MAP_H #define _GNOME_INTERNET_RADIO_LOCATOR_STATIONS_MAP_H #include #include #include "gnome_internet_radio_locator-tz.h" G_BEGIN_DECLS #define GNOME_INTERNET_RADIO_LOCATOR_TYPE_STATIONS_MAP gnome_internet_radio_locator_stations_map_get_type() #define GNOME_INTERNET_RADIO_LOCATOR_STATIONS_MAP(obj) \ (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ GNOME_INTERNET_RADIO_LOCATOR_TYPE_STATIONS_MAP, GNOMEInternetRadioLocatorStationsMap)) #define GNOME_INTERNET_RADIO_LOCATOR_STATIONS_MAP_CLASS(klass) \ (G_TYPE_CHECK_CLASS_CAST ((klass), \ GNOME_INTERNET_RADIO_LOCATOR_TYPE_STATIONS_MAP, GNOMEInternetRadioLocatorStationsMapClass)) #define GNOME_INTERNET_RADIO_LOCATOR_IS_STATIONS_MAP(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ GNOME_INTERNET_RADIO_LOCATOR_TYPE_STATIONS_MAP)) #define GNOME_INTERNET_RADIO_LOCATOR_IS_STATIONS_MAP_CLASS(klass ) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), \ GNOME_INTERNET_RADIO_LOCATOR_TYPE_STATIONS_MAP)) #define GNOME_INTERNET_RADIO_LOCATOR_STATIONS_MAP_GET_CLASS(obj) \ (G_TYPE_INSTANCE_GET_CLASS ((obj), \ GNOME_INTERNET_RADIO_LOCATOR_TYPE_STATIONS_MAP, GNOMEInternetRadioLocatorStationsMapClass)) typedef struct _GNOMEInternetRadioLocatorStationsMap GNOMEInternetRadioLocatorStationsMap; 280 typedef struct _GNOMEInternetRadioLocatorStationsMapClass GNOMEInternetRadioLocatorStationsMapClass; typedef struct _GNOMEInternetRadioLocatorStationsMapPrivate GNOMEInternetRadioLocatorStationsMapPrivate; struct _GNOMEInternetRadioLocatorStationsMap { GtkWidget parent; GNOMEInternetRadioLocatorStationsMapPrivate *priv; }; struct _GNOMEInternetRadioLocatorStationsMapClass { GtkWidgetClass parent_class; }; GType gnome_internet_radio_locator_stations_map_get_type (void) G_GNUC_CONST; GNOMEInternetRadioLocatorStationsMap * gnome_internet_radio_locator_stations_map_new (void); gboolean gnome_internet_radio_locator_stations_map_set_location (GNOMEInternetRadioLocatorStationsMap *map, const gchar *timezone); void gnome_internet_radio_locator_stations_map_set_bubble_text ( GNOMEInternetRadioLocatorStationsMap *map, const gchar *text); TzLocation * gnome_internet_radio_locator_stations_map_get_location ( GNOMEInternetRadioLocatorStationsMap *map); G_END_DECLS #endif /* _GNOME_INTERNET_RADIO_LOCATOR_STATIONS_MAP_H */ 36.25 gnome-internet-radio-locator-streams.h 281 /* $Id$ * * GNOME Internet Radio Locator * * Copyright (C) 2014-2019 Aamot Software * * Author: Ole Aamot * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License , or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef GNOME_INTERNET_RADIO_LOCATOR_STREAMS_H #define GNOME_INTERNET_RADIO_LOCATOR_STREAMS_H #include "gnome-internet-radio-locator.h" typedef struct _GNOMEInternetRadioLocatorStreamsInfo GNOMEInternetRadioLocatorStreamsInfo; typedef struct _GNOMEInternetRadioLocatorEncoderInfo GNOMEInternetRadioLocatorEncoderInfo; struct _GNOMEInternetRadioLocatorStreamsInfo { 282 GtkWidget *widget; gchar *mime; gchar *uri; gchar *codec; gchar *samplerate; gchar *streams; gchar *bitrate; GNOMEInternetRadioLocatorChannels channels; GNOMEInternetRadioLocatorEncoderInfo *encoder; GNOMEInternetRadioLocatorStreamsInfo *next; GNOMEInternetRadioLocatorStreamsInfo *prev; }; struct _GNOMEInternetRadioLocatorEncoderInfo { gchar *id; gchar *name; GNOMEInternetRadioLocatorEncoderInfo *next; gchar *mimetype; glong bitrate; glong samplerate; GNOMEInternetRadioLocatorChannels channels; gchar *uri; }; GNOMEInternetRadioLocatorStreamsInfo * gnome_internet_radio_locator_streams_new ( GNOMEInternetRadioLocatorStreamsInfo * head, gchar *mime, gchar *uri, gchar *codec, gchar *samplerate, gchar *channels, gchar *bitrate); void gnome_internet_radio_locator_streams_free( GNOMEInternetRadioLocatorStreamsInfo * info); GNOMEInternetRadioLocatorStreamsInfo * gnome_internet_radio_locator_streams_load_from_file( GNOMEInternetRadioLocatorStreamsInfo * head, char *filename); GNOMEInternetRadioLocatorStreamsInfo * gnome_internet_radio_locator_streams_load_from_http( GNOMEInternetRadioLocatorStreamsInfo * head, gpointer data); 283 #endif /* GNOME_INTERNET_RADIO_LOCATOR_STREAMS_H */ 36.26 gnome-internet-radio-locator-tz.h /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic- offset: 8 -*- */ /* $Id$ * * GNOME Internet Radio Locator * * Copyright (C) 2015-2019 Aamot Software * * Author: Ole Aamot * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License , or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * */ 284 /* * Essential parts of the source code below was based on * gnome-control-center/panels/datetime/tz.h * */ /* Generic timezone utilities. * * Copyright (C) 2000-2001 Ximian, Inc. * * Authors: Hans Petter Jansson * * Largely based on Michael Fulbright’s work on Anaconda. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License , or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ #ifndef _E_TZ_H #define _E_TZ_H #include #ifndef __sun # define TZ_DATA_FILE "/usr/share/zoneinfo/zone.tab" #else 285 # define TZ_DATA_FILE "/usr/share/lib/zoneinfo/tab/zone_sun.tab " #endif typedef struct _TzDB TzDB; typedef struct _TzLocation TzLocation; typedef struct _TzInfo TzInfo; struct _TzDB { GPtrArray *locations; GHashTable *backward; }; struct _TzLocation { gchar *country; gdouble latitude; gdouble longitude; gchar *zone; gchar *comment; gdouble dist; /* distance to clicked point for comparison */ }; /* see the glibc info page information on time zone information */ /* tzname_normal is the default name for the timezone */ /* tzname_daylight is the name of the zone when in daylight savings */ /* utc_offset is offset in seconds from utc */ /* daylight if non-zero then location obeys daylight savings */ struct _TzInfo { gchar *tzname_normal; gchar *tzname_daylight; glong utc_offset; gint daylight; }; 286 TzDB *tz_load_db (void); void tz_db_free (TzDB *db); char * tz_info_get_clean_name (TzDB *tz_db, const char *tz); GPtrArray *tz_get_locations (TzDB *db); void tz_location_get_position (TzLocation *loc, double *longitude, double *latitude); char *tz_location_get_country (TzLocation *loc); gchar *tz_location_get_zone (TzLocation *loc); gchar *tz_location_get_comment (TzLocation *loc); glong tz_location_get_utc_offset (TzLocation *loc); gint tz_location_set_locally (TzLocation *loc); TzInfo *tz_info_from_location (TzLocation *loc); void tz_info_free (TzInfo *tz_info); #endif 287 288 Chapter 37 Source Code in gnome-radio-0.2.0.tar.gz http://www.gnomeradio.org/0.2/gnome-radio-0.2.0.tar.gz 37.1 gnome-radio-file.c #include #include #include "gnome-radio-file.h" extern GList *radio_stations; #if 0 static void gnome_radio_file_parser (RadioInfo *info, xmlDocPtr doc, xmlNodePtr cur) { xmlNodePtr sub; g_return_if_fail (info != NULL); g_return_if_fail (doc != NULL); g_return_if_fail (cur != NULL); info->uri = (gchar *) xmlNodeGetProp (cur, (const xmlChar *) "uri"); 289 sub = cur->xmlChildrenNode; while (sub != NULL) { if ((!strcasecmp (sub->name, (const xmlChar *) "uri"))) { info->uri = (gchar *) xmlNodeListGetString (doc, sub ->xmlChildrenNode, 1); g_print ("station:%s\n", info->uri); } if ((!strcasecmp (sub->name, (const xmlChar *) "location "))) { LocationInfo *location = g_new0 (LocationInfo, 1); info->location = location; info->location->city = (gchar *) xmlNodeListGetString (doc, sub->xmlChildrenNode, 1); info->location->lat = (gchar *) xmlNodeGetProp (doc, sub->xmlChildrenNode); info->location->lon = (gchar *) xmlNodeGetProp (doc, sub->xmlChildrenNode); g_print ("location:city:%s\n", info->location->city) ; g_print ("location:lat:%d\n", info->location->lat); g_print ("location:lon:%d\n", info->location->lon); } if ((!strcasecmp (sub->name, (const xmlChar *) "stream") )) { StreamInfo *stream = g_new0 (StreamInfo, 1); info->stream = stream; info->stream->uri = (gchar *) xmlNodeGetProp (doc, sub->xmlChildrenNode); } sub = sub->next; } return; } RadioInfo * gnome_radio_file_loader (RadioInfo *head, char *filename) { xmlDocPtr doc = NULL; xmlNodePtr cur = NULL; RadioInfo *curr = NULL; RadioInfo *list = NULL; 290 g_return_val_if_fail (filename != NULL, NULL); doc = xmlReaderForFile (filename, NULL, 0); if (doc == NULL) { perror ("xmlParseFile"); xmlDocFree (doc); return NULL; } cur = xmlDocGetRootElement (doc); if (cur == NULL) { fprintf (stderr, "Empty␣document\n"); xmlDocFree (doc); return NULL; } if (strcasecmp (cur->name, (const xmlChar *) "radio")) { fprintf (stderr, "Document␣of␣wrong␣type,␣root␣node␣!=␣radio\n"); xmlDocFree (doc); return NULL; } cur = cur->xmlChildrenNode; while (cur != NULL) { if ((!strcasecmp (cur->name, (const xmlChar *) "station" ))) { curr = g_new0(RadioInfo, 1); gnome_radio_file_parser (curr, doc, cur); curr->next = head; head = curr; list = head; radio_stations = g_list_append (radio_stations, ( RadioInfo *)list); g_free (curr); } curr = curr->next; } xmlDocFree (doc); return curr; } #endif 37.2 gnome-radio-file.h 291 #ifndef GNOME_RADIO_FILE_H #define GNOME_RADIO_FILE_H 1 #include #include #include typedef struct _LocationInfo LocationInfo; typedef struct _RadioInfo RadioInfo; typedef struct _StreamInfo StreamInfo; typedef struct _RadioWindow RadioWindow; typedef struct _RadioOscilloscope RadioOscilloscope; struct _RadioOscilloscope { GtkWidget *window; struct timeval *tv; struct timezone *tz; GstPlayer *player; gchar *window_title; gchar *text; gchar *uri; }; struct _RadioWindow { GtkWidget *window; gchar *window_title; gchar *text; gchar *uri; }; struct _LocationInfo { double *lat; double *lon; gchar *city; }; struct _RadioInfo { gchar *uri; LocationInfo *location; StreamInfo *stream; RadioInfo *next; 292 RadioInfo *prev; }; struct _StreamInfo { gchar *uri; StreamInfo *next; StreamInfo *prev; }; #endif /* GNOME_RADIO_FILE_H */ 37.3 gnome-radio-main.c #include #include #include #include #include #include #include #include "gnome-radio-file.h" #include "gnome-radio-vosc.h" #define RADIO_MARKER_SIZE 10 #if 0 static void radio_window_init (RadioWindow *window) { gtk_widget_init_template (GTK_WIDGET (window)); } static void radio_window_class_init (RadioWindowClass *class) { gtk_widget_class_set_template_from_resource ( GTK_WIDGET_CLASS (class), "/org/gtk/gnome-radio/window.ui"); } 293 static void search_text_changed (GtkEntry *entry, RadioWindow *window) { RadioWindow *priv; const gchar *text; GtkWidget *tab; GtkWidget *view; GtkTextBuffer *buffer; GtkTextIter start, match_start, match_end; text = gtk_entry_get_text (entry); if (text[0] == ’\0’) return; priv = radio_window_get_instance_private (window); tab = gtk_stack_get_visible_child (GTK_STACK (priv->stack)); view = gtk_bin_get_child (GTK_BIN (tab)); buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)); /* Very simple-minded search implementation */ gtk_text_buffer_get_start_iter (buffer, &start); if (gtk_text_iter_forward_search (&start, text, GTK_TEXT_SEARCH_CASE_INSENSITIVE, &match_start, &match_end, NULL)) { gtk_text_buffer_select_range (buffer, &match_start, & match_end); gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (view), & match_start, 0.0, FALSE, 0.0, 0.0); } } static void init_radio_window (RadioWindow *window) { gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS ( class), radio_search_changed); } #endif /* gnome-radio draws the radio_marker wth Cairo composed of 1 static filled circle and 1 stroked circle animated as echo. */ static ClutterActor * 294 create_radio_marker (void) { ClutterActor *radio_marker; ClutterActor *bg; ClutterTimeline *timeline; cairo_t *cr; /* Create the marker */ radio_marker = champlain_custom_marker_new (); /* Static filled circle ------------------------------------------ */ bg = clutter_cairo_texture_new (RADIO_MARKER_SIZE, RADIO_MARKER_SIZE); cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE (bg )); cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); cairo_paint(cr); cairo_set_operator (cr, CAIRO_OPERATOR_OVER); /* Draw the circle */ cairo_set_source_rgb (cr, 0, 0, 0); cairo_arc (cr, RADIO_MARKER_SIZE / 2.0, RADIO_MARKER_SIZE / 2.0, RADIO_MARKER_SIZE / 2.0, 0, 2 * M_PI); cairo_close_path (cr); /* Fill the circle */ cairo_set_source_rgba (cr, 0.1, 0.9, 0.1, 1.0); cairo_fill (cr); cairo_destroy (cr); /* Add the circle to the radio_marker */ clutter_container_add_actor (CLUTTER_CONTAINER (radio_marker ), bg); clutter_actor_set_anchor_point_from_gravity (bg, CLUTTER_GRAVITY_CENTER); clutter_actor_set_position (bg, 0, 0); /* Echo circle ----------------------------------------------- */ bg = clutter_cairo_texture_new (2 * RADIO_MARKER_SIZE, 2 * RADIO_MARKER_SIZE); cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE (bg )); /* Draw the circle */ cairo_set_source_rgb (cr, 0, 0, 0); cairo_arc (cr, RADIO_MARKER_SIZE, RADIO_MARKER_SIZE, 0.9 * RADIO_MARKER_SIZE, 0, 2 * M_PI); cairo_close_path (cr); 295 /* Stroke the circle */ cairo_set_line_width (cr, 2.0); cairo_set_source_rgba (cr, 0.1, 0.7, 0.1, 1.0); cairo_stroke (cr); cairo_destroy (cr); /* Add the circle to the radio_marker */ clutter_container_add_actor (CLUTTER_CONTAINER (radio_marker ), bg); clutter_actor_lower_bottom (bg); /* Ensure it is under the previous circle */ clutter_actor_set_position (bg, 0, 0); clutter_actor_set_anchor_point_from_gravity (bg, CLUTTER_GRAVITY_CENTER); /* Animate the echo circle */ timeline = clutter_timeline_new (1000); clutter_timeline_set_loop (timeline, TRUE); clutter_actor_set_opacity (CLUTTER_ACTOR (bg), 255); clutter_actor_set_scale (CLUTTER_ACTOR (bg), 0.5, 0.5); clutter_actor_animate_with_timeline (CLUTTER_ACTOR (bg), CLUTTER_EASE_OUT_SINE, timeline, "opacity", 0, "scale-x", 2.0, "scale-y", 2.0, NULL); clutter_timeline_start (timeline); return radio_marker; } double lat = 21.293352; double lon = -157.839583; typedef struct { ChamplainView *view; ChamplainMarker *radio_marker; } GpsCallbackData; typedef struct { RadioOscilloscope *oscilloscope_visual; } OscilloscopeCallbackData; static gboolean 296 gps_callback (GpsCallbackData *data) { champlain_view_center_on (data->view, lat, lon); champlain_location_set_location (CHAMPLAIN_LOCATION (data-> radio_marker), lat, lon); return TRUE; } gint main (gint argc, gchar **argv) { GstPlayer *player; GtkWidget *window; ChamplainView *view; ClutterActor *actor, *radio_oscilloscope, *radio_marker, * oscilloscope_visual, *stage; ChamplainMarkerLayer *layer; RadioInfo *radioinfo; GpsCallbackData callback_data; /* OscilloscopeCallbackData oscilloscope_data; */ /* VOSCWindow *vosc; */ if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) return 1; /* vosc = (VOSCWindow *)g_new0(VOSCWindow, 1); */ stage = clutter_stage_new (); clutter_stage_set_title (stage, g_strconcat("GNOME␣Radio", " ␣", VERSION, "␣-␣", "http://www.gnomeradio.org/", "␣-␣", "https://wiki.gnome.org/Apps/Radio", NULL)); clutter_actor_set_size (stage, 800, 600); g_signal_connect (stage, "destroy", G_CALLBACK ( clutter_main_quit), NULL); /* Create the map view */ actor = champlain_view_new (); clutter_actor_set_size (CLUTTER_ACTOR (actor), 800, 600); clutter_container_add_actor (CLUTTER_CONTAINER (stage), actor); /* Create the radio_marker layer */ layer = champlain_marker_layer_new_full ( CHAMPLAIN_SELECTION_SINGLE); clutter_actor_show (CLUTTER_ACTOR (layer)); champlain_view_add_layer (CHAMPLAIN_VIEW (actor), CHAMPLAIN_LAYER (layer)); /* Create a radio_marker */ radio_marker = create_radio_marker (); 297 champlain_marker_layer_add_marker (layer, CHAMPLAIN_MARKER ( radio_marker)); /* Create a oscilloscope_visual */ /* oscilloscope_visual = create_oscilloscope_visual (); */ /* gnome_radio_add_visual_oscilloscope (layer, GNOME_RADIO_MARKER (oscilloscope_visual)); */ /* Finish initialising the map view */ g_object_set (G_OBJECT (actor), "zoom-level", 1, "kinetic-mode", TRUE, NULL); champlain_view_center_on (CHAMPLAIN_VIEW (actor), lat, lon); /* Create callback that updates the map periodically */ callback_data.view = CHAMPLAIN_VIEW (actor); callback_data.radio_marker = CHAMPLAIN_MARKER (radio_marker) ; /* oscilloscope_data.view = GNOME_RADIO_VIEW ( radio_oscilloscope); */ /* oscilloscope_data.oscilloscope_visual = GNOME_RADIO_MARKER (oscilloscope_visual); */ /* Create the radio player */ player = gst_player_new (NULL, gst_player_g_main_context_signal_dispatcher_new(NULL)); /* gnome_radio_file_loader (radioinfo, "gnome-radio.xml"); */ gst_player_set_uri (GST_PLAYER (player), "http://khpr-ice. streamguys1.com:80/khpr2"); gst_player_stop (GST_PLAYER (player)); /* Visual Oscillator */ /* vosc->window = gtk_window_new (GTK_WINDOW_TOPLEVEL); */ /* gtk_widget_show_all (vosc->window); */ /* gnome_radio_real(GST_PLAYER (player), CLUTTER_ACTOR ( radio_oscilloscope)); */ /* clutter_container_add_actor (CLUTTER_CONTAINER (stage ), CLUTTER_ACTOR (radio_oscilloscope)); */ gst_player_play(GST_PLAYER (player)); g_timeout_add (1000, (GSourceFunc) gps_callback, & callback_data); /* g_timeout_add (1000, (GSourceFunc) gnome_radio_real, & oscilloscope_data); */ clutter_actor_show (stage); /* clutter_actor_show (radio_oscilloscope); */ clutter_main (); return (0); } 298 New York City Southern California Hawaii 299 300 Part VII Software Packages for i386, x86_64 and amd64 301 Debian GNU/Linux, Fedora and Ubuntu software installation packages of GNOME Internet Radio Locator for the computer hardware architecture i386, x86_64, and amd64. https://www.gnome.org/~ole/debian/gnome-internet-radio-locator_3.0.0-1_i386.deb https://www.gnome.org/~ole/fedora/RPMS/x86_64/gnome-internet-radio-locator-3.0.0-1.fc31.x86_64.rpm https://www.gnome.org/~ole/ubuntu/gnome-internet-radio-locator_3.0.0-1_amd64.deb 303 304 Part VIII Figures and Layouts 305 Chapter 38 Illustrations The following illustrations document the position of radio in the open systems interconnection (OSI) model, and its free implementation as a graphical user in- terface software package GNOME Internet Radio Locator (gnome-internet-radio- locator) and GNOME Radio (gnome-radio), implemented as Free Software for Debian GNU/Linux, Fedora Linux, Ubuntu Linux, and MacPorts. 307 308 309 310 311 312 313 Chapter 39 Electronical Layouts 39.1 Wireless Transmission 314 39.2 Radio Transmission 315 39.3 Microphone 316 39.4 Loudspeaker 317 318 Part IX Classification of radio 319 When you publish music, photographs or video digitally, the physical rep- resentation of a scenery or humans visible in the exposured digital media can be labeled as places or with personal names and locations. Apple, Facebook, Google, Spotify and Twitter are software for classified information. This is more difficult with live radio in GNOME Radio, but the near exact location of the radio sta- tion broadcasting live voices of humans can’t be recorded and categorized. In GNOME Internet Radio Locator no humans are identified on the broadcast, but the characteristic human voices of the presenters and debaters are differentiated by the listener. 321 322 Part X Human vs. algorithmic curation of music on radio 323 In this Master thesis I have advocated for Free Software and human music curation in Free Internet Radio in my thesis. Google Music and Spotify Radio is using a proprietary software algorithm to select what music to play. With Google Music and Spotify Radio the user will listen to the same music she has been listening to because the algorithms lack human curation. Apple Music is promoting Beats 1, a human curated, but monopolistic radio station. Support for human curation from Spotity is discussed in this interview: https://www.theverge.com/2015/9/30/9416579/spotify- discover-weekly-online-music-curation-interview "This past June, legendary producer and major label insider Jimmy Iovine unveiled Apple Music as the grand finale of the tech titan’s semi-annual product showcase. "It’s a revolutionary music service curated by the leading music experts who we helped handpick," he declared, placing Apple firmly in the human curation camp. Apple’s curation service, Iovine promised, would match the song you hear to the mood and the moment. "Algorithms alone can’t do that emotional task. You need a human touch." Free Internet Radio is still a better alternative for listeners than Apple Music, Google Music and Spotify Radio, because of the human curation of music that is played on the air on a computer running Free Software is supported or funded by its listeners. Many stations included in gnome-internet-radio-locator have a audio message that says "You are listening to Free Internet Radio sponsored by listeners like your- self. To donate, visit www..org". Allthough these recorded messages repeats every time you switch station, most Internet radio stations are operated by humans. We support the element of human influence and consideration of music and debates in Free Internet Radio being funded and supported by the People and for the People, not by a billion dollar company such as Apple with human curation of a monopolistic station or by Google and Spotify with proprietary computer curation algorithms that makes you listen to the same music over and over again. Hypothesis Music on radio shouldn’t be curated by a computer algorithm, but by humans. Conclusion Wrong at times, since it’s on a computer, perhaps correct at Trump rallying events, but in the end he will be forgotten on the radio. 325 326 Part XI Rescue and emergency communication over public radio 327 In the case of evacuation of a physical area, due to Force Majeure events such as hurricanes, fires and wars, where a life-saving police, ambulance and hospi- tal team would save lives during such events, the rescue and emergency work is coordinated and communicated over public radio broadcasts. Listen to radio for safety information about COVID-19 and other crisis. 329 330 Part XII Essay: Democratic voices on public radio in Norway as Free Software (gnomeradio.org) 331 Ole Kristian Aamot (BS EE) olekaa@math.uio.no Department of Mathematics University of Oslo, Norway Norway is a democratic country with a public government and a minister cab- inet choosen in democratic elections. Hospitals, kindergartens, schools and universities prepare and support the vot- ers for the Norwegian inclusive work and welfare state. Several free and independent radio stations in Norway broadcast democratic debates on the progress of our country and civil society in peace. The radio stations in Norway that are available in GNOME Internet Radio Lo- cator (gnome-internet-radio-locator) are NRK P1, NRK P2, NRK P3, NRK P11, NRK Alltid Nyheter, as well as regional broadcasts in NRK Østfold, NRK Vest- fold, NRK Rogaland, NRK Hordaland, NRK Sørlandet, NRK Sogn og Fjordane, NRK Møre og Romsdal, NRK Trøndelag, NRK Nordland, NRK Troms og Finn- mark that broadcast daily radio programs such as the hourly, daily and weekly news reports NRK Dagsnytt, NRK Morgennytt, NRK Formiddagsnytt, NRK Et- termiddagsnytt, NRK Dagsrevyen and NRK Kveldsnytt as well as the debate pro- grams NRK Dagsnytt 18 and NRK Debatten. In addition to NRK, there is support for 3 Public University student radio stations such as Radio NOVA at University of Oslo, Studentradioen i Bergen at University of Bergen, Radio Revolt at NTNU in Trondheim, Norway in the public Internet Radio client GNOME Internet Radio Locator described in the Bachelor thesis "Public Internet Radio Client for Access- ing Free Audio Maps in Countries with Free Speech." http://folk.uio.no/olekaa/thesis/bachelor/AAMOT-2020.pdf The Norwegian democracy is upheld and protected by equal opportunities for moderate and often radical voices on radio through sound arguments between peers such as petitions from the left to the right in the Norwegian democracy. The elected party leader representatives such as Lan Marie Nguyen Berg (Miljø- partiet De Grønne), Erna Solberg (Høyre), Trine Skei Grande (Venstre), Jonas Gahr Støre (Arbeiderpartiet), Audun Lysbakken (Sosialistisk Venstreparti), Bjørnar Moxnes (Rødt), Kjell Ingolf Ropstad (Kristelig Folkeparti), Siv Jensen (Frem- skrittspartiet) and Trygve Slagsvold Vedum (Senterpartiet) must argue in public debates on NRK Radio and TV, as representatives for the public opinion, as they argue for political beliefs and convictions on the best progress for the voting pop- ulation in Norway. 333 334 Part XIII Binary Delivery 335 http://folk.uio.no/olekaa/thesis/bachelor/AAMOT-2020.zip 337 338 Part XIV Installation Instruction for Public Network Radio Software 339 Chapter 40 Installation on GNU/Linux 40.1 Debian GNU/Linux 10 i386 dpkg -i https://www.gnome.org/ ole/debian/gnome-internet-radio-locator .0.1 − 3 1 386.deb i 40.2 Debian GNU/Linux 9 amd64 dpkg -i https://www.gnome.org/ ole/debian/gnome-internet-radio-locator .8.0 − 2 1 md64.deb a 40.3 Fedora Core 32 x86_64 rpm -Uvh http://www.gnomeradio.org/ ole/fedora/RPMS/x86 4/gnome−internet− 6 radio−locator − 3.0.1 − 1.fc32.x86 4.rpm 6 40.4 Fedora Core 31 x86_64 rpm -Uvh https://www.gnome.org/ ole/fedora/RPMS/x86 4/gnome−internet− 6 radio−locator − 3.0.0 − 1.fc31.x86 4.rpm 6 341 40.5 Fedora Core 30 x86_64 rpm -Uvh https://www.gnome.org/ ole/fedora/RPMS/x86_64/gnome-internet-radio- locator-2.1.1-1.fc30.x86_64.rpm 40.6 Fedora Core 29 x86_64 rpm -Uvh https://www.gnome.org/ ole/fedora/RPMS/x86_64/gnome-internet-radio- locator-2.0.0-1.fc29.x86_64.rpm 40.7 Ubuntu 20.04 amd64 dpkg -i http://www.gnomeradio.org/ ole/ubuntu/gnome-internet-radio-locator_3.0.1- 1_amd64.deb 40.8 Ubuntu 19.10 amd64 dpkg -i https://www.gnome.org/ ole/ubuntu/gnome-internet-radio-locator_3.0.0- 1_amd64.deb 40.9 Ubuntu 19.04 amd64 dpkg -i https://www.gnome.org/ ole/ubuntu/gnome-internet-radio-locator_3.0.0- 1_amd64.deb 342