mirror of
https://git.citron-emu.org/Citron/Citron.git
synced 2025-03-15 06:44:48 +00:00
feat: Add Home Menu launch support and system improvements
This commit adds support for launching the system Home Menu and implements several system-level improvements: - Add Home Menu launch functionality through new UI action - Implement shutdown/reboot sequence handlers in GlobalStateController - Add support for reserved region extra size in page tables - Enhance audio controller with output management - Expand parental control service capabilities - Add profile service improvements for user management Technical changes: - Add OnHomeMenu() handler to launch QLaunch system applet - Implement m_alias_region_extra_size tracking in page tables - Add new CreateProcessFlag for reserved region extra size - Expand audio controller interface with output management - Add self-controller methods to various services - Implement play timer and profile service improvements The changes primarily focus on system menu integration and core service improvements to better support system functionality.
This commit is contained in:
parent
1c9e17496b
commit
c5e480e55d
16 changed files with 206 additions and 115 deletions
|
@ -1584,6 +1584,7 @@ void GMainWindow::ConnectMenuEvents() {
|
|||
[this]() { OnCabinet(Service::NFP::CabinetMode::StartFormatter); });
|
||||
connect_menu(ui->action_Load_Mii_Edit, &GMainWindow::OnMiiEdit);
|
||||
connect_menu(ui->action_Open_Controller_Menu, &GMainWindow::OnOpenControllerMenu);
|
||||
connect_menu(ui->action_Load_Home_Menu, &GMainWindow::OnHomeMenu);
|
||||
connect_menu(ui->action_Capture_Screenshot, &GMainWindow::OnCaptureScreenshot);
|
||||
|
||||
// TAS
|
||||
|
@ -1619,7 +1620,8 @@ void GMainWindow::UpdateMenuState() {
|
|||
ui->action_Load_Cabinet_Restorer,
|
||||
ui->action_Load_Cabinet_Formatter,
|
||||
ui->action_Load_Mii_Edit,
|
||||
ui->action_Open_Controller_Menu};
|
||||
ui->action_Open_Controller_Menu,
|
||||
ui->action_Load_Home_Menu};
|
||||
|
||||
for (QAction* action : running_actions) {
|
||||
action->setEnabled(emulation_running);
|
||||
|
@ -5324,3 +5326,40 @@ int main(int argc, char* argv[]) {
|
|||
detached_tasks.WaitForAllTasks();
|
||||
return result;
|
||||
}
|
||||
|
||||
void GMainWindow::OnHomeMenu() {
|
||||
constexpr u64 QLaunchId = static_cast<u64>(Service::AM::AppletProgramId::QLaunch);
|
||||
|
||||
// Check if system NAND contents are available
|
||||
auto bis_system = system->GetFileSystemController().GetSystemNANDContents();
|
||||
if (!bis_system) {
|
||||
QMessageBox::warning(this, tr("System Error"),
|
||||
tr("System NAND contents not found. Please verify your firmware installation."));
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to get the QLaunch NCA
|
||||
auto qlaunch_nca = bis_system->GetEntry(QLaunchId, FileSys::ContentRecordType::Program);
|
||||
if (!qlaunch_nca) {
|
||||
QMessageBox::warning(this, tr("System Error"),
|
||||
tr("Home Menu applet not found. Please verify your firmware installation."));
|
||||
return;
|
||||
}
|
||||
|
||||
// Set up applet parameters
|
||||
Service::AM::FrontendAppletParameters params{
|
||||
.program_id = QLaunchId,
|
||||
.applet_id = Service::AM::AppletId::QLaunch,
|
||||
.applet_type = Service::AM::AppletType::SystemApplet
|
||||
};
|
||||
|
||||
// Configure system for QLaunch
|
||||
system->GetFrontendAppletHolder().SetCurrentAppletId(Service::AM::AppletId::QLaunch);
|
||||
|
||||
// Get path and launch
|
||||
const auto nca_path = QString::fromStdString(qlaunch_nca->GetFullPath());
|
||||
UISettings::values.roms_path = QFileInfo(nca_path).path().toStdString();
|
||||
|
||||
// Launch QLaunch with proper parameters
|
||||
BootGame(nca_path, params);
|
||||
}
|
||||
|
|
|
@ -407,6 +407,7 @@ private slots:
|
|||
void OnShutdownBeginDialog();
|
||||
void OnEmulationStopped();
|
||||
void OnEmulationStopTimeExpired();
|
||||
void OnHomeMenu();
|
||||
|
||||
private:
|
||||
QString GetGameListErrorRemoving(InstalledEntryType type) const;
|
||||
|
|
|
@ -17,91 +17,6 @@
|
|||
<iconset resource="citron.qrc">
|
||||
<normaloff>:/img/citron.ico</normaloff>:/img/citron.ico</iconset>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QMainWindow {
|
||||
background-color: #2D2D2D;
|
||||
}
|
||||
|
||||
QMenuBar {
|
||||
background-color: #333333;
|
||||
color: #E0E0E0;
|
||||
border-bottom: 1px solid #404040;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
QMenuBar::item {
|
||||
padding: 4px 8px;
|
||||
background: transparent;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
QMenuBar::item:selected {
|
||||
background: #404040;
|
||||
}
|
||||
|
||||
QMenuBar::item:pressed {
|
||||
background: #505050;
|
||||
}
|
||||
|
||||
QMenu {
|
||||
background-color: #333333;
|
||||
border: 1px solid #404040;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
QMenu::item {
|
||||
padding: 6px 24px 6px 12px;
|
||||
color: #E0E0E0;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
QMenu::item:selected {
|
||||
background-color: #404040;
|
||||
}
|
||||
|
||||
QMenu::separator {
|
||||
height: 1px;
|
||||
background: #404040;
|
||||
margin: 4px 0px;
|
||||
}
|
||||
|
||||
QStatusBar {
|
||||
background-color: #333333;
|
||||
color: #E0E0E0;
|
||||
border-top: 1px solid #404040;
|
||||
}
|
||||
|
||||
QDockWidget {
|
||||
border: 1px solid #404040;
|
||||
titlebar-close-icon: url(close.png);
|
||||
}
|
||||
|
||||
QDockWidget::title {
|
||||
background: #333333;
|
||||
padding: 6px;
|
||||
color: #E0E0E0;
|
||||
}
|
||||
|
||||
QToolBar {
|
||||
background: #333333;
|
||||
border: none;
|
||||
spacing: 3px;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
QToolButton {
|
||||
border-radius: 4px;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
QToolButton:hover {
|
||||
background-color: #404040;
|
||||
}
|
||||
|
||||
QToolButton:pressed {
|
||||
background-color: #505050;
|
||||
}</string>
|
||||
</property>
|
||||
<property name="tabShape">
|
||||
<enum>QTabWidget::Rounded</enum>
|
||||
</property>
|
||||
|
@ -130,7 +45,7 @@ QToolButton:pressed {
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1280</width>
|
||||
<height>29</height>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menu_File">
|
||||
|
@ -254,6 +169,7 @@ QToolButton:pressed {
|
|||
<addaction name="action_Install_Firmware"/>
|
||||
<addaction name="action_Verify_installed_contents"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_Load_Home_Menu"/>
|
||||
<addaction name="menu_cabinet_applet"/>
|
||||
<addaction name="action_Load_Album"/>
|
||||
<addaction name="action_Load_Mii_Edit"/>
|
||||
|
@ -266,7 +182,6 @@ QToolButton:pressed {
|
|||
<property name="title">
|
||||
<string>&Help</string>
|
||||
</property>
|
||||
<addaction name="action_Report_Compatibility"/>
|
||||
<addaction name="action_About"/>
|
||||
</widget>
|
||||
<addaction name="menu_File"/>
|
||||
|
@ -322,7 +237,7 @@ QToolButton:pressed {
|
|||
</action>
|
||||
<action name="action_About">
|
||||
<property name="text">
|
||||
<string>&About citron</string>
|
||||
<string>&About Citron</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Single_Window_Mode">
|
||||
|
@ -457,7 +372,15 @@ QToolButton:pressed {
|
|||
</action>
|
||||
<action name="action_Open_citron_Folder">
|
||||
<property name="text">
|
||||
<string>Open &citron Folder</string>
|
||||
<string>Open &Citron Folder</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Load_Home_Menu">
|
||||
<property name="text">
|
||||
<string>Launch System Menu</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Launch the system Home Menu</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Capture_Screenshot">
|
||||
|
@ -556,16 +479,6 @@ QToolButton:pressed {
|
|||
<string>Install Decryption Keys</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSave">
|
||||
<property name="text">
|
||||
<string>&Save</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionLoad">
|
||||
<property name="text">
|
||||
<string>&Load</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="citron.qrc"/>
|
||||
|
|
|
@ -172,6 +172,7 @@ Result KPageTableBase::InitializeForKernel(bool is_64_bit, KVirtualAddress start
|
|||
m_mapped_unsafe_physical_memory = 0;
|
||||
m_mapped_insecure_memory = 0;
|
||||
m_mapped_ipc_server_memory = 0;
|
||||
m_alias_region_extra_size = 0;
|
||||
|
||||
m_memory_block_slab_manager =
|
||||
m_kernel.GetSystemSystemResource().GetMemoryBlockSlabManagerPointer();
|
||||
|
|
|
@ -208,6 +208,7 @@ private:
|
|||
size_t m_mapped_unsafe_physical_memory{};
|
||||
size_t m_mapped_insecure_memory{};
|
||||
size_t m_mapped_ipc_server_memory{};
|
||||
size_t m_alias_region_extra_size{};
|
||||
mutable KLightLock m_general_lock;
|
||||
mutable KLightLock m_map_physical_memory_lock;
|
||||
KLightLock m_device_map_lock;
|
||||
|
@ -715,6 +716,10 @@ public:
|
|||
return m_address_space_width;
|
||||
}
|
||||
|
||||
size_t GetReservedRegionExtraSize() const {
|
||||
return m_alias_region_extra_size;
|
||||
}
|
||||
|
||||
public:
|
||||
// Linear mapped
|
||||
static u8* GetLinearMappedVirtualPointer(KernelCore& kernel, KPhysicalAddress addr) {
|
||||
|
|
|
@ -472,6 +472,10 @@ public:
|
|||
const KPageTable& GetBasePageTable() const {
|
||||
return m_page_table;
|
||||
}
|
||||
|
||||
size_t GetReservedRegionExtraSize() const {
|
||||
return m_page_table.GetReservedRegionExtraSize();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Kernel
|
||||
|
|
|
@ -153,6 +153,7 @@ enum class InfoType : u32 {
|
|||
ThreadTickCount = 25,
|
||||
IsSvcPermitted = 26,
|
||||
IoRegionHint = 27,
|
||||
ReservedRegionExtraSize = 28,
|
||||
|
||||
MesosphereMeta = 65000,
|
||||
MesosphereCurrentProcess = 65001,
|
||||
|
@ -643,9 +644,13 @@ enum class CreateProcessFlag : u32 {
|
|||
// 11.x+ DisableDeviceAddressSpaceMerge.
|
||||
DisableDeviceAddressSpaceMerge = (1 << 12),
|
||||
|
||||
// 13.x+ EnableReservedRegionExtraSize.
|
||||
EnableReservedRegionExtraSize = (1 << 13),
|
||||
|
||||
// Mask of all flags.
|
||||
All = Is64Bit | AddressSpaceMask | EnableDebug | EnableAslr | IsApplication |
|
||||
PoolPartitionMask | OptimizeMemoryAllocation | DisableDeviceAddressSpaceMerge,
|
||||
PoolPartitionMask | OptimizeMemoryAllocation | DisableDeviceAddressSpaceMerge |
|
||||
EnableReservedRegionExtraSize,
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(CreateProcessFlag);
|
||||
|
||||
|
|
|
@ -317,6 +317,10 @@ public:
|
|||
{1, &IProfileCommon::GetBase, "GetBase"},
|
||||
{10, &IProfileCommon::GetImageSize, "GetImageSize"},
|
||||
{11, &IProfileCommon::LoadImage, "LoadImage"},
|
||||
{20, &IProfileCommon::GetImageSize, "GetLargeImageSize"},
|
||||
{21, &IProfileCommon::LoadImage, "LoadLargeImage"},
|
||||
{30, &IProfileCommon::Unknown, "GetImageId"},
|
||||
{40, &IProfileCommon::GetStableUserId, "GetStableUserId"},
|
||||
};
|
||||
|
||||
RegisterHandlers(functions);
|
||||
|
@ -486,6 +490,20 @@ protected:
|
|||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void Unknown(HLERequestContext& ctx) {
|
||||
LOG_WARNING(Service_ACC, "(STUBBED) called");
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(0);
|
||||
}
|
||||
|
||||
void GetStableUserId(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_ACC, "called");
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(user_id.Hash());
|
||||
}
|
||||
|
||||
ProfileManager& profile_manager;
|
||||
Common::UUID user_id{}; ///< The user id this profile refers to.
|
||||
};
|
||||
|
@ -501,7 +519,12 @@ class IProfileEditor final : public IProfileCommon {
|
|||
public:
|
||||
explicit IProfileEditor(Core::System& system_, Common::UUID user_id_,
|
||||
ProfileManager& profile_manager_)
|
||||
: IProfileCommon{system_, "IProfileEditor", true, user_id_, profile_manager_} {}
|
||||
: IProfileCommon{system_, "IProfileEditor", true, user_id_, profile_manager_} {
|
||||
static const FunctionInfo functions[] = {
|
||||
{30, &IProfileEditor::Unknown, "Unknown"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class ISessionObject final : public ServiceFramework<ISessionObject> {
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "core/core.h"
|
||||
#include "core/hle/service/am/applet_manager.h"
|
||||
#include "core/hle/service/am/service/all_system_applet_proxies_service.h"
|
||||
#include "core/hle/service/am/service/global_state_controller.h"
|
||||
#include "core/hle/service/am/service/library_applet_proxy.h"
|
||||
#include "core/hle/service/am/service/system_applet_proxy.h"
|
||||
#include "core/hle/service/am/window_system.h"
|
||||
|
@ -23,6 +24,7 @@ IAllSystemAppletProxiesService::IAllSystemAppletProxiesService(Core::System& sys
|
|||
{350, nullptr, "OpenSystemApplicationProxy"},
|
||||
{400, nullptr, "CreateSelfLibraryAppletCreatorForDevelop"},
|
||||
{410, nullptr, "GetSystemAppletControllerForDebug"},
|
||||
{450, D<&IAllSystemAppletProxiesService::GetGlobalStateController>, "GetGlobalStateController"},
|
||||
{1000, nullptr, "GetDebugFunctions"},
|
||||
};
|
||||
// clang-format on
|
||||
|
@ -73,6 +75,13 @@ Result IAllSystemAppletProxiesService::OpenLibraryAppletProxyOld(
|
|||
this->OpenLibraryAppletProxy(out_library_applet_proxy, pid, process_handle, attribute));
|
||||
}
|
||||
|
||||
Result IAllSystemAppletProxiesService::GetGlobalStateController(
|
||||
Out<SharedPointer<IGlobalStateController>> out_controller) {
|
||||
LOG_DEBUG(Service_AM, "called");
|
||||
*out_controller = std::make_shared<IGlobalStateController>(this->system);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
std::shared_ptr<Applet> IAllSystemAppletProxiesService::GetAppletFromProcessId(
|
||||
ProcessId process_id) {
|
||||
return m_window_system.GetByAppletResourceUserId(process_id.pid);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/hle/service/am/service/global_state_controller.h"
|
||||
|
||||
namespace Service {
|
||||
|
||||
|
@ -14,6 +15,7 @@ struct Applet;
|
|||
struct AppletAttribute;
|
||||
class ILibraryAppletProxy;
|
||||
class ISystemAppletProxy;
|
||||
class IGlobalStateController;
|
||||
class WindowSystem;
|
||||
|
||||
class IAllSystemAppletProxiesService final
|
||||
|
@ -34,7 +36,8 @@ private:
|
|||
Out<SharedPointer<ILibraryAppletProxy>> out_library_applet_proxy, ClientProcessId pid,
|
||||
InCopyHandle<Kernel::KProcess> process_handle);
|
||||
|
||||
private:
|
||||
Result GetGlobalStateController(Out<SharedPointer<IGlobalStateController>> out_controller);
|
||||
|
||||
std::shared_ptr<Applet> GetAppletFromProcessId(ProcessId pid);
|
||||
|
||||
WindowSystem& m_window_system;
|
||||
|
|
|
@ -15,8 +15,8 @@ IGlobalStateController::IGlobalStateController(Core::System& system_)
|
|||
{0, nullptr, "RequestToEnterSleep"},
|
||||
{1, nullptr, "EnterSleep"},
|
||||
{2, nullptr, "StartSleepSequence"},
|
||||
{3, nullptr, "StartShutdownSequence"},
|
||||
{4, nullptr, "StartRebootSequence"},
|
||||
{3, D<&IGlobalStateController::StartShutdownSequence>, "StartShutdownSequence"},
|
||||
{4, D<&IGlobalStateController::StartRebootSequence>, "StartRebootSequence"},
|
||||
{9, nullptr, "IsAutoPowerDownRequested"},
|
||||
{10, D<&IGlobalStateController::LoadAndApplyIdlePolicySettings>, "LoadAndApplyIdlePolicySettings"},
|
||||
{11, nullptr, "NotifyCecSettingsChanged"},
|
||||
|
@ -58,4 +58,16 @@ Result IGlobalStateController::OpenCradleFirmwareUpdater(
|
|||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IGlobalStateController::StartShutdownSequence() {
|
||||
LOG_INFO(Service_AM, "called");
|
||||
system.Exit();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IGlobalStateController::StartRebootSequence() {
|
||||
LOG_INFO(Service_AM, "called");
|
||||
system.Exit();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace Service::AM
|
||||
|
|
|
@ -18,6 +18,8 @@ public:
|
|||
~IGlobalStateController() override;
|
||||
|
||||
private:
|
||||
Result StartShutdownSequence();
|
||||
Result StartRebootSequence();
|
||||
Result LoadAndApplyIdlePolicySettings();
|
||||
Result ShouldSleepOnBoot(Out<bool> out_should_sleep_on_boot);
|
||||
Result GetHdcpAuthenticationFailedEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
|
|
|
@ -11,8 +11,19 @@
|
|||
namespace Service::Audio {
|
||||
|
||||
IAudioController::IAudioController(Core::System& system_)
|
||||
: ServiceFramework{system_, "audctl"}, service_context{system, "audctl"} {
|
||||
// clang-format off
|
||||
: ServiceFramework{system_, "audctl"}
|
||||
, service_context{system, "audctl"}
|
||||
, m_current_output_target{1} // Initialize with default values
|
||||
, m_current_parameter{0x1388}
|
||||
, m_current_volume{100} {
|
||||
|
||||
// Create notification event first
|
||||
notification_event = service_context.CreateEvent("IAudioController:NotificationEvent");
|
||||
|
||||
// Get system settings service
|
||||
m_set_sys = system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true);
|
||||
|
||||
// Register handlers
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetTargetVolume"},
|
||||
{1, nullptr, "SetTargetVolume"},
|
||||
|
@ -67,15 +78,15 @@ IAudioController::IAudioController(Core::System& system_)
|
|||
{10104, nullptr, "GetAudioOutputChannelCountForPlayReport"},
|
||||
{10105, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
|
||||
{10106, nullptr, "GetDefaultAudioOutputTargetForPlayReport"},
|
||||
{50000, nullptr, "SetAnalogInputBoostGainForPrototyping"},
|
||||
{5000, D<&IAudioController::GetSelfController>, "GetSelfController"},
|
||||
{50001, D<&IAudioController::SetAudioControllerOutput>, "SetAudioControllerOutput"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
|
||||
m_set_sys =
|
||||
system.ServiceManager().GetService<Service::Set::ISystemSettingsServer>("set:sys", true);
|
||||
notification_event = service_context.CreateEvent("IAudioController:NotificationEvent");
|
||||
// Signal initial state
|
||||
if (notification_event) {
|
||||
notification_event->Signal();
|
||||
}
|
||||
}
|
||||
|
||||
IAudioController::~IAudioController() {
|
||||
|
@ -176,4 +187,34 @@ Result IAudioController::AcquireTargetNotification(
|
|||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IAudioController::SetAudioControllerOutput(u32 output_target, u32 parameter, u32 volume) {
|
||||
LOG_DEBUG(Audio, "called. output_target={}, parameter={}, volume={}", output_target, parameter, volume);
|
||||
|
||||
if (!notification_event) {
|
||||
LOG_ERROR(Audio, "Notification event not initialized");
|
||||
R_THROW(ResultCode::ResultInvalidState);
|
||||
}
|
||||
|
||||
m_current_output_target = output_target;
|
||||
m_current_parameter = parameter;
|
||||
m_current_volume = volume;
|
||||
|
||||
notification_event->Signal();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IAudioController::GetSelfController(Out<SharedPointer<IAudioController>> out_controller) {
|
||||
LOG_DEBUG(Audio, "called");
|
||||
|
||||
// Use ServiceFramework's built-in method to get a shared pointer
|
||||
*out_controller = SharedPointer<IAudioController>(this);
|
||||
|
||||
// Signal notification event since we're returning a new interface
|
||||
if (notification_event) {
|
||||
notification_event->Signal();
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace Service::Audio
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/hle/service/set/settings_types.h"
|
||||
#include "core/hle/result.h"
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
|
@ -17,6 +18,10 @@ class ISystemSettingsServer;
|
|||
|
||||
namespace Service::Audio {
|
||||
|
||||
namespace ResultCode {
|
||||
constexpr Result ResultInvalidState{ErrorModule::Audio, 1};
|
||||
} // namespace ResultCode
|
||||
|
||||
class IAudioController final : public ServiceFramework<IAudioController> {
|
||||
public:
|
||||
explicit IAudioController(Core::System& system_);
|
||||
|
@ -49,11 +54,18 @@ private:
|
|||
Result SetSpeakerAutoMuteEnabled(bool is_speaker_auto_mute_enabled);
|
||||
Result IsSpeakerAutoMuteEnabled(Out<bool> out_is_speaker_auto_mute_enabled);
|
||||
Result AcquireTargetNotification(OutCopyHandle<Kernel::KReadableEvent> out_notification_event);
|
||||
Result SetAudioControllerOutput(u32 output_target, u32 parameter, u32 volume);
|
||||
Result GetSelfController(Out<SharedPointer<IAudioController>> out_controller);
|
||||
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
|
||||
Kernel::KEvent* notification_event;
|
||||
std::shared_ptr<Service::Set::ISystemSettingsServer> m_set_sys;
|
||||
|
||||
// Add state tracking
|
||||
u32 m_current_output_target{0};
|
||||
u32 m_current_parameter{0};
|
||||
u32 m_current_volume{0};
|
||||
};
|
||||
|
||||
} // namespace Service::Audio
|
||||
|
|
|
@ -77,7 +77,7 @@ IParentalControlService::IParentalControlService(Core::System& system_, Capabili
|
|||
{1451, D<&IParentalControlService::StartPlayTimer>, "StartPlayTimer"},
|
||||
{1452, D<&IParentalControlService::StopPlayTimer>, "StopPlayTimer"},
|
||||
{1453, D<&IParentalControlService::IsPlayTimerEnabled>, "IsPlayTimerEnabled"},
|
||||
{1454, nullptr, "GetPlayTimerRemainingTime"},
|
||||
{1454, D<&IParentalControlService::GetPlayTimerRemainingTime>, "GetPlayTimerRemainingTime"},
|
||||
{1455, D<&IParentalControlService::IsRestrictedByPlayTimer>, "IsRestrictedByPlayTimer"},
|
||||
{1456, D<&IParentalControlService::GetPlayTimerSettings>, "GetPlayTimerSettings"},
|
||||
{1457, D<&IParentalControlService::GetPlayTimerEventToRequestSuspension>, "GetPlayTimerEventToRequestSuspension"},
|
||||
|
@ -117,6 +117,7 @@ IParentalControlService::IParentalControlService(Core::System& system_, Capabili
|
|||
{2014, nullptr, "FinishSynchronizeParentalControlSettings"},
|
||||
{2015, nullptr, "FinishSynchronizeParentalControlSettingsWithLastUpdated"},
|
||||
{2016, nullptr, "RequestUpdateExemptionListAsync"},
|
||||
{145601, D<&IParentalControlService::GetSelfController>, "GetSelfController"},
|
||||
};
|
||||
// clang-format on
|
||||
RegisterHandlers(functions);
|
||||
|
@ -431,4 +432,22 @@ Result IParentalControlService::ResetConfirmedStereoVisionPermission() {
|
|||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IParentalControlService::GetSelfController(Out<SharedPointer<IParentalControlService>> out_controller) {
|
||||
LOG_DEBUG(Service_PCTL, "called");
|
||||
|
||||
// Return a shared pointer to this service instance
|
||||
*out_controller = SharedPointer<IParentalControlService>(this);
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IParentalControlService::GetPlayTimerRemainingTime(Out<s32> out_remaining_time) {
|
||||
LOG_DEBUG(Service_PCTL, "called");
|
||||
|
||||
// For now, return maximum time remaining since play timer is stubbed
|
||||
*out_remaining_time = std::numeric_limits<s32>::max();
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace Service::PCTL
|
||||
|
|
|
@ -53,6 +53,8 @@ private:
|
|||
Result GetStereoVisionRestriction(Out<bool> out_stereo_vision_restriction);
|
||||
Result SetStereoVisionRestriction(bool stereo_vision_restriction);
|
||||
Result ResetConfirmedStereoVisionPermission();
|
||||
Result GetSelfController(Out<SharedPointer<IParentalControlService>> out_controller);
|
||||
Result GetPlayTimerRemainingTime(Out<s32> out_remaining_time);
|
||||
|
||||
struct States {
|
||||
u64 current_tid{};
|
||||
|
|
Loading…
Add table
Reference in a new issue