[gnome-internet-radio-locator: 1/2] Prepare Non-Geoclue release of GNOME Internet Radio Locator 12.0.0




commit 46c4f6fc735bd387742d33a5ae9db2e6a61f072b
Author: Ole Aamot <ole gnome org>
Date:   Sat Jun 26 20:37:59 2021 +0200

    Prepare Non-Geoclue release of GNOME Internet Radio Locator 12.0.0

 NEWS                                        |   5 +
 src/Makefile.am                             |   3 +-
 src/gnome-internet-radio-locator-location.c | 197 ++++++++++++++++++++++++++++
 src/gnome-internet-radio-locator-location.h |  26 ++++
 src/gnome-internet-radio-locator-markers.c  |  11 ++
 src/gnome-internet-radio-locator.c          | 165 ++---------------------
 src/gnome-internet-radio-locator.xml        |   4 +-
 7 files changed, 253 insertions(+), 158 deletions(-)
---
diff --git a/NEWS b/NEWS
index d5be629..52136b0 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,10 @@ Version 12.0.0
 Build
 
        * configure.ac: Version 12.0.0
+       * src/Makefile.am: Add gnome-internet-radio-locator-location.c
+       * src/gnome-internet-radio-locator.c: Deactivate GeoClue code
+       * src/gnome-internet-radio-locator-location.c: Add GeoClue code
+       * src/gnome-internet-radio-locator-location.h: Add GeoClue code
 
 Documentation
 
@@ -19,6 +23,7 @@ Documentation
 
 Stations
 
+       * src/gnome-internet-radio-locator-markers.c: C-SPAN (Washington, D.C.)
        * src/gnome-internet-radio-locator.xml: Bump version
 
 =============
diff --git a/src/Makefile.am b/src/Makefile.am
index fcdd77b..e87edde 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -14,6 +14,7 @@ bin_PROGRAMS = gnome-internet-radio-locator
 gnome_internet_radio_locator_SOURCES = \
                gnome-internet-radio-locator-gui.c \
                gnome-internet-radio-locator-listener.c \
+               gnome-internet-radio-locator-location.c \
                gnome-internet-radio-locator-markers.c \
                gnome-internet-radio-locator-player.c \
                gnome-internet-radio-locator-program.c \
@@ -38,7 +39,7 @@ gnomeinternetradiolocatordir = $(datadir)/gnome-internet-radio-locator
 
 gnomeinternetradiolocator_DATA = gnome-internet-radio-locator-5.0.dtd gnome-internet-radio-locator.xml
 
-EXTRA_DIST = gnome-internet-radio-locator.h gnome-internet-radio-locator-player.h 
gnome-internet-radio-locator-keys.h gnome-internet-radio-locator-markers.h 
gnome-internet-radio-locator-player-kb.h gnome-internet-radio-locator-player-resource.h 
gnome-internet-radio-locator-radius.h gnome-internet-radio-locator-station.h 
gnome-internet-radio-locator-stations-map.h gnome-internet-radio-locator-tz.h 
gnome-internet-radio-locator-gui.h gnome-internet-radio-locator-listener.h 
gnome-internet-radio-locator-program.h gnome-internet-radio-locator-runners.h 
gnome-internet-radio-locator-streams.h gnome-internet-radio-locator-5.0.dtd gnome-internet-radio-locator.xml 
gnome-internet-radio-locator.xsl gnome-internet-radio-locator.gresource.xml
+EXTRA_DIST = gnome-internet-radio-locator.h gnome-internet-radio-locator-location.h 
gnome-internet-radio-locator-player.h gnome-internet-radio-locator-keys.h 
gnome-internet-radio-locator-markers.h gnome-internet-radio-locator-player-kb.h 
gnome-internet-radio-locator-player-resource.h gnome-internet-radio-locator-radius.h 
gnome-internet-radio-locator-station.h gnome-internet-radio-locator-stations-map.h 
gnome-internet-radio-locator-tz.h gnome-internet-radio-locator-gui.h gnome-internet-radio-locator-listener.h 
gnome-internet-radio-locator-program.h gnome-internet-radio-locator-runners.h 
gnome-internet-radio-locator-streams.h gnome-internet-radio-locator-5.0.dtd gnome-internet-radio-locator.xml 
gnome-internet-radio-locator.xsl gnome-internet-radio-locator.gresource.xml
 
 LDADD = $(GNOME_INTERNET_RADIO_LOCATOR_LIBS)
 
diff --git a/src/gnome-internet-radio-locator-location.c b/src/gnome-internet-radio-locator-location.c
new file mode 100644
index 0000000..fe044f6
--- /dev/null
+++ b/src/gnome-internet-radio-locator-location.c
@@ -0,0 +1,197 @@
+/* $Id$
+ *
+ * GNOME Internet Radio Locator
+ *
+ * Copyright (C) 2021  Aamot Software
+ *
+ * Author: Ole Aamot <ole gnome org>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <gtk/gtk.h>
+#include <gst/player/player.h>
+#include <champlain/champlain.h>
+#include <champlain-gtk/champlain-gtk.h>
+#include <clutter-gtk/clutter-gtk.h>
+#include <geocode-glib/geocode-glib.h>
+#include <glib/gstdio.h>
+#include <glib/gi18n.h>
+#include <string.h>
+#include <geoclue.h>
+
+#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"
+
+/* Commandline options */
+static gint timeout = 30; /* seconds */
+static GClueAccuracyLevel accuracy_level = GCLUE_ACCURACY_LEVEL_EXACT;
+static gint time_threshold;
+static GClueLocation *location;        
+static gdouble altitude, speed, heading;
+static GVariant *timestamp;
+static GOptionEntry entries[] =
+{
+        { "timeout",
+          't',
+          0,
+          G_OPTION_ARG_INT,
+          &timeout,
+          N_("Exit after T seconds. Default: 30"),
+          "T" },
+        { "time-threshold",
+          'i',
+          0,
+          G_OPTION_ARG_INT,
+          &time_threshold,
+          N_("Only report location update after T seconds. "
+             "Default: 0 (report new location without any delay)"),
+          "T" },
+        { "accuracy-level",
+          'a',
+          0,
+          G_OPTION_ARG_INT,
+          &accuracy_level,
+          N_("Request accuracy level A. "
+             "Country = 1, "
+             "City = 4, "
+             "Neighborhood = 5, "
+             "Street = 6, "
+             "Exact = 8."),
+          "A" },
+        { NULL }
+};
+
+GClueSimple *simple = NULL;
+GClueClient *client = NULL;
+GMainLoop *main_loop;
+
+static void
+print_location (GClueSimple *simple, ChamplainView *view)
+{
+        GClueLocation *location;
+        gdouble altitude, speed, heading;
+        GVariant *timestamp;
+        GTimeVal tv = { 0 };
+        const char *desc;
+
+        location = gclue_simple_get_location (simple);
+        GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG ("\nNew location:\n");
+        GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG ("Latitude:    %f°\nLongitude:   %f°\nAccuracy:    %f 
meters\n",
+                 gclue_location_get_latitude (location),
+                 gclue_location_get_longitude (location),
+                 gclue_location_get_accuracy (location));
+
+       champlain_view_center_on (CHAMPLAIN_VIEW (view),
+                                 gclue_location_get_latitude (location),
+                                 gclue_location_get_longitude (location));
+       
+        altitude = gclue_location_get_altitude (location);
+        if (altitude != -G_MAXDOUBLE)
+                GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG ("Altitude:    %f meters\n", altitude);
+        speed = gclue_location_get_speed (location);
+        if (speed >= 0)
+                GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG ("Speed:       %f meters/second\n", speed);
+        heading = gclue_location_get_heading (location);
+        if (heading >= 0)
+                GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG ("Heading:     %f°\n", heading);
+
+        desc = gclue_location_get_description (location);
+        if (strlen (desc) > 0)
+                GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG ("Description: %s\n", desc);
+
+        timestamp = gclue_location_get_timestamp (location);
+        if (timestamp) {
+                GDateTime *date_time;
+                gchar *str;
+
+                g_variant_get (timestamp, "(tt)", &tv.tv_sec, &tv.tv_usec);
+
+                date_time = g_date_time_new_from_timeval_local (&tv);
+                str = g_date_time_format
+                      (date_time,
+                       "%c (%s seconds since the Epoch)");
+                g_date_time_unref (date_time);
+
+                GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG ("Timestamp:   %s\n", str);
+                g_free (str);
+        }
+}
+
+static gboolean
+on_location_timeout (gpointer user_data)
+{
+        g_clear_object (&client);
+        g_clear_object (&simple);
+        g_main_loop_quit (main_loop);
+
+        return FALSE;
+}
+
+static void
+on_client_active_notify (GClueClient *client,
+                         GParamSpec *pspec,
+                         gpointer    user_data)
+{
+        if (gclue_client_get_active (client))
+                return;
+
+        GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG ("Geolocation disabled. Quitting..\n");
+        on_location_timeout (NULL);
+}
+
+static void
+on_simple_ready (GObject      *source_object,
+                 GAsyncResult *res,
+                 gpointer      user_data)
+{
+        GError *error = NULL;
+
+        simple = gclue_simple_new_finish (res, &error);
+        if (error != NULL) {
+            g_critical ("Failed to connect to GeoClue2 service: %s", error->message);
+
+            exit (-1);
+        }
+        client = gclue_simple_get_client (simple);
+        if (client) {
+                g_object_ref (client);
+                GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG ("Client object: %s\n",
+                         g_dbus_proxy_get_object_path (G_DBUS_PROXY (client)));
+
+                g_signal_connect (client,
+                                  "notify::active",
+                                  G_CALLBACK (on_client_active_notify),
+                                  NULL);
+        }
+        print_location (simple, user_data);
+
+        g_signal_connect (simple,
+                          "notify::location",
+                          G_CALLBACK (print_location),
+                          user_data);
+}
+
+void location_main (ChamplainView *view) {
+        gdouble altitude, speed, heading;
+       gclue_simple_new ("gnome-internet-radio-locator",
+                         accuracy_level,
+                         time_threshold,
+                         on_simple_ready,
+                         CHAMPLAIN_VIEW (view));
+       return;
+}
diff --git a/src/gnome-internet-radio-locator-location.h b/src/gnome-internet-radio-locator-location.h
new file mode 100644
index 0000000..32f2269
--- /dev/null
+++ b/src/gnome-internet-radio-locator-location.h
@@ -0,0 +1,26 @@
+/* $Id$
+ *
+ * GNOME Internet Radio Locator
+ *
+ * Copyright (C) 2021  Aamot Software
+ *
+ * Author: Ole Aamot <ole gnome org>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <champlain/champlain.h>
+#include <champlain-gtk/champlain-gtk.h>
+
+void location_main (ChamplainView *view);
diff --git a/src/gnome-internet-radio-locator-markers.c b/src/gnome-internet-radio-locator-markers.c
index 305184b..d6378ab 100644
--- a/src/gnome-internet-radio-locator-markers.c
+++ b/src/gnome-internet-radio-locator-markers.c
@@ -1002,6 +1002,17 @@ create_marker_layer (G_GNUC_UNUSED ChamplainView *view, ChamplainPathLayer **pat
        /* 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("Supreme Court, United States of America\n<span size=\"small\">C-SPAN</span>");
+       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), 38.8898027,-77.0094179);
+       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<span size=\"small\">NRK P1 Østfold</span>");
        champlain_label_set_text (CHAMPLAIN_LABEL (marker), station);
        champlain_label_set_use_markup (CHAMPLAIN_LABEL (marker), TRUE);
diff --git a/src/gnome-internet-radio-locator.c b/src/gnome-internet-radio-locator.c
index 371cebd..dfcc01b 100644
--- a/src/gnome-internet-radio-locator.c
+++ b/src/gnome-internet-radio-locator.c
@@ -34,6 +34,7 @@
 
 #include "gnome-internet-radio-locator.h"
 #include "gnome-internet-radio-locator-gui.h"
+#include "gnome-internet-radio-locator-location.h"
 #include "gnome-internet-radio-locator-markers.h"
 #include "gnome-internet-radio-locator-player.h"
 
@@ -86,109 +87,6 @@ GStatBuf stats;
 
 ChamplainView *view;
 
-/* Commandline options */
-static gint timeout = 30; /* seconds */
-static GClueAccuracyLevel accuracy_level = GCLUE_ACCURACY_LEVEL_EXACT;
-static gint time_threshold;
-
-static GOptionEntry entries[] =
-{
-        { "timeout",
-          't',
-          0,
-          G_OPTION_ARG_INT,
-          &timeout,
-          N_("Exit after T seconds. Default: 30"),
-          "T" },
-        { "time-threshold",
-          'i',
-          0,
-          G_OPTION_ARG_INT,
-          &time_threshold,
-          N_("Only report location update after T seconds. "
-             "Default: 0 (report new location without any delay)"),
-          "T" },
-        { "accuracy-level",
-          'a',
-          0,
-          G_OPTION_ARG_INT,
-          &accuracy_level,
-          N_("Request accuracy level A. "
-             "Country = 1, "
-             "City = 4, "
-             "Neighborhood = 5, "
-             "Street = 6, "
-             "Exact = 8."),
-          "A" },
-        { NULL }
-};
-
-GClueSimple *simple = NULL;
-GClueClient *client = NULL;
-GMainLoop *main_loop;
-
-static void
-print_location (GClueSimple *simple)
-{
-        GClueLocation *location;
-        gdouble altitude, speed, heading;
-        GVariant *timestamp;
-        GTimeVal tv = { 0 };
-        const char *desc;
-
-        location = gclue_simple_get_location (simple);
-        GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG ("\nNew location:\n");
-        GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG ("Latitude:    %f°\nLongitude:   %f°\nAccuracy:    %f 
meters\n",
-                 gclue_location_get_latitude (location),
-                 gclue_location_get_longitude (location),
-                 gclue_location_get_accuracy (location));
-
-       champlain_view_center_on (CHAMPLAIN_VIEW (view),
-                                 gclue_location_get_latitude (location),
-                                 gclue_location_get_longitude (location));
-       
-        altitude = gclue_location_get_altitude (location);
-        if (altitude != -G_MAXDOUBLE)
-                GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG ("Altitude:    %f meters\n", altitude);
-        speed = gclue_location_get_speed (location);
-        if (speed >= 0)
-                GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG ("Speed:       %f meters/second\n", speed);
-        heading = gclue_location_get_heading (location);
-        if (heading >= 0)
-                GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG ("Heading:     %f°\n", heading);
-
-        desc = gclue_location_get_description (location);
-        if (strlen (desc) > 0)
-                GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG ("Description: %s\n", desc);
-
-        timestamp = gclue_location_get_timestamp (location);
-        if (timestamp) {
-                GDateTime *date_time;
-                gchar *str;
-
-                g_variant_get (timestamp, "(tt)", &tv.tv_sec, &tv.tv_usec);
-
-                date_time = g_date_time_new_from_timeval_local (&tv);
-                str = g_date_time_format
-                      (date_time,
-                       "%c (%s seconds since the Epoch)");
-                g_date_time_unref (date_time);
-
-                GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG ("Timestamp:   %s\n", str);
-                g_free (str);
-        }
-}
-
-static gboolean
-on_location_timeout (gpointer user_data)
-{
-        g_clear_object (&client);
-        g_clear_object (&simple);
-        g_main_loop_quit (main_loop);
-
-        return FALSE;
-}
-
 gchar *
 str_channels (GNOMEInternetRadioLocatorChannels type) {
   gchar *channels;
@@ -888,49 +786,6 @@ on_search_matches(GtkEntryCompletion *widget,
 }
 
 
-static void
-on_client_active_notify (GClueClient *client,
-                         GParamSpec *pspec,
-                         gpointer    user_data)
-{
-        if (gclue_client_get_active (client))
-                return;
-
-        GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG ("Geolocation disabled. Quitting..\n");
-        on_location_timeout (NULL);
-}
-
-static void
-on_simple_ready (GObject      *source_object,
-                 GAsyncResult *res,
-                 gpointer      user_data)
-{
-        GError *error = NULL;
-
-        simple = gclue_simple_new_finish (res, &error);
-        if (error != NULL) {
-            g_critical ("Failed to connect to GeoClue2 service: %s", error->message);
-
-            exit (-1);
-        }
-        client = gclue_simple_get_client (simple);
-        if (client) {
-                g_object_ref (client);
-                GNOME_INTERNET_RADIO_LOCATOR_DEBUG_MSG ("Client object: %s\n",
-                         g_dbus_proxy_get_object_path (G_DBUS_PROXY (client)));
-
-                g_signal_connect (client,
-                                  "notify::active",
-                                  G_CALLBACK (on_client_active_notify),
-                                  NULL);
-        }
-        print_location (simple);
-
-        g_signal_connect (simple,
-                          "notify::location",
-                          G_CALLBACK (print_location),
-                          user_data);
-}
 
 int
 main (int argc,
@@ -944,8 +799,6 @@ main (int argc,
        GtkTreeIter iter;
        GNOMEInternetRadioLocatorStationInfo *stationinfo, *localstation;
        guint context_id;
-       GClueLocation *location;
-        gdouble altitude, speed, heading;
         GVariant *timestamp;
         GTimeVal tv = { 0 };
         const char *desc;
@@ -996,12 +849,7 @@ main (int argc,
        license_actor = champlain_view_get_license_actor (view);
        champlain_license_set_extra_text (license_actor, "Free Internet Radio");
        /* FIXME: New Haven, Connecticut */
-       // champlain_view_center_on (CHAMPLAIN_VIEW (view), 41.298434349999994,-72.93102342707913);
-       gclue_simple_new ("gnome-internet-radio-locator",
-                         accuracy_level,
-                         time_threshold,
-                         on_simple_ready,
-                         CHAMPLAIN_VIEW (view));
+       champlain_view_center_on (CHAMPLAIN_VIEW (view), 41.298434349999994,-72.93102342707913);
        
        // location = gclue_simple_get_location (simple);
        
@@ -1033,6 +881,15 @@ main (int argc,
        g_signal_connect(button, "clicked", G_CALLBACK (on_new_station_clicked), view);
        gtk_container_add (GTK_CONTAINER (bbox), button);
 
+#if 0 /* FIXME: GeoClue2 Location Services */
+       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), _("Discover Location"));
+       g_signal_connect(button, "clicked", G_CALLBACK (location_main), CHAMPLAIN_VIEW (view));
+       gtk_container_add (GTK_CONTAINER (bbox), button);
+#endif
        memset(&stats, 0, sizeof(stats));
 
        input = gtk_entry_new();
diff --git a/src/gnome-internet-radio-locator.xml b/src/gnome-internet-radio-locator.xml
index bc5aa08..983e60a 100644
--- a/src/gnome-internet-radio-locator.xml
+++ b/src/gnome-internet-radio-locator.xml
@@ -1340,15 +1340,13 @@ WUMR has been the University of Memphis broadcasting outlet since 1979, when Sou
     <stream mime="audio/mpeg" uri="http://wamu-1.streamguys.com/"; codec="MPEG 1 Audio, Layer 3 (MP3)" 
samplerate="44100 Hz" channels="Mono" bitrate="48 kbps" />
     <uri>http://wamu.org/</uri>
   </station>
-  <!-- Appears to be down as of 2021/06/11
   <station band="90.1FM" id="c-span" lang="en" name="C-SPAN" rank="1.0" type="org">
     <frequency uri="http://www.c-span.org/";>90.1 FM in Supreme Court, United States of America</frequency>
     <location>Supreme Court, United States of America</location>
     <description lang="en">C-SPAN Radio 90.1 WCSP-FM in Washington, DC offers commercial-free public affairs 
programming 24 hours a day. You’ll hear live coverage from Washington of important congressional hearings and 
key speeches from national leaders.</description>
-    <stream mime="audio/mpeg" 
uri="https://playerservices.streamtheworld.com/api/livestream-redirect/CSPANRADIO.mp3"; codec="MPEG 1 Audio, 
Layer 3 (MP3)" samplerate="22050 Hz" channels="Stereo" bitrate="39 kbps" />
+    <stream mime="audio/mpeg" uri="https://18123.live.streamtheworld.com/CSPANRADIO.mp3"; codec="MPEG 1 
Audio, Layer 3 (MP3)" samplerate="22050 Hz" channels="Stereo" bitrate="39 kbps" />
     <uri>http://www.c-span.org/</uri>
   </station>
-  -->
   <!-- Appears to be down as of 2016/07/07
   <station band="1580AM" id="kdup" lang="en" name="KDUP" rank="1.0" type="edu">
     <frequency uri="http://kdup.up.edu/";>1580 AM in Portland, Oregon</frequency>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]