diff --git a/gst/udp/gstmultiudpsink.c b/gst/udp/gstmultiudpsink.c
index f097333..de4cd53 100644
--- a/gst/udp/gstmultiudpsink.c
+++ b/gst/udp/gstmultiudpsink.c
@@ -92,6 +92,9 @@ enum
   PROP_SOCKFD,
   PROP_CLOSEFD,
   PROP_SOCK,
+  PROP_SOCKFD6,
+  PROP_CLOSEFD6,
+  PROP_SOCK6,
   PROP_CLIENTS,
   PROP_AUTO_MULTICAST,
   PROP_TTL,
@@ -108,6 +111,12 @@ G_STMT_START {                                                            \
       udpctx->sockfd = DEFAULT_SOCKFD;                                    \
   }                                                                       \
   udpctx->sock = DEFAULT_SOCK;                                            \
+  if ((!udpctx->externalfd6) || (udpctx->externalfd6 && udpctx->closefd6)) { \
+    CLOSE_SOCKET(udpctx->sock6);                                           \
+    if (udpctx->sock6 == udpctx->sockfd6)                                   \
+      udpctx->sockfd6 = DEFAULT_SOCKFD;                                    \
+  }                                                                       \
+  udpctx->sock6 = DEFAULT_SOCK;                                            \
 } G_STMT_END
 
 static void gst_multiudpsink_base_init (gpointer g_class);
@@ -291,7 +300,20 @@ gst_multiudpsink_class_init (GstMultiUDPSinkClass * klass)
           DEFAULT_CLOSEFD, G_PARAM_READWRITE));
   g_object_class_install_property (gobject_class, PROP_SOCK,
       g_param_spec_int ("sock", "Socket Handle",
-          "Socket currently in use for UDP sending. (-1 == no socket)",
+          "Socket currently in use for UDP sending . (-1 == no socket)",
+          -1, G_MAXINT, DEFAULT_SOCK, G_PARAM_READABLE));
+  g_object_class_install_property (gobject_class, PROP_SOCKFD6,
+      g_param_spec_int ("sockfd6",
+          "Socket Handle for IP6 for non dual-stack systems",
+          "Socket to use for UDP sending to IP6 clients on non dual-stack systems. (-1 == allocate)",
+          -1, G_MAXINT, DEFAULT_SOCKFD, G_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class, PROP_CLOSEFD6,
+      g_param_spec_boolean ("closefd6", "Close sockfd6",
+          "Close sockfd6 if passed as property on state change",
+          DEFAULT_CLOSEFD, G_PARAM_READWRITE));
+  g_object_class_install_property (gobject_class, PROP_SOCK6,
+      g_param_spec_int ("sock6", "Socket Handle for IP6",
+          "Socket currently in use for UDP sending to IP6 clients on non dual-stack systems. (-1 == no socket)",
           -1, G_MAXINT, DEFAULT_SOCK, G_PARAM_READABLE));
   g_object_class_install_property (gobject_class, PROP_CLIENTS,
       g_param_spec_string ("clients", "Clients",
@@ -304,8 +326,8 @@ gst_multiudpsink_class_init (GstMultiUDPSinkClass * klass)
           " has to do it himself", DEFAULT_AUTO_MULTICAST, G_PARAM_READWRITE));
   g_object_class_install_property (gobject_class, PROP_TTL,
       g_param_spec_int ("ttl", "Multicast TTL",
-          "Used for setting the multicast TTL parameter",
-          0, 255, DEFAULT_TTL, G_PARAM_READWRITE));
+          "Used for setting the multicast TTL parameter", 0, 255, DEFAULT_TTL,
+          G_PARAM_READWRITE));
   g_object_class_install_property (gobject_class, PROP_LOOP,
       g_param_spec_boolean ("loop", "Multicast Loopback",
           "Used for setting the multicast loop parameter. TRUE = enable,"
@@ -330,6 +352,10 @@ gst_multiudpsink_class_init (GstMultiUDPSinkClass * klass)
 static void
 gst_multiudpsink_init (GstMultiUDPSink * sink)
 {
+  int testsock;
+  int v6only;
+  int ret;
+
   WSA_STARTUP (sink);
 
   sink->client_lock = g_mutex_new ();
@@ -337,10 +363,31 @@ gst_multiudpsink_init (GstMultiUDPSink * sink)
   sink->sockfd = DEFAULT_SOCKFD;
   sink->closefd = DEFAULT_CLOSEFD;
   sink->externalfd = (sink->sockfd != -1);
+  sink->sock6 = DEFAULT_SOCK;
+  sink->sockfd6 = DEFAULT_SOCKFD;
+  sink->closefd6 = DEFAULT_CLOSEFD;
+  sink->externalfd6 = (sink->sockfd6 != -1);
   sink->auto_multicast = DEFAULT_AUTO_MULTICAST;
   sink->ttl = DEFAULT_TTL;
   sink->loop = DEFAULT_LOOP;
   sink->qos_dscp = DEFAULT_QOS_DSCP;
+
+  /* Unless we can confirm that dual-stack works, don't use it */
+  sink->dualstack = FALSE;
+
+  /* Figure out if we support dual-stack mode */
+  testsock = socket (AF_INET6, SOCK_DGRAM, 0);
+  if (testsock >= 0) {
+    /* Turn off v6-only to make the socket dual-stack */
+    v6only = 0;
+    ret = setsockopt (testsock, IPPROTO_IPV6, IPV6_V6ONLY,
+        (char *) &v6only, sizeof (v6only));
+    /* Successfully switched to dual-stack mode, yay! */
+    if (ret == 0)
+      sink->dualstack = TRUE;
+
+    CLOSE_SOCKET (testsock);
+  }
 }
 
 static void
@@ -356,6 +403,9 @@ gst_multiudpsink_finalize (GObject * object)
   if (sink->sockfd >= 0 && sink->closefd)
     CLOSE_SOCKET (sink->sockfd);
 
+  if (sink->sockfd6 >= 0 && sink->closefd6)
+    CLOSE_SOCKET (sink->sockfd6);
+
   g_mutex_free (sink->client_lock);
 
   WSA_CLEANUP (object);
@@ -491,23 +541,43 @@ gst_multiudpsink_setup_qos_dscp (GstMultiUDPSink * sink)
   if (sink->qos_dscp < 0)
     return;
 
-  if (sink->sock < 0)
-    return;
-
-  GST_DEBUG_OBJECT (sink, "setting TOS to %d", sink->qos_dscp);
-
   /* Extract and shift 6 bits of DSFIELD */
   tos = (sink->qos_dscp & 0x3f) << 2;
 
-  if (setsockopt (sink->sock, IPPROTO_IP, IP_TOS, &tos, sizeof (tos)) < 0) {
-    GST_ERROR_OBJECT (sink, "could not set TOS: %s", g_strerror (errno));
-  }
+  if (sink->sock != -1) {
+    GST_DEBUG_OBJECT (sink, "setting TOS to %d", sink->qos_dscp);
+
+    if (setsockopt (sink->sock, IPPROTO_IP, IP_TOS, &tos, sizeof (tos)) < 0) {
+      GST_ERROR_OBJECT (sink, "could not set TOS: %s", g_strerror (errno));
+    }
 #ifdef IPV6_TCLASS
-  if (setsockopt (sink->sock, IPPROTO_IPV6, IPV6_TCLASS, &tos,
-          sizeof (tos)) < 0) {
-    GST_ERROR_OBJECT (sink, "could not set TCLASS: %s", g_strerror (errno));
+    /* If we have a sock6, then this isn't an IPv6 socket, so don't try to set this. */
+    if (sink->sock6 == -1) {
+      GST_DEBUG_OBJECT (sink, "setting TCLASS to %d", sink->qos_dscp);
+
+      if (setsockopt (sink->sock, IPPROTO_IPV6, IPV6_TCLASS, &tos,
+              sizeof (tos)) < 0) {
+        GST_ERROR_OBJECT (sink, "could not set TCLASS: %s", g_strerror (errno));
+      }
+    }
+#endif
   }
+
+  if (sink->sock6 != -1) {
+    GST_DEBUG_OBJECT (sink, "setting TOS to %d", sink->qos_dscp);
+
+    if (setsockopt (sink->sock6, IPPROTO_IP, IP_TOS, &tos, sizeof (tos)) < 0) {
+      GST_ERROR_OBJECT (sink, "could not set TOS: %s", g_strerror (errno));
+    }
+#ifdef IPV6_TCLASS
+    GST_DEBUG_OBJECT (sink, "setting TCLASS to %d", sink->qos_dscp);
+
+    if (setsockopt (sink->sock6, IPPROTO_IPV6, IPV6_TCLASS, &tos,
+            sizeof (tos)) < 0) {
+      GST_ERROR_OBJECT (sink, "could not set TCLASS: %s", g_strerror (errno));
+    }
 #endif
+  }
 }
 
 static void
@@ -529,6 +599,16 @@ gst_multiudpsink_set_property (GObject * object, guint prop_id,
     case PROP_CLOSEFD:
       udpsink->closefd = g_value_get_boolean (value);
       break;
+    case PROP_SOCKFD6:
+      if (udpsink->sockfd6 >= 0 && udpsink->sockfd6 != udpsink->sock6 &&
+          udpsink->closefd6)
+        CLOSE_SOCKET (udpsink->sockfd6);
+      udpsink->sockfd6 = g_value_get_int (value);
+      GST_DEBUG_OBJECT (udpsink, "setting SOCKFD6 to %d", udpsink->sockfd6);
+      break;
+    case PROP_CLOSEFD6:
+      udpsink->closefd6 = g_value_get_boolean (value);
+      break;
     case PROP_CLIENTS:
       gst_multiudpsink_set_clients_string (udpsink, g_value_get_string (value));
       break;
@@ -575,6 +655,15 @@ gst_multiudpsink_get_property (GObject * object, guint prop_id, GValue * value,
     case PROP_SOCK:
       g_value_set_int (value, udpsink->sock);
       break;
+    case PROP_SOCKFD6:
+      g_value_set_int (value, udpsink->sockfd6);
+      break;
+    case PROP_CLOSEFD6:
+      g_value_set_boolean (value, udpsink->closefd6);
+      break;
+    case PROP_SOCK6:
+      g_value_set_int (value, udpsink->sock6);
+      break;
     case PROP_CLIENTS:
       g_value_take_string (value,
           gst_multiudpsink_get_clients_string (udpsink));
@@ -605,28 +694,130 @@ gst_multiudpsink_init_send (GstMultiUDPSink * sink)
   GList *clients;
   GstUDPClient *client;
 
-  if (sink->sockfd == -1) {
-    /* create sender socket try IP6, fall back to IP4 */
-    if ((sink->sock = socket (AF_INET6, SOCK_DGRAM, 0)) == -1)
-      if ((sink->sock = socket (AF_INET, SOCK_DGRAM, 0)) == -1)
+  if (sink->sockfd != -1 && sink->sockfd6 != -1) {
+    /* User has supplied two FDs, so use them. */
+    sink->sock = sink->sockfd;
+    sink->externalfd = TRUE;
+
+    sink->sock6 = sink->sockfd6;
+    sink->externalfd6 = TRUE;
+
+    sink->dualstack = FALSE;
+  } else if (sink->dualstack) {
+    int v6only;
+    if (sink->sockfd == -1) {
+      /* create sender socket for (dual-stack) IPv6 */
+      if ((sink->sock = socket (AF_INET6, SOCK_DGRAM, 0)) < 0)
+        goto no_socket;
+
+      /* Turn off v6-only to make the socket dual-stack */
+      v6only = 0;
+      /* This failing should be impossible, since we determined that
+         dual-stack works already */
+      if (setsockopt (sink->sock, IPPROTO_IPV6, IPV6_V6ONLY,
+              (char *) &v6only, sizeof (v6only)) < 0)
+        goto no_socket;
+
+      GST_DEBUG_OBJECT (sink, "Dual-stack socket FD: %d", sink->sock);
+
+      sink->externalfd = FALSE;
+    } else {
+      struct sockaddr_storage sa;
+      socklen_t slen = sizeof (sa);
+
+      /* we use the configured socket */
+      sink->sock = sink->sockfd;
+      sink->externalfd = TRUE;
+
+      /* If the user-supplied socket is a v6 socket, then make it dual-stack
+       * so we can use v4 on it too */
+      if (getsockname (sink->sock, (struct sockaddr *) &sa, &slen) < 0)
         goto no_socket;
 
-    sink->externalfd = FALSE;
+      if (sa.ss_family == AF_INET6) {
+        /* Turn off v6-only to make the socket dual-stack */
+        v6only = 0;
+        /* This failing should be impossible, since we determined that
+           dual-stack works already */
+        if (setsockopt (sink->sock, IPPROTO_IPV6, IPV6_V6ONLY,
+                (char *) &v6only, sizeof (v6only)) < 0)
+          goto no_socket;
+      } else {
+        GST_INFO_OBJECT (sink,
+            "IPv6 not available since application-supplied socket is IPv4");
+
+        /* Now we need to fix up any IPv4-mapped IPv6 addresses for
+         * already-present clients */
+        for (clients = sink->clients; clients; clients = g_list_next (clients)) {
+          client = (GstUDPClient *) clients->data;
+
+          if (client->theiraddr.ss_family == AF_INET6) {
+            /* Surely there must be a better way to do this... */
+            struct sockaddr_in6 addr6;
+            struct sockaddr_in *addr =
+                (struct sockaddr_in *) &client->theiraddr;
+
+            memcpy (&addr6, &client->theiraddr, sizeof (struct sockaddr_in6));
+
+            addr->sin_family = AF_INET;
+            addr->sin_port = addr6.sin6_port;
+            addr->sin_addr.s_addr = ((guint32 *) & addr6.sin6_addr)[3];
+          }
+        }
+      }
+    }
   } else {
-    /* we use the configured socket */
-    sink->sock = sink->sockfd;
-    sink->externalfd = TRUE;
+    /* Not dual-stack capable. Create two sockets. */
+
+    if (sink->sockfd == -1) {
+      /* create sender socket for IPv4 */
+      if ((sink->sock = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
+        goto no_socket;
+      GST_DEBUG_OBJECT (sink, "IPv4 socket: %d", sink->sock);
+
+      sink->externalfd = FALSE;
+    } else {
+      /* we use the configured socket */
+      sink->sock = sink->sockfd;
+      sink->externalfd = TRUE;
+    }
+
+    if (sink->sockfd6 == -1) {
+      /* create sender socket for IPv6 */
+      if ((sink->sock6 = socket (AF_INET6, SOCK_DGRAM, 0)) < 0) {
+        /* Failing this is ok - it just means we don't have IPv6 support */
+#ifdef G_OS_WIN32
+        if (WSAGetLastError () != WSAEAFNOSUPPORT)
+#else
+        if (errno != EAFNOSUPPORT)
+#endif
+          goto no_socket;
+      }
+      GST_DEBUG_OBJECT (sink, "IPv6 socket: %d", sink->sock6);
+
+      sink->externalfd6 = FALSE;
+    } else {
+      /* we use the configured socket */
+      sink->sock6 = sink->sockfd6;
+      sink->externalfd6 = TRUE;
+    }
   }
 
   bc_val = 1;
-  if (setsockopt (sink->sock, SOL_SOCKET, SO_BROADCAST, &bc_val,
-          sizeof (bc_val)) < 0)
+  if (setsockopt (sink->sock, SOL_SOCKET, SO_BROADCAST,
+          &bc_val, sizeof (bc_val)) < 0)
+    goto no_broadcast;
+
+  if (sink->sock6 != -1 && setsockopt (sink->sock6, SOL_SOCKET, SO_BROADCAST,
+          &bc_val, sizeof (bc_val)) < 0)
     goto no_broadcast;
 
   sink->bytes_to_serve = 0;
   sink->bytes_served = 0;
 
   gst_udp_set_loop_ttl (sink->sock, sink->loop, sink->ttl);
+  if (sink->sock6 != -1)
+    gst_udp_set_loop_ttl (sink->sock6, sink->loop, sink->ttl);
   gst_multiudpsink_setup_qos_dscp (sink);
 
   /* look for multicast clients and join multicast groups appropriately */
@@ -666,16 +857,31 @@ gst_multiudpsink_add_internal (GstMultiUDPSink * sink, const gchar * host,
 {
   GstUDPClient *client;
   GTimeVal now;
+  int family;
 
   GST_DEBUG_OBJECT (sink, "adding client on host %s, port %d", host, port);
   client = g_new0 (GstUDPClient, 1);
   client->host = g_strdup (host);
   client->port = port;
-  client->sock = &sink->sock;
 
-  if (gst_udp_get_addr (host, port, &client->theiraddr) < 0)
+  if (sink->dualstack)
+    family = AF_INET6;
+  else
+    family = AF_UNSPEC;
+
+  if (gst_udp_get_addr (host, port, &client->theiraddr, family) < 0)
     goto getaddrinfo_error;
 
+  /* point the client to correct socket family */
+  if (sink->dualstack)
+    client->sock = &sink->sock;
+  else {
+    if (client->theiraddr.ss_family == AF_INET6)
+      client->sock = &sink->sock6;
+    else
+      client->sock = &sink->sock;
+  }
+
   g_get_current_time (&now);
   client->connect_time = GST_TIMEVAL_TO_TIME (now);
 
diff --git a/gst/udp/gstmultiudpsink.h b/gst/udp/gstmultiudpsink.h
index e9543ed..a9b2942 100644
--- a/gst/udp/gstmultiudpsink.h
+++ b/gst/udp/gstmultiudpsink.h
@@ -38,7 +38,7 @@ typedef struct _GstMultiUDPSink GstMultiUDPSink;
 typedef struct _GstMultiUDPSinkClass GstMultiUDPSinkClass;
 
 typedef struct {
-  int *sock;
+  int *sock; /* Pointer to the socket FD we're using for this client */
 
   struct sockaddr_storage theiraddr;
 
@@ -57,18 +57,40 @@ typedef struct {
 struct _GstMultiUDPSink {
   GstBaseSink parent;
 
-  int sock;
-
   GMutex        *client_lock;
   GList         *clients;
 
   /* properties */
   guint64        bytes_to_serve;
   guint64        bytes_served;
-  int            sockfd;
-  gboolean       closefd;
 
-  gboolean       externalfd;
+  /* If we have a dual-stack (IPv4 and IPv6) capable system, we use 'sock' for
+   * all connections. If it's two independent stacks (or IPv6 isn't 
+   * supported at all), then 'sock' is for IPv4 only, and 'sock6' is used for IPv6).
+   */
+  gboolean       dualstack;
+#if 0
+   *
+   * if dualstack
+   *   use sock
+   * else
+   *   if addr is v4
+   *     use sock
+   *   else
+   *     use sock6
+#endif
+
+  int            sock;        /* Actual socket FD */
+  int            sockfd;      /* The FD for the socket to use, or -1 if we're 
+                                 going to allocate a socket ourselves */
+  gboolean       closefd;     /* TRUE if we should close an externally-
+                                 supplied FD when we stop */
+  gboolean       externalfd;  /* TRUE if the FD is externally supplied */
+
+  int            sock6;
+  int            sockfd6;
+  gboolean       closefd6;
+  gboolean       externalfd6;
 
   gboolean       auto_multicast;
   gint           ttl;
diff --git a/gst/udp/gstudpnetutils.c b/gst/udp/gstudpnetutils.c
index 86c1f50..356b370 100644
--- a/gst/udp/gstudpnetutils.c
+++ b/gst/udp/gstudpnetutils.c
@@ -77,18 +77,29 @@ gst_udp_get_sockaddr_length (struct sockaddr_storage *addr)
 }
 
 int
-gst_udp_get_addr (const char *hostname, int port, struct sockaddr_storage *addr)
+gst_udp_get_addr (const char *hostname, int port, struct sockaddr_storage *addr,
+    int sock_family)
 {
-  struct addrinfo hints, *res, *nres;
+  struct addrinfo hints, *res = NULL, *nres;
   char service[NI_MAXSERV];
   int ret;
 
   memset (&hints, 0, sizeof (hints));
-  hints.ai_family = AF_UNSPEC;
+  hints.ai_family = sock_family;
   hints.ai_socktype = SOCK_DGRAM;
   g_snprintf (service, sizeof (service) - 1, "%d", port);
   service[sizeof (service) - 1] = '\0';
 
+  /* Create v4-mapped addresses if we have a v6 socket but a v4 address */
+  if (sock_family == AF_INET6) {
+    hints.ai_flags = AI_V4MAPPED;
+
+    /* Linux (glibc < 2.8, at least) has a broken implementation of AI_V4MAPPED
+     * which only works if you also pass AI_ALL.
+     */
+    hints.ai_flags = hints.ai_flags | AI_ALL;
+  }
+
   if ((ret = getaddrinfo (hostname, (port == -1) ? NULL : service, &hints,
               &res)) < 0) {
     goto beach;
@@ -96,11 +107,55 @@ gst_udp_get_addr (const char *hostname, int port, struct sockaddr_storage *addr)
 
   nres = res;
   while (nres) {
-    if (nres->ai_family == AF_INET || nres->ai_family == AF_INET6)
+    if (sock_family == AF_UNSPEC &&
+        (nres->ai_family == AF_INET || nres->ai_family == AF_INET6))
+      break;
+    else if (nres->ai_family == sock_family)
       break;
     nres = nres->ai_next;
   }
 
+#ifndef G_OS_WIN32
+  /* If we didn't accept any of the results, but we have a v4 address when
+     looking for a v6 address, try it again as a v4mapped address.
+     This can happen if we look up a hostname (rather than an IP); we get a
+     V4 address only - we can then look up THAT address as a v4-mapped address,
+     and will hopefully get a v4mapped address. As an example, looking up
+     'localhost' returns only a v4 address, but we require a v6 address.
+   */
+  if (!nres && res && res->ai_family == AF_INET && sock_family == AF_INET6) {
+    char addrbuf[INET_ADDRSTRLEN];
+    const char *addr;
+
+    memset (&hints, 0, sizeof (hints));
+    hints.ai_family = AF_INET6;
+    hints.ai_socktype = SOCK_DGRAM;
+    hints.ai_flags = AI_V4MAPPED | AI_ALL;
+
+    addr = inet_ntop (AF_INET,
+        &((struct sockaddr_in *) (res->ai_addr))->sin_addr,
+        addrbuf, sizeof (addrbuf));
+    if (!addr)
+      goto beach;
+
+    /* free the old one, try the new one again */
+    freeaddrinfo (res);
+    res = NULL;
+
+    if ((ret = getaddrinfo (addr, (port == -1) ? NULL : service, &hints,
+                &res)) < 0) {
+      goto beach;
+    }
+
+    nres = res;
+    while (nres) {
+      if (nres->ai_family == AF_INET6)
+        break;
+      nres = nres->ai_next;
+    }
+  }
+#endif
+
   if (nres) {
     memcpy (addr, nres->ai_addr, nres->ai_addrlen);
   } else {
@@ -108,7 +163,8 @@ gst_udp_get_addr (const char *hostname, int port, struct sockaddr_storage *addr)
   }
 
 beach:
-  freeaddrinfo (res);
+  if (res)
+    freeaddrinfo (res);
   return ret;
 }
 
diff --git a/gst/udp/gstudpnetutils.h b/gst/udp/gstudpnetutils.h
index 04d847c..953a92d 100644
--- a/gst/udp/gstudpnetutils.h
+++ b/gst/udp/gstudpnetutils.h
@@ -77,7 +77,8 @@ gboolean gst_udp_net_utils_win32_wsa_startup (GstObject * obj);
 
 int gst_udp_get_sockaddr_length(struct sockaddr_storage *addr);
 
-int gst_udp_get_addr      (const char *hostname, int port, struct sockaddr_storage *addr);
+int gst_udp_get_addr      (const char *hostname, int port, struct sockaddr_storage *addr,
+        int sock_family);
 int gst_udp_is_multicast  (struct sockaddr_storage *addr);
 
 int gst_udp_set_loop_ttl  (int sockfd, gboolean loop, int ttl);
diff --git a/gst/udp/gstudpsrc.c b/gst/udp/gstudpsrc.c
index c84e46c..092ed8a 100644
--- a/gst/udp/gstudpsrc.c
+++ b/gst/udp/gstudpsrc.c
@@ -803,7 +803,8 @@ gst_udpsrc_start (GstBaseSrc * bsrc)
     GST_DEBUG_OBJECT (src, "allocating socket for %s:%d", src->multi_group,
         src->port);
     if ((ret =
-            gst_udp_get_addr (src->multi_group, src->port, &src->myaddr)) < 0)
+            gst_udp_get_addr (src->multi_group, src->port, &src->myaddr,
+                AF_UNSPEC)) < 0)
       goto getaddrinfo_error;
 
     if ((ret = socket (src->myaddr.ss_family, SOCK_DGRAM, IPPROTO_UDP)) < 0)
