GNOME Radio Podcast 1.0.0

An open-source global radio podcast experience

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 & Install

Installation

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

Publications

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

Checkout GNOME Radio 73.0 Source Code

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