+
+#include "LiveSupport/Core/Ptr.h"
+#include "LiveSupport/Core/Configurable.h"
+
+
+namespace LiveSupport {
+namespace Core {
+
+using namespace LiveSupport::Core;
+
+/* ================================================================ constants */
+
+
+/* =================================================================== macros */
+
+
+/* =============================================================== data types */
+
+/**
+ * A class for representing an RDS key - value pair.
+ *
+ * This object has to be configured with an XML configuration element
+ * called rdsItem. This may look like the following:
+ *
+ *
+ * <rdsItem key = "PS"
+ * value = "BBC Four"
+ * enabled = "1" />
+ *
+ *
+ * The possible key values are PS, PI, RT, etc
+ * (see http://en.wikipedia.org/wiki/Radio_Data_System).
+ *
+ * There value attribute can be any string.
+ *
+ * The enabled attribute is either 0 (disabled) or 1 (enabled).
+ *
+ * The DTD for the expected XML element looks like the following:
+ *
+ *
+ * <!ELEMENT rdsItem EMPTY >
+ * <!ATTLIST rdsItem key CDATA #REQUIRED >
+ * <!ATTLIST rdsItem value CDATA #REQUIRED >
+ * <!ATTLIST rdsItem enabled CDATA #REQUIRED >
+ *
+ *
+ *
+ * @author $Author$
+ * @version $Revision$
+ * @see RdsItemContainer
+ */
+class RdsItem : public Configurable
+{
+ private:
+ /**
+ * The name of the configuration XML element used by RdsItem.
+ */
+ static const std::string configElementName;
+
+ /**
+ * The key for this RDS item.
+ */
+ Ptr::Ref key;
+
+ /**
+ * The value for this RDS item.
+ */
+ Ptr::Ref value;
+
+ /**
+ * The enabled/disabled attribute for this RDS item.
+ */
+ bool enabled;
+
+ /**
+ * An XML document used by toXmlElement().
+ */
+ Ptr::Ref xmlDocument;
+
+ /**
+ * Set to true by setValue(), and to false by toXmlElement().
+ */
+ bool touched;
+
+
+ public:
+ /**
+ * Default constructor.
+ */
+ RdsItem() throw ()
+ : enabled(false),
+ touched(false)
+ {
+ }
+
+ /**
+ * Constructor which sets the variables.
+ */
+ RdsItem(Ptr::Ref key,
+ Ptr::Ref value,
+ bool enabled = false) throw ()
+ : key(key),
+ value(value),
+ enabled(enabled),
+ touched(false)
+ {
+ }
+
+ /**
+ * A virtual destructor, as this class has virtual functions.
+ */
+ virtual
+ ~RdsItem(void) throw ()
+ {
+ }
+
+ /**
+ * Return the name of the XML element this object expects
+ * to be sent to a call to configure().
+ *
+ * @return the name of the expected XML configuration element.
+ */
+ static const std::string
+ getConfigElementName(void) throw ()
+ {
+ return configElementName;
+ }
+
+ /**
+ * Configure the object based on an XML configuration element.
+ *
+ * @param elemen the XML configuration element.
+ * @exception std::invalid_argument if the supplied XML element
+ * contains bad configuration information
+ */
+ virtual void
+ configure(const xmlpp::Element &element)
+ throw (std::invalid_argument);
+
+ /**
+ * Get the key.
+ * The key can be a 0 pointer if the object has not been
+ * configured yet.
+ *
+ * @return the key of this RDS item.
+ */
+ Ptr::Ref
+ getKey(void) throw ()
+ {
+ return key;
+ }
+
+ /**
+ * Get the value.
+ * The value can be a 0 pointer if the object has not been
+ * configured yet.
+ *
+ * @return the key of this RDS item.
+ */
+ Ptr::Ref
+ getValue(void) throw ()
+ {
+ return value;
+ }
+
+ /**
+ * Set the value.
+ *
+ * @param value the new value of this RDS item.
+ */
+ void
+ setValue(Ptr::Ref value) throw ()
+ {
+ this->value = value;
+ touched = true;
+ }
+
+ /**
+ * Get the enabled/disabled flag.
+ *
+ * @return true if the RDS item is enabled, false if not.
+ */
+ bool
+ isEnabled(void) throw ()
+ {
+ return enabled;
+ }
+
+ /**
+ * Set the enabled/disabled flag.
+ *
+ * @param enabled the new value of the flag.
+ */
+ void
+ setEnabled(bool enabled) throw ()
+ {
+ this->enabled = enabled;
+ touched = true;
+ }
+
+ /**
+ * Convert the object to XML.
+ *
+ * @return an XML Element, which can be passed to configure()
+ * to create an object identical to this one.
+ */
+ const xmlpp::Element *
+ toXmlElement(void) throw ();
+
+ /**
+ * Tells you whether the object has been touched since the last save.
+ * Starts out false; set to true by setValue() and setEnabled();
+ * set back to false by toXmlElement().
+ *
+ * @return whether the object has been touched.
+ */
+ bool
+ isTouched(void) throw ()
+ {
+ return touched;
+ }
+};
+
+
+/* ================================================= external data structures */
+
+
+/* ====================================================== function prototypes */
+
+
+} // namespace Core
+} // namespace LiveSupport
+
+#endif // LiveSupport_Core_RdsItem_h
+
diff --git a/campcaster/src/modules/core/src/OptionsContainer.cxx b/campcaster/src/modules/core/src/OptionsContainer.cxx
index f92bc46de..f337ccd29 100644
--- a/campcaster/src/modules/core/src/OptionsContainer.cxx
+++ b/campcaster/src/modules/core/src/OptionsContainer.cxx
@@ -65,6 +65,14 @@ OptionsContainer :: OptionsContainer(
{
optionsDocument.create_root_node_by_import(&optionsElement, true);
// true == recursive
+
+ xmlpp::Node::NodeList nodes = optionsElement.get_children(
+ RdsContainer::getConfigElementName());
+ if (nodes.size() > 0) {
+ rdsContainer.reset(new RdsContainer());
+ rdsContainer->configure(
+ *dynamic_cast(nodes.front()));
+ }
}
@@ -156,6 +164,37 @@ OptionsContainer :: setKeyboardShortcutItem(
}
+/*------------------------------------------------------------------------------
+ * Set the value of an RDS string.
+ *----------------------------------------------------------------------------*/
+void
+OptionsContainer :: setRdsString(Ptr::Ref key,
+ Ptr::Ref value)
+ throw ()
+{
+ if (!rdsContainer) {
+ rdsContainer.reset(new RdsContainer());
+ }
+
+ rdsContainer->setRdsString(key, value);
+}
+
+
+/*------------------------------------------------------------------------------
+ * Get the value of an RDS string.
+ *----------------------------------------------------------------------------*/
+Ptr::Ref
+OptionsContainer :: getRdsString(Ptr::Ref key)
+ throw ()
+{
+ Ptr::Ref value;
+ if (rdsContainer) {
+ value = rdsContainer->getRdsString(key);
+ }
+ return value;
+}
+
+
/*------------------------------------------------------------------------------
* Find the node corresponding to an OptionItemString value.
*----------------------------------------------------------------------------*/
@@ -289,6 +328,16 @@ void
OptionsContainer :: writeToFile(void) throw ()
{
if (configFileName) {
+ if (rdsContainer && rdsContainer->isTouched()) {
+ xmlpp::Element * rootNode = optionsDocument.get_root_node();
+ xmlpp::Node::NodeList nodes = rootNode->get_children(
+ RdsContainer::getConfigElementName());
+ if (nodes.size() > 0) {
+ rootNode->remove_child(nodes.front());
+ }
+ rootNode->import_node(rdsContainer->toXmlElement(), true);
+ }
+
std::ofstream file(configFileName->c_str());
if (file.good()) {
optionsDocument.write_to_stream_formatted(file, "utf-8");
diff --git a/campcaster/src/modules/core/src/RdsContainer.cxx b/campcaster/src/modules/core/src/RdsContainer.cxx
new file mode 100644
index 000000000..dee5b06f8
--- /dev/null
+++ b/campcaster/src/modules/core/src/RdsContainer.cxx
@@ -0,0 +1,158 @@
+/*------------------------------------------------------------------------------
+
+ Copyright (c) 2004 Media Development Loan Fund
+
+ This file is part of the Campcaster project.
+ http://campcaster.campware.org/
+ To report bugs, send an e-mail to bugs@campware.org
+
+ Campcaster 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.
+
+ Campcaster 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 Campcaster; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+ Author : $Author$
+ Version : $Revision$
+ Location : $URL$
+
+------------------------------------------------------------------------------*/
+
+/* ============================================================ include files */
+
+#ifdef HAVE_CONFIG_H
+#include "configure.h"
+#endif
+
+#include "LiveSupport/Core/RdsContainer.h"
+
+
+using namespace LiveSupport::Core;
+using namespace LiveSupport::Core;
+
+/* =================================================== local data structures */
+
+
+/* ================================================ local constants & macros */
+
+/**
+ * The name of the config element for this class
+ */
+const std::string RdsContainer::configElementName = "rdsContainer";
+
+
+/* =============================================== local function prototypes */
+
+
+/* ============================================================= module code */
+
+/*------------------------------------------------------------------------------
+ * Create an RDS container object based on an XML element.
+ *----------------------------------------------------------------------------*/
+void
+RdsContainer :: configure(const xmlpp::Element & element)
+ throw (std::invalid_argument)
+{
+ if (element.get_name() != configElementName) {
+ throw std::invalid_argument("bad coniguration element "
+ + element.get_name());
+ }
+
+ xmlpp::Node::NodeList childNodes = element.get_children(
+ RdsItem::getConfigElementName());
+ xmlpp::Node::NodeList::const_iterator it;
+
+ rdsItemList.clear();
+ for (it = childNodes.begin(); it != childNodes.end(); ++it) {
+ const xmlpp::Element * rdsItemElement
+ = dynamic_cast (*it);
+
+ Ptr::Ref rdsItem(new RdsItem());
+ rdsItem->configure(*rdsItemElement);
+
+ rdsItemList.push_back(rdsItem);
+ }
+}
+
+
+/*------------------------------------------------------------------------------
+ * Set the value of an RDS string.
+ *----------------------------------------------------------------------------*/
+void
+RdsContainer :: setRdsString(Ptr::Ref key,
+ Ptr::Ref value)
+ throw ()
+{
+ RdsItemListType::const_iterator it;
+
+ bool found = false;
+ for(it = rdsItemList.begin(); it != rdsItemList.end(); ++it) {
+ Ptr::Ref rdsItem = *it;
+ if (*rdsItem->getKey() == *key) {
+ found = true;
+ rdsItem->setValue(value);
+ break;
+ }
+ }
+
+ if (!found) {
+ Ptr::Ref rdsItem(new RdsItem(key, value));
+ rdsItemList.push_back(rdsItem);
+ }
+
+ touched = true;
+}
+
+
+/*------------------------------------------------------------------------------
+ * Get the value of an RDS string.
+ *----------------------------------------------------------------------------*/
+Ptr::Ref
+RdsContainer :: getRdsString(Ptr::Ref key)
+ throw ()
+{
+ RdsItemListType::const_iterator it;
+ for(it = rdsItemList.begin(); it != rdsItemList.end(); ++it) {
+ Ptr::Ref rdsItem = *it;
+ if (*rdsItem->getKey() == *key) {
+ return rdsItem->getValue();
+ }
+ }
+
+ Ptr::Ref nullPointer;
+ return nullPointer;
+}
+
+
+/*------------------------------------------------------------------------------
+ * Convert the object to XML.
+ *----------------------------------------------------------------------------*/
+const xmlpp::Element *
+RdsContainer :: toXmlElement(void) throw ()
+{
+ if (!touched && xmlDocument) {
+ return xmlDocument->get_root_node();
+ }
+
+ xmlDocument.reset(new xmlpp::Document());
+ xmlpp::Element * rootNode = xmlDocument->create_root_node(
+ configElementName);
+ RdsItemListType::const_iterator it;
+ for(it = rdsItemList.begin(); it != rdsItemList.end(); ++it) {
+ Ptr::Ref rdsItem = *it;
+ rootNode->import_node(rdsItem->toXmlElement(), true);
+ }
+
+ touched = false;
+ return rootNode;
+}
+
diff --git a/campcaster/src/modules/core/src/RdsContainerTest.cxx b/campcaster/src/modules/core/src/RdsContainerTest.cxx
new file mode 100644
index 000000000..3e79a6cf6
--- /dev/null
+++ b/campcaster/src/modules/core/src/RdsContainerTest.cxx
@@ -0,0 +1,129 @@
+/*------------------------------------------------------------------------------
+
+ Copyright (c) 2004 Media Development Loan Fund
+
+ This file is part of the Campcaster project.
+ http://campcaster.campware.org/
+ To report bugs, send an e-mail to bugs@campware.org
+
+ Campcaster 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.
+
+ Campcaster 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 Campcaster; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+ Author : $Author$
+ Version : $Revision$
+ Location : $URL$
+
+------------------------------------------------------------------------------*/
+
+/* ============================================================ include files */
+
+#ifdef HAVE_CONFIG_H
+#include "configure.h"
+#endif
+
+#if HAVE_UNISTD_H
+#include
+#else
+#error "Need unistd.h"
+#endif
+
+#include
+
+#include "RdsContainerTest.h"
+
+
+using namespace LiveSupport::Core;
+using namespace LiveSupport::Core;
+
+/* =================================================== local data structures */
+
+
+/* ================================================ local constants & macros */
+
+CPPUNIT_TEST_SUITE_REGISTRATION(RdsContainerTest);
+
+namespace {
+
+/**
+ * The name of the test RDS container config file.
+ */
+const std::string configFileName = "etc/rdsContainer.xml";
+
+}
+
+/* =============================================== local function prototypes */
+
+
+/* ============================================================= module code */
+
+/*------------------------------------------------------------------------------
+ * Set up the test environment
+ *----------------------------------------------------------------------------*/
+void
+RdsContainerTest :: setUp(void) throw (CPPUNIT_NS::Exception)
+{
+ std::ifstream ifs;
+ ifs.open(configFileName.c_str());
+
+ if (!ifs.is_open() || ifs.bad()) {
+ ifs.close();
+ CPPUNIT_FAIL("could not open RDS container config file "
+ + configFileName);
+ }
+
+ rdsContainer.reset(new RdsContainer);
+
+ try {
+ Ptr::Ref parser(new xmlpp::DomParser());
+ parser->parse_stream(ifs);
+ parser->set_validate();
+ const xmlpp::Document * document = parser->get_document();
+ const xmlpp::Element * root = document->get_root_node();
+
+ rdsContainer->configure(*root);
+
+ } catch (std::invalid_argument &e) {
+ ifs.close();
+ CPPUNIT_FAIL("semantic error in RDS container configuration file: "
+ + std::string(e.what()));
+ } catch (xmlpp::exception &e) {
+ ifs.close();
+ CPPUNIT_FAIL("syntax error in RDS container configuration file: "
+ + std::string(e.what()));
+ }
+ ifs.close();
+}
+
+
+/*------------------------------------------------------------------------------
+ * Clean up the test environment
+ *----------------------------------------------------------------------------*/
+void
+RdsContainerTest :: tearDown(void) throw ()
+{
+}
+
+
+/*------------------------------------------------------------------------------
+ * A simple test.
+ *----------------------------------------------------------------------------*/
+void
+RdsContainerTest :: firstTest(void)
+ throw (CPPUNIT_NS::Exception)
+{
+ Ptr::Ref key(new Glib::ustring("PS"));
+ CPPUNIT_ASSERT(*rdsContainer->getRdsString(key) == "BBC Four");
+}
+
diff --git a/campcaster/src/modules/core/src/RdsContainerTest.h b/campcaster/src/modules/core/src/RdsContainerTest.h
new file mode 100644
index 000000000..136c885ca
--- /dev/null
+++ b/campcaster/src/modules/core/src/RdsContainerTest.h
@@ -0,0 +1,121 @@
+/*------------------------------------------------------------------------------
+
+ Copyright (c) 2004 Media Development Loan Fund
+
+ This file is part of the Campcaster project.
+ http://campcaster.campware.org/
+ To report bugs, send an e-mail to bugs@campware.org
+
+ Campcaster 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.
+
+ Campcaster 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 Campcaster; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+ Author : $Author$
+ Version : $Revision$
+ Location : $URL$
+
+------------------------------------------------------------------------------*/
+#ifndef RdsContainerTest_h
+#define RdsContainerTest_h
+
+#ifndef __cplusplus
+#error This is a C++ include file
+#endif
+
+
+/* ============================================================ include files */
+
+#ifdef HAVE_CONFIG_H
+#include "configure.h"
+#endif
+
+#include
+
+#include "LiveSupport/Core/Ptr.h"
+#include "LiveSupport/Core/BaseTestMethod.h"
+
+#include "LiveSupport/Core/RdsContainer.h"
+
+
+namespace LiveSupport {
+namespace Core {
+
+using namespace LiveSupport::Core;
+
+/* ================================================================ constants */
+
+
+/* =================================================================== macros */
+
+
+/* =============================================================== data types */
+
+/**
+ * Testing audio playback from the storage.
+ *
+ * @author $Author$
+ * @version $Revision$
+ * @see KeyboardShortcutFactory
+ */
+class RdsContainerTest : public BaseTestMethod
+{
+ CPPUNIT_TEST_SUITE(RdsContainerTest);
+ CPPUNIT_TEST(firstTest);
+ CPPUNIT_TEST_SUITE_END();
+
+ private:
+
+ /**
+ * The RdsContainer object we are testing.
+ */
+ Ptr::Ref rdsContainer;
+
+ protected:
+
+ /**
+ * A simple test.
+ *
+ * @exception CPPUNIT_NS::Exception on test failures.
+ */
+ void
+ firstTest(void) throw (CPPUNIT_NS::Exception);
+
+
+ public:
+
+ /**
+ * Set up the environment for the test case.
+ */
+ void
+ setUp(void) throw (CPPUNIT_NS::Exception);
+
+ /**
+ * Clean up the environment after the test case.
+ */
+ void
+ tearDown(void) throw ();
+};
+
+
+/* ================================================= external data structures */
+
+
+/* ====================================================== function prototypes */
+
+
+} // namespace Core
+} // namespace LiveSupport
+
+#endif // RdsContainerTest_h
+
diff --git a/campcaster/src/modules/core/src/RdsItem.cxx b/campcaster/src/modules/core/src/RdsItem.cxx
new file mode 100644
index 000000000..1c9bc7200
--- /dev/null
+++ b/campcaster/src/modules/core/src/RdsItem.cxx
@@ -0,0 +1,145 @@
+/*------------------------------------------------------------------------------
+
+ Copyright (c) 2004 Media Development Loan Fund
+
+ This file is part of the Campcaster project.
+ http://campcaster.campware.org/
+ To report bugs, send an e-mail to bugs@campware.org
+
+ Campcaster 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.
+
+ Campcaster 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 Campcaster; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+ Author : $Author$
+ Version : $Revision$
+ Location : $URL$
+
+------------------------------------------------------------------------------*/
+
+/* ============================================================ include files */
+
+#ifdef HAVE_CONFIG_H
+#include "configure.h"
+#endif
+
+#include "LiveSupport/Core/RdsItem.h"
+
+
+using namespace LiveSupport::Core;
+using namespace LiveSupport::Core;
+
+/* =================================================== local data structures */
+
+
+/* ================================================ local constants & macros */
+
+/**
+ * The name of the config element for this class
+ */
+const std::string RdsItem::configElementName = "rdsItem";
+
+namespace {
+
+/**
+ * The name of the "key" attribute.
+ */
+const std::string keyAttributeName = "key";
+
+/**
+ * The name of the "value" attribute.
+ */
+const std::string valueAttributeName = "value";
+
+/**
+ * The name of the "enabled" attribute.
+ */
+const std::string enabledAttributeName = "enabled";
+
+}
+
+/* =============================================== local function prototypes */
+
+
+/* ============================================================= module code */
+
+/*------------------------------------------------------------------------------
+ * Create an RDS item object based on an XML element.
+ *----------------------------------------------------------------------------*/
+void
+RdsItem :: configure(const xmlpp::Element & element)
+ throw (std::invalid_argument)
+{
+ if (element.get_name() != configElementName) {
+ throw std::invalid_argument("bad coniguration element "
+ + element.get_name());
+ }
+
+ xmlpp::Attribute * keyAttribute = element.get_attribute(
+ keyAttributeName);
+ if (keyAttribute) {
+ key.reset(new Glib::ustring(keyAttribute->get_value()));
+ } else {
+ throw std::invalid_argument("missing "
+ + keyAttributeName + " attribute");
+ }
+
+ xmlpp::Attribute * valueAttribute = element.get_attribute(
+ valueAttributeName);
+ if (valueAttribute) {
+ key.reset(new Glib::ustring(valueAttribute->get_value()));
+ } else {
+ throw std::invalid_argument("missing "
+ + valueAttributeName + " attribute");
+ }
+
+ xmlpp::Attribute * enabledAttribute = element.get_attribute(
+ enabledAttributeName);
+ if (enabledAttribute) {
+ Glib::ustring enabledString = enabledAttribute->get_value();
+ if (enabledString == "0") {
+ enabled = false;
+ } else if (enabledString == "1") {
+ enabled = true;
+ } else {
+ throw std::invalid_argument("bad "
+ + enabledAttributeName + " attribute");
+ }
+ } else {
+ throw std::invalid_argument("missing "
+ + enabledAttributeName + " attribute");
+ }
+}
+
+
+/*------------------------------------------------------------------------------
+ * Convert the object to XML.
+ *----------------------------------------------------------------------------*/
+const xmlpp::Element *
+RdsItem :: toXmlElement(void) throw ()
+{
+ if (!touched && xmlDocument) {
+ return xmlDocument->get_root_node();
+ }
+
+ xmlDocument.reset(new xmlpp::Document());
+ xmlpp::Element * rootNode = xmlDocument->create_root_node(
+ configElementName);
+ rootNode->set_attribute(keyAttributeName, *key);
+ rootNode->set_attribute(valueAttributeName, *value);
+ rootNode->set_attribute(enabledAttributeName, enabled ? "1" : "0");
+
+ touched = false;
+ return rootNode;
+}
+