+IMPLEMENT_LISTENER (Context, acknowledge_infant);
+void
+Context::acknowledge_infant (SCM sev)
+{
+ infant_event_ = unsmob_stream_event (sev);
+}
+
+IMPLEMENT_LISTENER (Context, set_property_from_event);
+void
+Context::set_property_from_event (SCM sev)
+{
+ Stream_event *ev = unsmob_stream_event (sev);
+
+ SCM sym = ev->get_property ("symbol");
+ if (scm_is_symbol (sym))
+ {
+ SCM val = ev->get_property ("value");
+ bool ok = true;
+ if (val != SCM_EOL)
+ ok = type_check_assignment (sym, val, ly_symbol2scm ("translation-type?"));
+ if (ok)
+ set_property (sym, val);
+ }
+}
+
+IMPLEMENT_LISTENER (Context, unset_property_from_event);
+void
+Context::unset_property_from_event (SCM sev)
+{
+ Stream_event *ev = unsmob_stream_event (sev);
+
+ SCM sym = ev->get_property ("symbol");
+ type_check_assignment (sym, SCM_EOL, ly_symbol2scm ("translation-type?"));
+ unset_property (sym);
+}
+
+/*
+ Creates a new context from a CreateContext event, and sends an
+ AnnounceNewContext event to this context.
+*/
+IMPLEMENT_LISTENER (Context, create_context_from_event);
+void
+Context::create_context_from_event (SCM sev)
+{
+ Stream_event *ev = unsmob_stream_event (sev);
+
+ string id = ly_scm2string (ev->get_property ("id"));
+ SCM ops = ev->get_property ("ops");
+ SCM type_scm = ev->get_property ("type");
+ string type = ly_symbol2string (type_scm);
+
+ vector<Context_def*> path
+ = unsmob_context_def (definition_)->path_to_acceptable_context (type_scm, get_output_def ());
+ if (path.size () != 1)
+ {
+ programming_error (_f ("Invalid CreateContext event: Cannot create %s context", type.c_str ()));
+ return;
+ }
+ Context_def *cdef = path[0];
+
+ Context *new_context = cdef->instantiate (ops);
+
+ new_context->id_string_ = id;
+
+ /* Register various listeners:
+ - Make the new context hear events that universally affect contexts
+ - connect events_below etc. properly */
+ /* We want to be the first ones to hear our own events. Therefore, wait
+ before registering events_below_ */
+ new_context->event_source ()->
+ add_listener (GET_LISTENER (new_context->create_context_from_event),
+ ly_symbol2scm ("CreateContext"));
+ new_context->event_source ()->
+ add_listener (GET_LISTENER (new_context->remove_context),
+ ly_symbol2scm ("RemoveContext"));
+ new_context->event_source ()->
+ add_listener (GET_LISTENER (new_context->change_parent),
+ ly_symbol2scm ("ChangeParent"));
+ new_context->event_source ()->
+ add_listener (GET_LISTENER (new_context->set_property_from_event),
+ ly_symbol2scm ("SetProperty"));
+ new_context->event_source ()->
+ add_listener (GET_LISTENER (new_context->unset_property_from_event),
+ ly_symbol2scm ("UnsetProperty"));
+
+ new_context->events_below_->register_as_listener (new_context->event_source_);
+ this->add_context (new_context);
+
+ new_context->unprotect ();
+
+ Context_def *td = unsmob_context_def (new_context->definition_);
+
+ /* This cannot move before add_context (), because \override
+ operations require that we are in the hierarchy. */
+ td->apply_default_property_operations (new_context);
+ apply_property_operations (new_context, ops);
+
+ send_stream_event (this, "AnnounceNewContext", 0,
+ ly_symbol2scm ("context"), new_context->self_scm (),
+ ly_symbol2scm ("creator"), sev);
+}
+
+Context *
+Context::create_context (Context_def *cdef,
+ string id,
+ SCM ops)
+{
+ infant_event_ = 0;
+ /* TODO: This is fairly misplaced. We can fix this when we have taken out all
+ iterator specific stuff from the Context class */
+ event_source_->
+ add_listener (GET_LISTENER (acknowledge_infant),
+ ly_symbol2scm ("AnnounceNewContext"));
+ /* The CreateContext creates a new context, and sends an announcement of the
+ new context through another event. That event will be stored in
+ infant_event_ to create a return value. */
+ send_stream_event (this, "CreateContext", 0,
+ ly_symbol2scm ("ops"), ops,
+ ly_symbol2scm ("type"), cdef->get_context_name (),
+ ly_symbol2scm ("id"), ly_string2scm (id));
+ event_source_->
+ remove_listener (GET_LISTENER (acknowledge_infant),
+ ly_symbol2scm ("AnnounceNewContext"));
+
+ assert (infant_event_);
+ SCM infant_scm = infant_event_->get_property ("context");
+ Context *infant = unsmob_context (infant_scm);
+
+ if (!infant || infant->get_parent_context () != this)
+ {
+ programming_error ("create_context: can't locate newly created context");
+ return 0;
+ }
+
+ return infant;
+}
+