Added alarm-notifications example.

This commit is contained in:
yellows8 2019-11-17 18:26:53 -05:00
parent afb3d2132f
commit b9df83b93d
No known key found for this signature in database
GPG Key ID: 0AF90DA3F1E60E43
2 changed files with 403 additions and 0 deletions

View File

@ -0,0 +1,222 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPRO)),)
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>/devkitpro")
endif
TOPDIR ?= $(CURDIR)
include $(DEVKITPRO)/libnx/switch_rules
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# DATA is a list of directories containing data files
# INCLUDES is a list of directories containing header files
# ROMFS is the directory containing data to be added to RomFS, relative to the Makefile (Optional)
#
# NO_ICON: if set to anything, do not use icon.
# NO_NACP: if set to anything, no .nacp file is generated.
# APP_TITLE is the name of the app stored in the .nacp file (Optional)
# APP_AUTHOR is the author of the app stored in the .nacp file (Optional)
# APP_VERSION is the version of the app stored in the .nacp file (Optional)
# APP_TITLEID is the titleID of the app stored in the .nacp file (Optional)
# ICON is the filename of the icon (.jpg), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.jpg
# - icon.jpg
# - <libnx folder>/default_icon.jpg
#
# CONFIG_JSON is the filename of the NPDM config file (.json), relative to the project folder.
# If not set, it attempts to use one of the following (in this order):
# - <Project name>.json
# - config.json
# If a JSON file is provided or autodetected, an ExeFS PFS0 (.nsp) is built instead
# of a homebrew executable (.nro). This is intended to be used for sysmodules.
# NACP building is skipped as well.
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := source
DATA := data
INCLUDES := include
#ROMFS := romfs
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE
CFLAGS := -g -Wall -O2 -ffunction-sections \
$(ARCH) $(DEFINES)
CFLAGS += $(INCLUDE) -D__SWITCH__
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
LIBS := -lnx
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(PORTLIBS) $(LIBNX)
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
ifeq ($(strip $(CONFIG_JSON)),)
jsons := $(wildcard *.json)
ifneq (,$(findstring $(TARGET).json,$(jsons)))
export APP_JSON := $(TOPDIR)/$(TARGET).json
else
ifneq (,$(findstring config.json,$(jsons)))
export APP_JSON := $(TOPDIR)/config.json
endif
endif
else
export APP_JSON := $(TOPDIR)/$(CONFIG_JSON)
endif
ifeq ($(strip $(ICON)),)
icons := $(wildcard *.jpg)
ifneq (,$(findstring $(TARGET).jpg,$(icons)))
export APP_ICON := $(TOPDIR)/$(TARGET).jpg
else
ifneq (,$(findstring icon.jpg,$(icons)))
export APP_ICON := $(TOPDIR)/icon.jpg
endif
endif
else
export APP_ICON := $(TOPDIR)/$(ICON)
endif
ifeq ($(strip $(NO_ICON)),)
export NROFLAGS += --icon=$(APP_ICON)
endif
ifeq ($(strip $(NO_NACP)),)
export NROFLAGS += --nacp=$(CURDIR)/$(TARGET).nacp
endif
ifneq ($(APP_TITLEID),)
export NACPFLAGS += --titleid=$(APP_TITLEID)
endif
ifneq ($(ROMFS),)
export NROFLAGS += --romfsdir=$(CURDIR)/$(ROMFS)
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
ifeq ($(strip $(APP_JSON)),)
@rm -fr $(BUILD) $(TARGET).nro $(TARGET).nacp $(TARGET).elf
else
@rm -fr $(BUILD) $(TARGET).nsp $(TARGET).nso $(TARGET).npdm $(TARGET).elf
endif
#---------------------------------------------------------------------------------
else
.PHONY: all
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
ifeq ($(strip $(APP_JSON)),)
all : $(OUTPUT).nro
ifeq ($(strip $(NO_NACP)),)
$(OUTPUT).nro : $(OUTPUT).elf $(OUTPUT).nacp
else
$(OUTPUT).nro : $(OUTPUT).elf
endif
else
all : $(OUTPUT).nsp
$(OUTPUT).nsp : $(OUTPUT).nso $(OUTPUT).npdm
$(OUTPUT).nso : $(OUTPUT).elf
endif
$(OUTPUT).elf : $(OFILES)
$(OFILES_SRC) : $(HFILES_BIN)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o %_bin.h : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -0,0 +1,181 @@
// Include the most common headers from the C standard library
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
// Include the main libnx system header, for Switch development
#include <switch.h>
// This example shows how to use Alarm Notifications, see libnx notif.h.
// This must be run under a host Application. To avoid conflicts with official apps, normally you should not run under a host Application where the official Application also uses Alarm Notifications.
// Parse the ApplicationParameter and verify that it belongs to the current hb app. You can store any data you want in the ApplicationParameter.
bool parse_app_param(u8 *outdata, size_t outdata_size, u64 out_size, u8 *app_param_header, size_t app_param_header_size) {
printf("out_size=0x%lx\n", out_size);
if (out_size != outdata_size) // Adjust this check if needed.
printf("out_size is invalid, ignoring data since it doesn't belong to the current app.\n");
else {
if(memcmp(outdata, app_param_header, app_param_header_size)==0) {
printf("data: %s\n", (char*)&outdata[0x8]);
return true;
}
else
printf("ApplicationParameter header mismatch, ignoring data since it doesn't belong to the current app.\n");
}
return false;
}
// Main program entrypoint
int main(int argc, char* argv[])
{
// This example uses a text console, as a simple way to output text to the screen.
// If you want to write a software-rendered graphics application,
// take a look at the graphics/simplegfx example, which uses the libnx Framebuffer API instead.
// If on the other hand you want to write an OpenGL based application,
// take a look at the graphics/opengl set of examples, which uses EGL instead.
consoleInit(NULL);
printf("alarm-notifications example\n");
Result rc=0, rc2=0;
bool tmpflag=0;
u16 alarm_setting_id=0;
s32 total_out=0;
NotifAlarmSetting alarm_setting;
NotifAlarmSetting alarm_settings[NOTIF_MAX_ALARMS];
Event alarmevent={0};
// To avoid conflicts with other hb apps, use some sort of header to verify that the ApplicationParameter belongs to the current hb app. Replace this with your own data. Note that official apps don't do this.
// Note that ApplicationParameter is optional, see notif.h - you can disable/remove code using it you want.
u8 app_param_header[0x8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
u8 app_param[0x20]={0};
u8 outdata[0x21]; // Since we're handling this as a string, make sure it's NUL-terminated.
memcpy(app_param, app_param_header, sizeof(app_param_header));
strncpy((char*)&app_param[0x8], "app param", sizeof(app_param)-9); // This example stores a string in the app_param - replace this with whatever data you want.
rc = notifInitialize(NotifServiceType_Application);
if (R_FAILED(rc)) printf("notifInitialize(): 0x%x\n", rc);
if (R_SUCCEEDED(rc)) { // Some official apps don't use this. See libnx notif.h for this.
rc = notifGetNotificationSystemEvent(&alarmevent);
printf("notifGetNotificationSystemEvent(): 0x%x\n", rc);
}
if (R_SUCCEEDED(rc)) {
printf("Press A to register the Alarm.\n");
printf("Press B to list the Alarms.\n");
printf("Press X to delete the registered Alarm.\n");
}
printf("Press + to exit.\n");
// Main loop
while (appletMainLoop())
{
// Scan all the inputs. This should be done once for each frame
hidScanInput();
// hidKeysDown returns information about which buttons have been
// just pressed in this frame compared to the previous one
u64 kDown = hidKeysDown(CONTROLLER_P1_AUTO);
if (kDown & KEY_PLUS)
break; // break in order to return to hbmenu
if (R_SUCCEEDED(rc) && R_SUCCEEDED(eventWait(&alarmevent, 0))) { // Some official apps don't use this. See libnx notif.h for this.
u64 out_size=0;
memset(outdata, 0, sizeof(outdata));
rc = notifTryPopNotifiedApplicationParameter(outdata, sizeof(outdata)-1, &out_size);
printf("notifTryPopNotifiedApplicationParameter(): 0x%x\n", rc);
if (R_SUCCEEDED(rc)) {
parse_app_param(outdata, sizeof(outdata)-1, out_size, app_param_header, sizeof(app_param_header));
}
}
if (R_SUCCEEDED(rc)) {
if (kDown & KEY_A) {
// Setup an alarm with {current local-time} + {2 minutes}. You can use any weekday/time you want.
// See libnx notif.h for more notifAlarmSetting*() funcs.
notifAlarmSettingCreate(&alarm_setting);
time_t unixTime = time(NULL) + 60*2;
struct tm* timeStruct = localtime((const time_t *)&unixTime);
u32 day = timeStruct->tm_wday;
s32 hour = timeStruct->tm_hour;
s32 minute = timeStruct->tm_min;
printf("Using the following schedule setting: weekday = %u, %02d:%02d.\n", day, hour, minute);
// You can also use this multiple times if you want for multiple days - this example only uses it once for a single day.
rc = notifAlarmSettingEnable(&alarm_setting, day, hour, minute);
printf("notifAlarmSettingEnable(): 0x%x\n", rc);
if (R_SUCCEEDED(rc)) {
rc = notifRegisterAlarmSetting(&alarm_setting_id, &alarm_setting, app_param, sizeof(app_param));
printf("notifRegisterAlarmSetting(): 0x%x\n", rc);
if (R_SUCCEEDED(rc)) printf("alarm_setting_id = 0x%x\n", alarm_setting_id);
}
}
else if (kDown & KEY_B) {
// List the Alarms.
total_out=0;
memset(alarm_settings, 0, sizeof(alarm_settings));
rc = notifListAlarmSettings(alarm_settings, NOTIF_MAX_ALARMS, &total_out);
printf("notifListAlarmSettings(): 0x%x\n", rc);
if (R_SUCCEEDED(rc)) {
printf("total_out: %d\n", total_out);
for (s32 alarmi=0; alarmi<total_out; alarmi++) {
printf("[%d]: muted=%d.\n", alarmi, alarm_settings[alarmi].muted);
// Verify that the Alarm belongs to the current app via the ApplicationParameter / parse the data from there.
u32 actual_size=0;
memset(outdata, 0, sizeof(outdata));
rc2 = notifLoadApplicationParameter(alarm_settings[alarmi].alarm_setting_id, outdata, sizeof(outdata)-1, &actual_size);
printf("notifLoadApplicationParameter(): 0x%x\n", rc2);
if (R_FAILED(rc2) || !parse_app_param(outdata, sizeof(outdata)-1, actual_size, app_param_header, sizeof(app_param_header))) continue;
// If you want to update an AlarmSetting/ApplicationParameter from the alarm-listing, you can use this. notifAlarmSetting*() funcs can be used to update it if wanted.
// rc2 = notifUpdateAlarmSetting(&alarm_settings[alarmi], outdata, sizeof(outdata)-1);
// printf("notifUpdateAlarmSetting(): 0x%x\n", rc2);
// Print the schedule settings.
for (u32 day_of_week=0; day_of_week<7; day_of_week++) {
rc2 = notifAlarmSettingIsEnabled(&alarm_settings[alarmi], day_of_week, &tmpflag);
if (R_SUCCEEDED(rc2) && tmpflag) {
NotifAlarmTime alarmtime={0};
rc2 = notifAlarmSettingGet(&alarm_settings[alarmi], day_of_week, &alarmtime);
if (R_SUCCEEDED(rc2)) {
printf("weekday %d = %02d:%02d. ", day_of_week, alarmtime.hour, alarmtime.minute);
}
}
}
printf("\n");
}
}
}
else if ((kDown & KEY_X) && alarm_setting_id) {
// Delete the AlarmSetting which was registered with the KEY_A block.
// If wanted, you can also use this with alarm_settings[alarmi].alarm_setting_id with the output from notifListAlarmSettings.
rc = notifDeleteAlarmSetting(alarm_setting_id);
printf("notifDeleteAlarmSetting(): 0x%x\n", rc);
}
}
// Update the console, sending a new frame to the display
consoleUpdate(NULL);
}
eventClose(&alarmevent);
notifExit();
// Deinitialize and clean up resources used by the console (important!)
consoleExit(NULL);
return 0;
}