// license:BSD-3-Clause // copyright-holders:Nicola Salmoria, Aaron Giles, Vas Crabb /*************************************************************************** output.c General purpose output routines. ***************************************************************************/ #include "emu.h" #include "coreutil.h" #include "modules/output/output_module.h" #define OUTPUT_VERBOSE 0 //************************************************************************** // OUTPUT ITEM //************************************************************************** output_manager::output_item::output_item( output_manager &manager, std::string &&name, u32 id, s32 value) : m_manager(manager) , m_name(std::move(name)) , m_id(id) , m_value(value) , m_notifylist() { } void output_manager::output_item::notify(s32 value) { if (OUTPUT_VERBOSE) m_manager.machine().logerror("Output %s = %d (was %d)\n", m_name, value, m_value); m_value = value; // call the local notifiers first for (auto const ¬ify : m_notifylist) notify(m_name.c_str(), value); // call the global notifiers next for (auto const ¬ify : m_manager.m_global_notifylist) notify(m_name.c_str(), value); } //************************************************************************** // OUTPUT ITEM PROXY //************************************************************************** void output_manager::item_proxy::resolve(device_t &device, std::string const &name) { assert(!m_item); m_item = &device.machine().output().find_or_create_item(name.c_str(), 0); } //************************************************************************** // OUTPUT MANAGER //************************************************************************** //------------------------------------------------- // output_manager - constructor //------------------------------------------------- output_manager::output_manager(running_machine &machine) : m_machine(machine), m_uniqueid(12345) { /* add pause callback */ machine.add_notifier(MACHINE_NOTIFY_PAUSE, machine_notify_delegate(&output_manager::pause, this)); machine.add_notifier(MACHINE_NOTIFY_RESUME, machine_notify_delegate(&output_manager::resume, this)); } /*------------------------------------------------- find_item - find an item based on a string -------------------------------------------------*/ output_manager::output_item* output_manager::find_item(const char *string) { auto item = m_itemtable.find(std::string(string)); if (item != m_itemtable.end()) return &item->second; return nullptr; } /*------------------------------------------------- create_new_item - create a new item -------------------------------------------------*/ output_manager::output_item &output_manager::create_new_item(const char *outname, s32 value) { auto const ins(m_itemtable.emplace( std::piecewise_construct, std::forward_as_tuple(outname), std::forward_as_tuple(*this, outname, m_uniqueid++, value))); assert(ins.second); return ins.first->second; } output_manager::output_item &output_manager::find_or_create_item(const char *outname, s32 value) { output_item *const item = find_item(outname); return item ? *item : create_new_item(outname, value); } /*------------------------------------------------- output_pause - send pause message -------------------------------------------------*/ void output_manager::pause() { set_value("pause", 1); } void output_manager::resume() { set_value("pause", 0); } /*------------------------------------------------- output_set_value - set the value of an output -------------------------------------------------*/ void output_manager::set_value(const char *outname, s32 value) { output_item *const item = find_item(outname); // if no item of that name, create a new one and force notification if (!item) create_new_item(outname, value).notify(value); else item->set(value); // set the new value (notifies on change) } /*------------------------------------------------- output_set_indexed_value - set the value of an indexed output -------------------------------------------------*/ void output_manager::set_indexed_value(const char *basename, int index, int value) { char buffer[100]; char *dest = buffer; /* copy the string */ while (*basename != 0) *dest++ = *basename++; /* append the index */ if (index >= 1000) *dest++ = '0' + ((index / 1000) % 10); if (index >= 100) *dest++ = '0' + ((index / 100) % 10); if (index >= 10) *dest++ = '0' + ((index / 10) % 10); *dest++ = '0' + (index % 10); *dest++ = 0; /* set the value */ set_value(buffer, value); } /*------------------------------------------------- output_get_value - return the value of an output -------------------------------------------------*/ s32 output_manager::get_value(const char *outname) { output_item const *const item = find_item(outname); // if no item, value is 0 return item ? item->get() : 0; } /*------------------------------------------------- output_set_notifier - sets a notifier callback for a particular output, or for all outputs if nullptr is specified -------------------------------------------------*/ void output_manager::set_notifier(const char *outname, output_notifier_func callback, void *param) { // if an item is specified, find/create it if (outname) { output_item *const item = find_item(outname); (item ? *item : create_new_item(outname, 0)).set_notifier(callback, param); } else { m_global_notifylist.emplace_back(callback, param); } } /*------------------------------------------------- output_notify_all - immediately call the given notifier for all outputs -------------------------------------------------*/ void output_manager::notify_all(output_module *module) { for (auto &item : m_itemtable) module->notify(item.second.name().c_str(), item.second.get()); } /*------------------------------------------------- output_name_to_id - returns a unique ID for a given name -------------------------------------------------*/ u32 output_manager::name_to_id(const char *outname) { // if no item, ID is 0 output_item const *const item = find_item(outname); return item ? item->id() : 0; } /*------------------------------------------------- output_id_to_name - returns a name that maps to a given unique ID -------------------------------------------------*/ const char *output_manager::id_to_name(u32 id) { for (auto &item : m_itemtable) if (item.second.id() == id) return item.second.name().c_str(); /* nothing found, return nullptr */ return nullptr; }