+
+/**
+ * Adds model to the scenery. The path to the added branch (/models/model[*])
+ * is returned in property "property".
+ */
+static bool
+do_add_model (const SGPropertyNode * arg)
+{
+ SGPropertyNode * model = fgGetNode("models", true);
+ for (int i = 0;; i++) {
+ if (i < 0)
+ return false;
+ if (!model->getChild("model", i, false)) {
+ model = model->getChild("model", i, true);
+ break;
+ }
+ }
+ copyProperties(arg, model);
+ if (model->hasValue("elevation-m"))
+ model->setDoubleValue("elevation-ft", model->getDoubleValue("elevation-m")
+ * SG_METER_TO_FEET);
+ model->getNode("load", true);
+ model->removeChildren("load");
+ const_cast<SGPropertyNode *>(arg)->setStringValue("property", model->getPath());
+ return true;
+}
+
+
+/**
+ * Set mouse cursor coordinates and cursor shape.
+ */
+static bool
+do_set_cursor (const SGPropertyNode * arg)
+{
+ if (arg->hasValue("x") || arg->hasValue("y")) {
+ SGPropertyNode *mx = fgGetNode("/devices/status/mice/mouse/x", true);
+ SGPropertyNode *my = fgGetNode("/devices/status/mice/mouse/y", true);
+ int x = arg->getIntValue("x", mx->getIntValue());
+ int y = arg->getIntValue("y", my->getIntValue());
+ fgWarpMouse(x, y);
+ mx->setIntValue(x);
+ my->setIntValue(y);
+ }
+
+ SGPropertyNode *cursor = const_cast<SGPropertyNode *>(arg)->getNode("cursor", true);
+ if (cursor->getType() != simgear::props::NONE)
+ fgSetMouseCursor(cursor->getIntValue());
+
+ cursor->setIntValue(fgGetMouseCursor());
+ return true;
+}
+
+
+/**
+ * Built-in command: play an audio message (i.e. a wav file) This is
+ * fire and forget. Call this once per message and it will get dumped
+ * into a queue. Messages are played sequentially so they do not
+ * overlap.
+ */
+static bool
+do_play_audio_sample (const SGPropertyNode * arg)
+{
+ string path = arg->getStringValue("path");
+ string file = arg->getStringValue("file");
+ float volume = arg->getFloatValue("volume");
+ // cout << "playing " << path << " / " << file << endl;
+ try {
+ static FGSampleQueue *queue = 0;
+ if ( !queue ) {
+ SGSoundMgr *smgr = globals->get_soundmgr();
+ queue = new FGSampleQueue(smgr, "chatter");
+ queue->tie_to_listener();
+ }
+
+ SGSoundSample *msg = new SGSoundSample(path.c_str(), file.c_str());
+ msg->set_volume( volume );
+ queue->add( msg );
+
+ return true;
+
+ } catch (const sg_io_exception&) {
+ SG_LOG(SG_GENERAL, SG_ALERT, "play-audio-sample: "
+ "failed to load" << path << '/' << file);
+ return false;
+ }
+}
+