Podcast
GNOME Radio Podcast 1.0.0
The 1.0.0 release features the software applications gnome-radio-podcast shipped in gnome-radio-podcast-1.0.0.tar.xz with 8 different music podcasts
/* GNOME Radio Podcast
Public Domain Audio
http://www.gnomeradio.org:8000/320.ogg
http://www.gnomeradio.org:8000/192.ogg
http://www.gnomeradio.org:8000/128.ogg
http://www.gnomeradio.org:8000/112.ogg
http://www.gnomeradio.org:8000/96.ogg
http://www.gnomeradio.org:8000/80.ogg
http://www.gnomeradio.org:8000/64.ogg
http://www.gnomeradio.org:8000/56.ogg
2026-03-22
*/
#include <gtk/gtk.h>
#include <gst/gst.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <stdlib.h>
#include <string.h>
#define CONFIG_DIR ".gnome-radio-podcast"
#define XML_FILE "gnome-radio-podcast.xml"
typedef struct _Podcast {
char *title;
char *description;
char *url;
struct _Podcast *next;
} Podcast;
static Podcast *podcast_list = NULL;
static GstElement *player = NULL;
static GtkWidget *entry_url;
static GtkWidget *entry_title;
static GtkWidget *entry_desc;
/* --------------------------
Linked list
---------------------------*/
void add_podcast(const char *title,
const char *desc,
const char *url)
{
Podcast *p = g_malloc(sizeof(Podcast));
p->title = g_strdup(title);
p->description = g_strdup(desc);
p->url = g_strdup(url);
p->next = podcast_list;
podcast_list = p;
}
/* --------------------------
XML path
---------------------------*/
char *get_xml_path()
{
const char *home = g_get_home_dir();
char *dir =
g_build_filename(home, CONFIG_DIR, NULL);
g_mkdir_with_parents(dir, 0700);
char *path =
g_build_filename(dir, XML_FILE, NULL);
g_free(dir);
return path;
}
/* --------------------------
Save XML
---------------------------*/
void save_xml()
{
char *path = get_xml_path();
xmlDocPtr doc = xmlNewDoc(
BAD_CAST "1.0");
xmlNodePtr root =
xmlNewNode(NULL,
BAD_CAST "gnome_radio_podcast");
xmlDocSetRootElement(doc, root);
Podcast *p = podcast_list;
while (p)
{
xmlNodePtr node =
xmlNewChild(root, NULL,
BAD_CAST "podcast",
NULL);
xmlNewChild(node, NULL,
BAD_CAST "title",
BAD_CAST p->title);
xmlNewChild(node, NULL,
BAD_CAST "description",
BAD_CAST p->description);
xmlNewChild(node, NULL,
BAD_CAST "url",
BAD_CAST p->url);
p = p->next;
}
xmlSaveFormatFileEnc(
path,
doc,
"UTF-8",
1);
xmlFreeDoc(doc);
g_free(path);
}
/* --------------------------
Load XML
---------------------------*/
void load_xml()
{
char *path = get_xml_path();
xmlDoc *doc =
xmlReadFile(path, NULL, 0);
if (!doc)
return;
xmlNode *root =
xmlDocGetRootElement(doc);
for (xmlNode *n = root->children;
n;
n = n->next)
{
if (n->type != XML_ELEMENT_NODE)
continue;
if (!strcmp((char*)n->name,
"podcast"))
{
char *title = NULL;
char *desc = NULL;
char *url = NULL;
for (xmlNode *c = n->children;
c;
c = c->next)
{
if (c->type != XML_ELEMENT_NODE)
continue;
char *txt =
(char*)
xmlNodeGetContent(c);
if (!strcmp((char*)c->name,
"title"))
title = g_strdup(txt);
if (!strcmp((char*)c->name,
"description"))
desc = g_strdup(txt);
if (!strcmp((char*)c->name,
"url"))
url = g_strdup(txt);
xmlFree(txt);
}
if (title && url)
add_podcast(title, desc, url);
}
}
xmlFreeDoc(doc);
g_free(path);
}
/* --------------------------
GStreamer
---------------------------*/
void play_url(const char *url)
{
if (!player)
return;
g_object_set(
player,
"uri",
url,
NULL);
gst_element_set_state(
player,
GST_STATE_PLAYING);
}
void pause_stream()
{
gst_element_set_state(
player,
GST_STATE_PAUSED);
}
/* --------------------------
Buttons
---------------------------*/
static void on_add(GtkButton *b,
gpointer d)
{
const char *url =
gtk_editable_get_text(
GTK_EDITABLE(entry_url));
const char *title =
gtk_editable_get_text(
GTK_EDITABLE(entry_title));
const char *desc =
gtk_editable_get_text(
GTK_EDITABLE(entry_desc));
if (url && title)
{
add_podcast(title, desc, url);
save_xml();
}
}
static void on_play(GtkButton *b,
gpointer d)
{
if (podcast_list)
play_url(podcast_list->url);
}
static void on_pause(GtkButton *b,
gpointer d)
{
pause_stream();
}
static void on_search(GtkButton *b,
gpointer d)
{
const char *q =
gtk_editable_get_text(
GTK_EDITABLE(entry_title));
if (!q)
return;
char *cmd =
g_strdup_printf(
"xdg-open "
"'https://duckduckgo.com/?q=%s'",
q);
system(cmd);
g_free(cmd);
}
/* --------------------------
UI
---------------------------*/
static void activate(GtkApplication *app,
gpointer data)
{
GtkWidget *win =
gtk_application_window_new(app);
gtk_window_set_title(
GTK_WINDOW(win),
"GNOME Radio Podcast");
GtkWidget *box =
gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
gtk_window_set_child(
GTK_WINDOW(win),
box);
entry_url =
gtk_entry_new();
gtk_entry_set_placeholder_text(GTK_ENTRY(entry_url), "http://gnomeradio.org:8000/320.ogg");
entry_title =
gtk_entry_new();
gtk_entry_set_placeholder_text(GTK_ENTRY(entry_title), "Radio Podcast");
entry_desc =
gtk_entry_new();
gtk_entry_set_placeholder_text(GTK_ENTRY(entry_desc), "Radio Podcast 8000");
gtk_box_append(GTK_BOX(box),
entry_title);
gtk_box_append(GTK_BOX(box),
entry_desc);
gtk_box_append(GTK_BOX(box),
entry_url);
GtkWidget *add =
gtk_button_new_with_label("Add");
GtkWidget *play =
gtk_button_new_with_label("Play");
GtkWidget *pause =
gtk_button_new_with_label("Pause");
GtkWidget *search =
gtk_button_new_with_label("Search");
gtk_box_append(GTK_BOX(box), add);
gtk_box_append(GTK_BOX(box), play);
gtk_box_append(GTK_BOX(box), pause);
gtk_box_append(GTK_BOX(box), search);
g_signal_connect(add,
"clicked",
G_CALLBACK(on_add),
NULL);
g_signal_connect(play,
"clicked",
G_CALLBACK(on_play),
NULL);
g_signal_connect(pause,
"clicked",
G_CALLBACK(on_pause),
NULL);
g_signal_connect(search,
"clicked",
G_CALLBACK(on_search),
NULL);
gtk_window_present(
GTK_WINDOW(win));
}
/* --------------------------
main
---------------------------*/
int main(int argc, char **argv)
{
gst_init(&argc, &argv);
player =
gst_element_factory_make(
"playbin",
"player");
load_xml();
GtkApplication *app =
gtk_application_new(
"org.gnomeradio.podcast",
G_APPLICATION_DEFAULT_FLAGS);
g_signal_connect(
app,
"activate",
G_CALLBACK(activate),
NULL);
int status =
g_application_run(
G_APPLICATION(app),
argc,
argv);
g_object_unref(app);
return status;
}
Download Source & Install
Radio
GNOME Radio is Free Internet Radio Software for the GNU Network Object Model Environment. The 75.0 release features the software applications gnome-radio, gnome-internet-radio-locator, gtk-internet-radio-locator, org.gnome.Radio, radio-beamy and radio-icy shipped in gnome-radio-75.0.tar.xz with 240 international radio stations including Studentradioen i Bergen (Bergen, Norway), Radio Revolt (Trondheim, Norway), Nea Radio (Stjørdal, Norway), Radio Riks Oslo (Akershus, Norway), Radio Rjukan (Rjukan, Telemark), Radio Stortinget (Stortinget, Oslo, Norway), Radio Latin-Amerika (Oslo, Norway), Radio Havana Cuba (Havana, Cuba), The Current (Minnesota, United States of America), Circuito Adulto Joven (Caracas, Venezuela), Radio Greenland (Godthåb, Grønland), UCT Radio (South Africa), Radio Warszawa (Poland), BBC (UK), C-SPAN (USA), Hawaii Public Radio (NPR), NPO Radio 1 (Netherlands), Radio Punjab Today (India), University of Washington (USA), Radio Alhara (Betlehem, Palestine), Radio Haifa (Israel), as well as 100+ city map markers around the world.
Buy Source & InstallInstallation
Windows 11 / Fedora 43 WSL2
wsl.exe --install Fedora
In FedoraLinux-43 Application console:
sudo dnf install gnome-radio gstreamer*
gnome-radio
Fedora Asahi Remix 42
sudo dnf install https://www.gnomeradio.org/~ole/fedora/RPMS/aarch64/gnome-radio-73.0-1.fc42.aarch64.rpm
Fedora Asahi Remix 43
sudo dnf install https://www.gnomeradio.org/~ole/fedora/RPMS/aarch64/gnome-radio-75.0-1.fc43.aarch64.rpm
Fedora Core 42
sudo dnf install gnome-radio
Fedora Core 43
sudo dnf install https://www.gnomeradio.org/~ole/fedora/RPMS/x86_64/gnome-radio-75.0-1.fc43.x86_64.rpm
Fedora Core 44
sudo dnf install gnome-radio
Fedora Core Rawhide
sudo dnf install gnome-radio
macOS (via MacPorts)
sudo port install xorg-server
sudo port install gnome-radio
Ubuntu 24.04.4 LTS
wget https://www.gnomeradio.org/~ole/ubuntu/gnome-radio_73.0-1_amd64.deb
sudo dpkg -i gnome-radio_73.0-1_amd64.deb
News
- March 22, 2026: GNOME Radio Podcast 1.0.0 for GNOME 50 released. Download Source
- March 22, 2026: GNOME Radio 73.0 for GNOME 50 released. Buy Source
Publications
- Aamot, Ole (GUADEC 2025). RADIO SIGNAL PRIVACY: MATHEMATICAL PERSPECTIVES AND FCC POLICY.
- Aamot, Ole (GUADEC 2024). GTK Radio on GNOME 46.
- Aamot, Ole (GUADEC 2023). GNU Network Object Model Environment Radio 64 on GNOME 44.
- Aamot, Ole (GUADEC 2022). GNU Network Object Model Environment Radio 16 on GNOME 42.
- Aamot, Ole (BSc Thesis, 2020). Public Internet Radio Client for Accessing Free Audio Maps in Countries with Free Speech.
Source Code
GNOME Radio Podcast
GitHub Repository · Download Tarball
git clone https://github.com/aamotsoftware/gnome-radio-podcast.git
cd gnome-radio-podcast/
make
sudo make install
gnome-radio-podcast
GNOME Radio
Help
Visit the Help Guide for GNOME Radio 75.0.
A quick introduction is available here.
Bugs
Visit Fedora Project and Red Hat Bugzilla for bug reports on gnome-radio.
References
- Shannon, Claude (1948). A Mathematical Theory of Communication. Bell Labs.
- Nielsen, Michael A. & Chuang, Isaac L. (2021). Quantum Computation and Quantum Information.
- Piccardo, Marco et al. (2019). Laser radio transmitter. MIT Lincoln Laboratory.

