summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/modules/osdmodule.cpp
blob: 0fb43d4331abe7737eb00840d400addcb88f570d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// license:BSD-3-Clause
// copyright-holders:Couriersud
/*
 * osdmodule.cpp
 *
 */

#include "modules/osdmodule.h"

#include "emucore.h"

#include "osdcore.h"

#include <algorithm>


osd_module_manager::osd_module_manager()
{
}

osd_module_manager::~osd_module_manager()
{
}

void osd_module_manager::register_module(const module_type &mod_type)
{
	std::unique_ptr<osd_module> module = mod_type();
	if (module->probe())
	{
		osd_printf_verbose("===> registered module %s %s\n", module->name(), module->type());
		m_modules.emplace_back(std::move(module));
	}
	else
	{
		osd_printf_verbose("===> not supported %s %s\n", module->name(), module->type());
	}
}

bool osd_module_manager::type_has_name(const char *type, const char *name) const
{
	return (get_module_index(type, name) >= 0);
}

osd_module *osd_module_manager::get_module_generic(const char *type, const char *name)
{
	int const i = get_module_index(type, name);
	if (i >= 0)
		return m_modules[i].get();
	else
		return nullptr;
}

osd_module &osd_module_manager::select_module(osd_interface &osd, const osd_options &options, const char *type, const char *name)
{
	// see if a module of this type has already been already selected
	for (osd_module &existing : m_selected)
	{
		if (existing.type() == type)
		{
			osd_printf_warning(
					"Attempt to select %s module %s after selecting module %s\n",
					type,
					(name && *name) ? name : "<default>",
					existing.name());
			return existing;
		}
	}

	// try to start the selected module
	osd_module *const m = get_module_generic(type, name);
	if (m)
	{
		//osd_printf_verbose("Attempting to initialize %s module %s\n", type, m->name());
		if (!m->init(osd, options))
		{
			m_selected.emplace_back(*m);
			return *m;
		}
		osd_printf_verbose("Initializing %s module %s failed\n", type, m->name());
	}
	else
	{
		osd_printf_verbose("Could not find %s module %s\n", type, name ? name : "<default>");
	}

	// walk down the list until something works
	for (auto const &fallback : m_modules)
	{
		if ((fallback->type() == type) && (fallback.get() != m))
		{
			osd_printf_verbose("Attempting to initialize %s module %s\n", type, fallback->name());
			if (!fallback->init(osd, options))
			{
				osd_printf_warning(
						m
							?  "Initializing %s module %s failed, falling back to %s\n"
							: "Could not find %s module %s, falling back to %s\n",
						type,
						m ? m->name() : (name && *name) ? name : "<default>",
						fallback->name());
				m_selected.emplace_back(*fallback);
				return *fallback;
			}
		}
	}

	// can't deal with absence of a module, and at least the "none" module should have worked
	throw emu_fatalerror("All %s modules failed to initialize", type);
}

void osd_module_manager::exit()
{
	// Find count
	while (!m_selected.empty())
	{
		m_selected.back().get().exit();
		m_selected.pop_back();
	}
}

int osd_module_manager::get_module_index(const char *type, const char *name) const
{
	for (int i = 0; m_modules.size() > i; i++)
	{
		if ((m_modules[i]->type() == type) && (!name[0] || (m_modules[i]->name() == name)))
			return i;
	}
	return -1;
}

std::vector<std::string_view> osd_module_manager::get_module_names(const char *type) const
{
	std::vector<std::string_view> result;
	for (auto &m : m_modules)
	{
		if (m->type() == type)
			result.emplace_back(m->name());
	}
	return result;
}