Import of the watch repository from Pebble

This commit is contained in:
Matthieu Jeanson
2025-01-27 11:38:16 -08:00
committed by Katharine Berry
commit 3b92768480
10334 changed files with 2564465 additions and 0 deletions
@@ -0,0 +1,42 @@
/*
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "vibe_client.h"
#include "applib/ui/vibes.h"
#include "services/normal/notifications/alerts_preferences_private.h"
#include "services/normal/vibes/vibe_score.h"
#include "services/normal/vibes/vibe_score_info.h"
#include "system/logging.h"
static VibeScoreId prv_get_resource_for_client(VibeClient client) {
if (client == VibeClient_AlarmsLPM) {
return VibeScoreId_AlarmsLPM;
}
return alerts_preferences_get_vibe_score_for_client(client);
}
VibeScore *vibe_client_get_score(VibeClient client) {
VibeScoreId id = prv_get_resource_for_client(client);
if (id == VibeScoreId_Disabled) {
return NULL;
}
VibeScore *score = vibe_score_create_with_resource(vibe_score_info_get_resource_id(id));
if (!score) {
PBL_LOG(LOG_LEVEL_ERROR, "Got a null VibeScore resource!");
}
return score;
}
@@ -0,0 +1,30 @@
/*
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "vibe_score.h"
typedef enum VibeClient {
VibeClient_Notifications = 0,
VibeClient_PhoneCalls,
VibeClient_Alarms,
VibeClient_AlarmsLPM
} VibeClient;
// Returns the appropriate vibe score for the client.
// This is determined from alert preferences.
VibeScore *vibe_client_get_score(VibeClient client);
@@ -0,0 +1,70 @@
/*
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "vibe_intensity.h"
#include "services/common/i18n/i18n.h"
#include "services/common/vibe_pattern.h"
#include "services/normal/notifications/alerts_preferences_private.h"
uint8_t get_strength_for_intensity(VibeIntensity intensity) {
switch (intensity) {
case VibeIntensityLow:
return 40;
case VibeIntensityMedium:
return 60;
case VibeIntensityHigh:
return 100;
default:
return 100;
}
}
void vibe_intensity_init(void) {
vibe_intensity_set(vibe_intensity_get());
}
void vibe_intensity_set(VibeIntensity intensity) {
vibes_set_default_vibe_strength(get_strength_for_intensity(intensity));
}
VibeIntensity vibe_intensity_get(void) {
return alerts_preferences_get_vibe_intensity();
}
const char *vibe_intensity_get_string_for_intensity(VibeIntensity intensity) {
switch (intensity) {
case VibeIntensityLow: {
/// Standard vibration pattern option that has a low intensity
return i18n_noop("Standard - Low");
}
case VibeIntensityMedium: {
/// Standard vibration pattern option that has a medium intensity
return i18n_noop("Standard - Medium");
}
case VibeIntensityHigh: {
/// Standard vibration pattern option that has a high intensity
return i18n_noop("Standard - High");
}
default: {
return NULL;
}
}
}
VibeIntensity vibe_intensity_cycle_next(VibeIntensity intensity) {
return (intensity + 1) % VibeIntensityNum;
}
@@ -0,0 +1,54 @@
/*
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <stdint.h>
typedef enum VibeIntensity {
VibeIntensityLow,
VibeIntensityMedium,
VibeIntensityHigh,
VibeIntensityNum,
} VibeIntensity;
#if PLATFORM_SPALDING
#define DEFAULT_VIBE_INTENSITY VibeIntensityMedium
#else
#define DEFAULT_VIBE_INTENSITY VibeIntensityHigh
#endif
void vibe_intensity_init(void);
//! Returns the corresponding strength for the given level of intensity.
//! The strength corresponds to a percentage of the max strength, ie in the range [0,100].
uint8_t get_strength_for_intensity(VibeIntensity intensity);
//! Sets the intensity of ALL vibrations (not just notifications)
void vibe_intensity_set(VibeIntensity intensity);
//! Gets the current vibe intensity
VibeIntensity vibe_intensity_get(void);
//! Returns a string representation of the provided vibe intensity.
//! @param intensity The intensity for which to get a string representation
//! @return A string representation of the provided intensity, or NULL if the intensity is invalid
const char *vibe_intensity_get_string_for_intensity(VibeIntensity intensity);
//! Gets the next intensity in the vibe intensity cycle
//! @param intensity Input intensity for which to get the next intensity
//! @return The next vibe intensity in the cycle
VibeIntensity vibe_intensity_cycle_next(VibeIntensity intensity);
+237
View File
@@ -0,0 +1,237 @@
/*
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "vibe_score.h"
#include "process_management/app_manager.h"
#include "syscall/syscall.h"
#include "system/passert.h"
#include "drivers/vibe.h"
#include "applib/applib_malloc.auto.h"
#include "util/net.h"
#define VIBE_SCORE_MAX_REPEAT_DELAY_MS (10000) // matches MAX_VIBE_DURATION_MS in vibe_pattern
static VibeNote *prv_vibe_score_get_note_list(GenericAttribute *notes_attribute) {
return (VibeNote *)notes_attribute->data;
}
static VibeNoteIndex *prv_vibe_score_get_pattern_list(GenericAttribute *pattern_attribute) {
return (VibeNoteIndex *)pattern_attribute->data;
}
static unsigned int prv_vibe_score_get_num_note_types(GenericAttribute *notes_attribute) {
return notes_attribute->length / sizeof(VibeNote);
}
static unsigned int prv_vibe_score_get_pattern_length(GenericAttribute *pattern_attribute) {
return pattern_attribute->length / sizeof(VibeNoteIndex);
}
static bool prv_vibe_score_resource_is_valid(ResAppNum app_num, uint32_t resource_id,
uint32_t expected_signature, uint32_t *data_size) {
// Load file signature, and check that it matches the expected_signature
uint32_t data_signature;
if (!(sys_resource_load_range(app_num, resource_id, 0, (uint8_t*)&data_signature,
sizeof(data_signature)) == sizeof(data_signature) &&
(ntohl(data_signature) == expected_signature))) {
return false;
}
// Data is the second entry after the resource signature
if (data_size) {
size_t output_data_size = sys_resource_size(app_num, resource_id) - VIBE_DATA_OFFSET;
*data_size = output_data_size;
}
return true;
}
bool vibe_score_validate(VibeScore *score, uint32_t data_size) {
if (!score) {
return false;
}
uint32_t total_size = sizeof(VibeScore);
// check large enough to contain non-flexible parts
if (data_size < total_size) {
return false;
}
// check version number
if (score->version > VIBE_SCORE_VERSION) {
return false;
}
// check if attr_list_size is correct
if (score->attr_list_size != (data_size - (sizeof(VibeScore) - sizeof(GenericAttributeList)))) {
return false;
}
// check exact file size to contain all flexible-sized data
for (unsigned int i = 0; i < score->attr_list.num_attributes; i++) {
GenericAttribute * attribute = (GenericAttribute *)((uint8_t *)score + total_size);
total_size += sizeof(GenericAttribute);
if (data_size < total_size) {
return false;
}
total_size += attribute->length;
if (data_size < total_size) {
return false;
}
}
if (data_size != total_size) {
return false;
}
// check to see all indices point to valid notes
GenericAttribute *notes_attribute = generic_attribute_find_attribute(&score->attr_list,
VibeAttributeId_Notes,
score->attr_list_size);
GenericAttribute *pattern_attribute = generic_attribute_find_attribute(&score->attr_list,
VibeAttributeId_Pattern,
score->attr_list_size);
if (!notes_attribute || !pattern_attribute) {
return false;
}
unsigned int num_note_types = prv_vibe_score_get_num_note_types(notes_attribute);
if (notes_attribute->length != num_note_types * sizeof(VibeNote)) {
return false;
}
VibeNoteIndex *pattern_list = prv_vibe_score_get_pattern_list(pattern_attribute);
for (unsigned int i = 0; i < prv_vibe_score_get_pattern_length(pattern_attribute); i++) {
if (pattern_list[i] >= num_note_types) {
return false;
}
}
GenericAttribute *repeat_delay_attribute =
generic_attribute_find_attribute(&score->attr_list, VibeAttributeId_RepeatDelay,
score->attr_list_size);
if (repeat_delay_attribute) {
if (repeat_delay_attribute->length != sizeof(uint16_t)) {
return false;
}
uint16_t *delay = (uint16_t *)repeat_delay_attribute->data;
if (*delay > VIBE_SCORE_MAX_REPEAT_DELAY_MS) {
return false;
}
}
return true;
}
VibeScore *vibe_score_create_with_resource_system(ResAppNum app_num,
uint32_t resource_id) {
uint32_t data_size;
if (!prv_vibe_score_resource_is_valid(app_num, resource_id, VIBE_SIGNATURE, &data_size)) {
return NULL;
}
VibeScore *vibe_score = applib_zalloc(data_size);
if (!vibe_score || sys_resource_load_range(app_num, resource_id, VIBE_DATA_OFFSET,
(uint8_t*)vibe_score, data_size) != data_size) {
applib_free(vibe_score);
return NULL;
}
// Validate the loaded command sequence
if (!vibe_score_validate(vibe_score, data_size)) {
applib_free(vibe_score);
return NULL;
}
return vibe_score;
}
unsigned int vibe_score_get_duration_ms(VibeScore *score) {
if (!score) {
return 0;
}
GenericAttribute *notes_attribute = generic_attribute_find_attribute(&score->attr_list,
VibeAttributeId_Notes,
score->attr_list_size);
GenericAttribute *pattern_attribute = generic_attribute_find_attribute(&score->attr_list,
VibeAttributeId_Pattern,
score->attr_list_size);
PBL_ASSERTN(notes_attribute && pattern_attribute);
unsigned int duration_ms = 0;
VibeNote *note_list = prv_vibe_score_get_note_list(notes_attribute);
VibeNoteIndex *pattern_list = prv_vibe_score_get_pattern_list(pattern_attribute);
unsigned int pattern_length = prv_vibe_score_get_pattern_length(pattern_attribute);
for (unsigned int i = 0; i < pattern_length; i++) {
VibeNote *note = &note_list[pattern_list[i]];
duration_ms += (note->vibe_duration_ms + note->brake_duration_ms);
}
return duration_ms;
}
unsigned int vibe_score_get_repeat_delay_ms(VibeScore *score) {
if (!score) {
return 0;
}
GenericAttribute *repeat_delay_attribute =
generic_attribute_find_attribute(&score->attr_list, VibeAttributeId_RepeatDelay,
score->attr_list_size);
if (repeat_delay_attribute) {
uint16_t *repeat_delay = (uint16_t *) repeat_delay_attribute->data;
return *repeat_delay;
}
return 0;
}
void vibe_score_do_vibe(VibeScore *score) {
PBL_ASSERTN(score);
GenericAttribute *notes_attribute = generic_attribute_find_attribute(&score->attr_list,
VibeAttributeId_Notes,
score->attr_list_size);
GenericAttribute *pattern_attribute = generic_attribute_find_attribute(&score->attr_list,
VibeAttributeId_Pattern,
score->attr_list_size);
PBL_ASSERTN(notes_attribute && pattern_attribute);
VibeNote *note_list = prv_vibe_score_get_note_list(notes_attribute);
VibeNoteIndex *pattern_list = prv_vibe_score_get_pattern_list(pattern_attribute);
unsigned int pattern_length = prv_vibe_score_get_pattern_length(pattern_attribute);
for (unsigned int i = 0; i < pattern_length; i++) {
VibeNote *note = &note_list[pattern_list[i]];
if (note->vibe_duration_ms > 0) {
sys_vibe_pattern_enqueue_step_raw(note->vibe_duration_ms, note->strength);
}
if (note->brake_duration_ms > 0) {
sys_vibe_pattern_enqueue_step_raw(note->brake_duration_ms, vibe_get_braking_strength());
}
}
sys_vibe_pattern_trigger_start();
}
VibeScore *vibe_score_create_with_resource(uint32_t resource_id) {
ResAppNum app_num = sys_get_current_resource_num();
return vibe_score_create_with_resource_system(app_num, resource_id);
}
void vibe_score_destroy(VibeScore *score) {
if (!score) {
return;
}
applib_free(score);
}
+72
View File
@@ -0,0 +1,72 @@
/*
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "resource/resource.h"
#include "util/attributes.h"
#include "util/generic_attribute.h"
#include "util/pack.h"
#define VIBE_SCORE_VERSION (1)
#define VIBE_SIGNATURE MAKE_WORD('V', 'I', 'B', 'E')
#define VIBE_DATA_OFFSET sizeof(VIBE_SIGNATURE)
typedef enum VibeAttributeId {
VibeAttributeId_Invalid = 0x00,
VibeAttributeId_Notes = 0x01,
VibeAttributeId_Pattern = 0x02,
VibeAttributeId_RepeatDelay = 0x03,
} VibeAttributeId;
typedef struct PACKED VibeScore {
uint16_t version;
uint8_t reserved[4];
uint16_t attr_list_size;
GenericAttributeList attr_list;
} VibeScore;
typedef struct PACKED VibeNote {
uint16_t vibe_duration_ms;
uint8_t brake_duration_ms;
int8_t strength;
} VibeNote;
typedef uint8_t VibeNoteIndex;
// Fetches a vibe score from resources, specifying a ResAppNum
// Must be freed using vibe_score_destroy()
VibeScore *vibe_score_create_with_resource_system(ResAppNum app_num, uint32_t resource_id);
// Fetches a vibe score from resources, using the caller ResAppNum
// Must be freed using vibe_score_destroy()
VibeScore *vibe_score_create_with_resource(uint32_t resource_id);
// Checks whether a vibe score is valid, given its data size
bool vibe_score_validate(VibeScore *score, uint32_t data_size);
// Returns the duration in ms of the vibe pattern specified by the score
unsigned int vibe_score_get_duration_ms(VibeScore *score);
// Returns the value of the repeat_delay attribute, or 0 if it does not exist
unsigned int vibe_score_get_repeat_delay_ms(VibeScore *score);
// Queues the vibe pattern specified by the score and starts the vibe motor
// If there the system is already playing a vibe, this will do nothing
void vibe_score_do_vibe(VibeScore *score);
// Frees a vibe created with vibe_score_create_with_resource
void vibe_score_destroy(VibeScore *score);
@@ -0,0 +1,118 @@
/*
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "vibe_score_info.h"
#include "resource/resource_ids.auto.h"
#include "services/common/i18n/i18n.h"
#include "system/passert.h"
#include "util/size.h"
typedef enum AlertType {
AlertType_Notifications = 1 << 0,
AlertType_Calls = 1 << 1,
AlertType_Alarms = 1 << 2,
AlertType_AlarmsLPM = 1 << 3,
AlertType_All = AlertType_Notifications | AlertType_Calls | AlertType_Alarms,
} AlertType;
typedef struct {
const VibeScoreId id;
const char *name;
const int alert_types;
const uint32_t resource_id;
} VibeScoreInfo;
#define VIBE_DEF(identifier, enum_name, name_str, alert_types_arg, res_id)\
{ .id = identifier, \
.name = name_str, \
.alert_types = alert_types_arg, \
.resource_id = res_id },
static const VibeScoreInfo S_VIBE_MAP[] = {
#include "vibes.def"
};
#undef VIBE_DEF
#define VIBE_MAP_SIZE ARRAY_LENGTH(S_VIBE_MAP)
static const VibeScoreInfo *prv_vibe_score_find_info(VibeScoreId id) {
for (unsigned int x = 0; x < VIBE_MAP_SIZE; x++) {
if (S_VIBE_MAP[x].id == id) {
return &S_VIBE_MAP[x];
}
}
return NULL;
}
uint32_t vibe_score_info_get_resource_id(VibeScoreId id) {
const VibeScoreInfo *info = prv_vibe_score_find_info(id);
return info ? info->resource_id : RESOURCE_ID_INVALID;
}
const char *vibe_score_info_get_name(VibeScoreId id) {
const VibeScoreInfo *info = prv_vibe_score_find_info(id);
return info ? info->name : "";
}
static int prv_get_index(VibeScoreId id) {
for (unsigned int x = 0; x < VIBE_MAP_SIZE; x++) {
if (S_VIBE_MAP[x].id == id) {
return x;
}
}
return 0;
}
VibeScoreId vibe_score_info_cycle_next(VibeClient client, VibeScoreId curr_id) {
AlertType alert_type;
switch (client) {
case VibeClient_Notifications: {
alert_type = AlertType_Notifications;
break;
}
case VibeClient_PhoneCalls: {
alert_type = AlertType_Calls;
break;
}
case VibeClient_Alarms: {
alert_type = AlertType_Alarms;
break;
}
default: {
WTF;
}
}
unsigned int currently_showing_index = prv_get_index(curr_id);
unsigned int search_index = (currently_showing_index + 1) % VIBE_MAP_SIZE;
while (search_index != currently_showing_index) {
if ((S_VIBE_MAP[search_index].alert_types & alert_type) == alert_type) {
return S_VIBE_MAP[search_index].id;
}
search_index = (search_index + 1) % VIBE_MAP_SIZE;
}
return curr_id;
}
bool vibe_score_info_is_valid(VibeScoreId id) {
const VibeScoreInfo *info = prv_vibe_score_find_info(id);
return (id != VibeScoreId_Invalid) &&
info &&
((id == VibeScoreId_Disabled) || (info->resource_id != RESOURCE_ID_INVALID));
}
@@ -0,0 +1,57 @@
/*
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include "services/normal/vibes/vibe_client.h"
#include <stdbool.h>
#include <stdint.h>
#define VIBE_DEF(identifier, enum_name, name_str, alert_types_arg, res_id)\
VibeScoreId_##enum_name = identifier,
typedef enum VibeScoreId {
VibeScoreId_Invalid = 0,
#include "vibes.def"
} VibeScoreId;
#undef VIBE_DEF
#if PLATFORM_SPALDING
#define DEFAULT_VIBE_SCORE_NOTIFS (VibeScoreId_Pulse)
#define DEFAULT_VIBE_SCORE_INCOMING_CALLS (VibeScoreId_Pulse)
#define DEFAULT_VIBE_SCORE_ALARMS (VibeScoreId_Pulse)
#else
#define DEFAULT_VIBE_SCORE_NOTIFS (VibeScoreId_NudgeNudge)
#define DEFAULT_VIBE_SCORE_INCOMING_CALLS (VibeScoreId_Pulse)
#define DEFAULT_VIBE_SCORE_ALARMS (VibeScoreId_Reveille)
#endif
// Returns the ResourceId for the VibeScore represented by this id.
// If the id does not exist, the ResourceId of the first vibe in S_VIBE_MAP is returned
uint32_t vibe_score_info_get_resource_id(VibeScoreId id);
// Returns the name of the VibeScore represented by this id
// If the id does not exist, the name of the first vibe in S_VIBE_MAP is returned
const char *vibe_score_info_get_name(VibeScoreId id);
// Returns the next vibe score playable by the client from the array defined by vibes.def
// Wraps around and continues searching if the end of the array is reached
// Returns current_id if there is no next vibe score
VibeScoreId vibe_score_info_cycle_next(VibeClient client, VibeScoreId curr_id);
// Checks if the vibe score id exists and if the associated VibeScoreInfo contains a valid
// resource_id
bool vibe_score_info_is_valid(VibeScoreId id);
+16
View File
@@ -0,0 +1,16 @@
// IDs must be monotonically increasing, i.e. they must never be reused
// ID 0 is reserved for "Invalid". Do not use!
VIBE_DEF(1, Disabled, i18n_ctx_noop("NotifVibe", "Disabled"), (AlertType_Notifications | AlertType_Calls), RESOURCE_ID_INVALID)
VIBE_DEF(2, StandardShortPulseLow, i18n_noop("Standard - Low"), AlertType_Notifications, RESOURCE_ID_VIBE_SCORE_STANDARD_SHORT_LOW)
VIBE_DEF(3, StandardLongPulseLow, i18n_noop("Standard - Low"), (AlertType_Calls | AlertType_Alarms), RESOURCE_ID_VIBE_SCORE_STANDARD_LONG_LOW)
VIBE_DEF(4, StandardShortPulseHigh, i18n_noop("Standard - High"), AlertType_Notifications, RESOURCE_ID_VIBE_SCORE_STANDARD_SHORT_HIGH)
VIBE_DEF(5, StandardLongPulseHigh, i18n_noop("Standard - High"), (AlertType_Calls | AlertType_Alarms), RESOURCE_ID_VIBE_SCORE_STANDARD_LONG_HIGH)
VIBE_DEF(8, Pulse, i18n_noop("Pulse"), AlertType_All, RESOURCE_ID_VIBE_SCORE_PULSE)
VIBE_DEF(9, NudgeNudge, i18n_noop("Nudge Nudge"), AlertType_All, RESOURCE_ID_VIBE_SCORE_NUDGE_NUDGE)
#if !PLATFORM_SPALDING
VIBE_DEF(10, Jackhammer, i18n_noop("Jackhammer"), AlertType_All, RESOURCE_ID_VIBE_SCORE_JACKHAMMER)
VIBE_DEF(11, Reveille, "Reveille", AlertType_Alarms, RESOURCE_ID_VIBE_SCORE_REVEILLE)
VIBE_DEF(12, Mario, "Mario", AlertType_All, RESOURCE_ID_VIBE_SCORE_MARIO)
#endif
VIBE_DEF(13, AlarmsLPM, "ALARMS LPM", AlertType_AlarmsLPM, RESOURCE_ID_VIBE_SCORE_ALARM_LPM)