701 lines
18 KiB
Python
Executable File
701 lines
18 KiB
Python
Executable File
//Compile out Title Update changes to header functions.
|
|
//Must be before includes.
|
|
//CONST_INT USE_TU_CHANGES 0 // Removed by Kenneth R.
|
|
|
|
|
|
USING "rage_builtins.sch"
|
|
USING "globals.sch"
|
|
USING "commands_misc.sch"
|
|
USING "commands_script.sch"
|
|
USING "commands_pad.sch"
|
|
USING "cellphone_public.sch"
|
|
USING "cellphone_private.sch"
|
|
USING "dialogue_public.sch"
|
|
USING "player_ped_public.sch"
|
|
USING "stack_sizes.sch"
|
|
USING "mission_repeat_public.sch"
|
|
USING "mission_stat_public.sch"
|
|
USING "finance_modifiers_public.sch"
|
|
|
|
|
|
|
|
|
|
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
//
|
|
// MISSION NAME : appZit.sc
|
|
// AUTHOR : Steve T
|
|
// DESCRIPTION : This application returns the currently playing song title and
|
|
// artist plus additional stats to the cellphone.
|
|
//
|
|
//
|
|
//
|
|
//
|
|
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
|
|
|
|
|
|
|
|
|
|
//SCALEFORM_RETURN_INDEX Choice_ReturnedSFIndex
|
|
|
|
|
|
|
|
|
|
|
|
STRUCT structSongData
|
|
|
|
|
|
TEXT_LABEL_63 Title //The Song Title
|
|
TEXT_LABEL_31 Artist //The Artist Name
|
|
|
|
INT i_NumberOfTimesHeard
|
|
TEXT_LABEL_23 RadioStation //Radio Station this song is playing on.
|
|
|
|
|
|
ENDSTRUCT
|
|
|
|
|
|
|
|
structSongData CurrentSongData
|
|
|
|
INT i_ZitID = -99
|
|
|
|
|
|
TEXT_LABEL_31 ZitPhoneBlock = "TRACKID"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BOOL b_OkayToUseShareButton = FALSE
|
|
|
|
BOOL b_DoSharingRoutine = FALSE, b_ShareComplete = FALSE
|
|
|
|
INT i_SharingProgress = 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if IS_DEBUG_BUILD
|
|
PROC Temp_Setup_Of_Test_Song_Data()
|
|
|
|
|
|
//CurrentSongData.
|
|
|
|
CurrentSongData.Title = "CELL_4100"
|
|
CurrentSongData.Artist = "CELL_4101"
|
|
CurrentSongData.RadioStation = "CELL_4102"
|
|
|
|
CurrentSongData.i_NumberOfTimesHeard = 2
|
|
|
|
|
|
|
|
ENDPROC
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
PROC Get_Song_Data_From_Audio()
|
|
|
|
|
|
i_ZitID = GET_AUDIBLE_MUSIC_TRACK_TEXT_ID()
|
|
|
|
CurrentSongData.Title = ""
|
|
CurrentSongData.Title += i_ZitId
|
|
CurrentSongData.Title += "S"
|
|
|
|
CurrentSongData.Artist = ""
|
|
CurrentSongData.Artist += i_ZitId
|
|
CurrentSongData.Artist += "A"
|
|
|
|
CurrentSongData.RadioStation = GET_PLAYER_RADIO_STATION_NAME()
|
|
|
|
IF NOT DOES_TEXT_LABEL_EXIST ( CurrentSongData.Title )
|
|
CurrentSongData.Title = "CELL_195"
|
|
ENDIF
|
|
|
|
IF NOT DOES_TEXT_LABEL_EXIST ( CurrentSongData.Artist )
|
|
CurrentSongData.Artist = "CELL_195"
|
|
CurrentSongData.RadioStation = "CELL_195"
|
|
ENDIF
|
|
|
|
|
|
#if IS_DEBUG_BUILD
|
|
cdPrintnl()
|
|
cdPrintstring("Zit returned station index is ")
|
|
cdPrintint(GET_PLAYER_RADIO_STATION_INDEX())
|
|
cdPrintnl()
|
|
cdPrintstring(GET_PLAYER_RADIO_STATION_NAME())
|
|
cdPrintnl()
|
|
#endif
|
|
|
|
|
|
|
|
ENDPROC
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PROC Run_Listening_Timer()
|
|
|
|
|
|
IF TIMERA() > 2200
|
|
|
|
IF g_b_ToggleButtonLabels
|
|
|
|
LEGACY_SCALEFORM_MOVIE_METHOD_WITH_NUMBER_AND_STRING (SF_MovieIndex, "SET_SOFT_KEYS", BADGER_POS, 1,
|
|
13, INVALID_SCALEFORM_PARAM, INVALID_SCALEFORM_PARAM, "CELL_201") //"YES" - Positive
|
|
|
|
ELSE
|
|
|
|
LEGACY_SCALEFORM_MOVIE_METHOD_WITH_NUMBER_AND_STRING (SF_MovieIndex, "SET_SOFT_KEYS", BADGER_POS, 1,
|
|
13, INVALID_SCALEFORM_PARAM, INVALID_SCALEFORM_PARAM) //"YES" - Positive
|
|
|
|
ENDIF
|
|
|
|
|
|
b_OkayToUseShareButton = TRUE
|
|
|
|
ENDIF
|
|
|
|
|
|
|
|
|
|
ENDPROC
|
|
|
|
|
|
|
|
|
|
|
|
PROC Place_Song_Data_in_App()
|
|
|
|
|
|
|
|
//Would get current radio station, track details and here via some magic commands. Times played seems redundant.
|
|
|
|
|
|
BEGIN_SCALEFORM_MOVIE_METHOD (SF_MovieIndex, "SET_DATA_SLOT")
|
|
|
|
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT (23) //System
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT (0) //System
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT (0) //Zit Screen
|
|
|
|
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_STRING ("CELL_4001") //Listening text
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_STRING (CurrentSongData.Title) //Song Title
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_STRING (CurrentSongData.Artist) //Artist
|
|
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_STRING ("CELL_4002") //Times heard text
|
|
|
|
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT (CurrentSongData.i_NumberOfTimesHeard) //Times heard number
|
|
|
|
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_STRING ("CELL_4003") //Last heard on text
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_STRING (CurrentSongData.RadioStation) //Radio Station Name
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_STRING ("CELL_4004") //Share this song.
|
|
|
|
|
|
END_SCALEFORM_MOVIE_METHOD()
|
|
|
|
|
|
LEGACY_SCALEFORM_MOVIE_METHOD_WITH_NUMBER (SF_MovieIndex, "DISPLAY_VIEW", 23, TO_FLOAT(0))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
IF g_b_ToggleButtonLabels
|
|
|
|
IF b_OkayToUseShareButton
|
|
|
|
LEGACY_SCALEFORM_MOVIE_METHOD_WITH_NUMBER_AND_STRING (SF_MovieIndex, "SET_SOFT_KEYS", BADGER_POS, 1,
|
|
13, INVALID_SCALEFORM_PARAM, INVALID_SCALEFORM_PARAM, "CELL_201") //"YES" - Positive
|
|
|
|
ELSE
|
|
|
|
LEGACY_SCALEFORM_MOVIE_METHOD_WITH_NUMBER_AND_STRING (SF_MovieIndex, "SET_SOFT_KEYS", BADGER_POS, 0,
|
|
13, INVALID_SCALEFORM_PARAM, INVALID_SCALEFORM_PARAM, "CELL_201") //"YES" - Positive
|
|
|
|
ENDIF
|
|
|
|
|
|
LEGACY_SCALEFORM_MOVIE_METHOD_WITH_NUMBER_AND_STRING (SF_MovieIndex, "SET_SOFT_KEYS", BADGER_NEG, 1,
|
|
14, INVALID_SCALEFORM_PARAM, INVALID_SCALEFORM_PARAM, "CELL_213") //"NO" - Negative
|
|
|
|
|
|
ELSE
|
|
|
|
IF b_OkayToUseShareButton
|
|
|
|
LEGACY_SCALEFORM_MOVIE_METHOD_WITH_NUMBER_AND_STRING (SF_MovieIndex, "SET_SOFT_KEYS", BADGER_POS, 1,
|
|
13, INVALID_SCALEFORM_PARAM, INVALID_SCALEFORM_PARAM) //"YES" - Positive
|
|
|
|
ELSE
|
|
|
|
LEGACY_SCALEFORM_MOVIE_METHOD_WITH_NUMBER_AND_STRING (SF_MovieIndex, "SET_SOFT_KEYS", BADGER_POS, 0,
|
|
13, INVALID_SCALEFORM_PARAM, INVALID_SCALEFORM_PARAM) //"YES" - Positive
|
|
|
|
ENDIF
|
|
|
|
|
|
|
|
LEGACY_SCALEFORM_MOVIE_METHOD_WITH_NUMBER_AND_STRING (SF_MovieIndex, "SET_SOFT_KEYS", BADGER_NEG, 1,
|
|
14, INVALID_SCALEFORM_PARAM, INVALID_SCALEFORM_PARAM) //"NO" - Negative
|
|
|
|
ENDIF
|
|
|
|
LEGACY_SCALEFORM_MOVIE_METHOD_WITH_NUMBER_AND_STRING (SF_MovieIndex, "SET_SOFT_KEYS", BADGER_OTHER, 0,
|
|
1, INVALID_SCALEFORM_PARAM, INVALID_SCALEFORM_PARAM) //"Error!" - Other
|
|
CLEAR_BIT (BitSet_CellphoneDisplay, g_BS_OTHER_OPTION_IS_DISPLAYED)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ENDPROC
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PROC Check_For_Share_Selection()
|
|
|
|
|
|
IF g_InputButtonJustPressed = FALSE
|
|
IF Is_Phone_Control_Just_Pressed (FRONTEND_CONTROL, INT_TO_ENUM (CONTROL_ACTION, PHONE_POSITIVE_INPUT)) //positive action - Repeat selected.
|
|
|
|
|
|
|
|
|
|
IF b_OkayToUseShareButton
|
|
AND b_ShareComplete = FALSE
|
|
AND b_DoSharingRoutine = FALSE
|
|
|
|
/*
|
|
IF g_CellPhone.PhoneDS > PDS_AWAY //make sure that the following state assignment cannot interfere with AWAY or DISABLED assignment.
|
|
|
|
g_Cellphone.PhoneDS = PDS_COMPLEXAPP
|
|
|
|
#if IS_DEBUG_BUILD
|
|
cdPrintnl()
|
|
cdPrintstring("STATE ASSIGNMENT 230. appZit assigns PDS_COMPLEXAPP")
|
|
cdPrintnl()
|
|
#endif
|
|
|
|
ENDIF
|
|
*/
|
|
|
|
i_SharingProgress = 0 // reset sharing progress.
|
|
|
|
BEGIN_SCALEFORM_MOVIE_METHOD (SF_MovieIndex, "SET_DATA_SLOT")
|
|
|
|
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT (23) //System
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT (0) //System
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT (1) //Sharing screen
|
|
|
|
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_STRING ("CELL_4005")
|
|
|
|
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT (i_SharingProgress) //Progress bar...
|
|
|
|
END_SCALEFORM_MOVIE_METHOD()
|
|
|
|
|
|
LEGACY_SCALEFORM_MOVIE_METHOD_WITH_NUMBER (SF_MovieIndex, "DISPLAY_VIEW", 23, TO_FLOAT(0))
|
|
|
|
|
|
|
|
IF g_b_ToggleButtonLabels
|
|
LEGACY_SCALEFORM_MOVIE_METHOD_WITH_NUMBER_AND_STRING (SF_MovieIndex, "SET_SOFT_KEYS", BADGER_POS, 0,
|
|
13, INVALID_SCALEFORM_PARAM, INVALID_SCALEFORM_PARAM, "CELL_201") //"YES" - Positive
|
|
|
|
LEGACY_SCALEFORM_MOVIE_METHOD_WITH_NUMBER_AND_STRING (SF_MovieIndex, "SET_SOFT_KEYS", BADGER_NEG, 1,
|
|
14, INVALID_SCALEFORM_PARAM, INVALID_SCALEFORM_PARAM, "CELL_213") //"NO" - Negative
|
|
|
|
|
|
ELSE
|
|
LEGACY_SCALEFORM_MOVIE_METHOD_WITH_NUMBER_AND_STRING (SF_MovieIndex, "SET_SOFT_KEYS", BADGER_POS, 0,
|
|
13, INVALID_SCALEFORM_PARAM, INVALID_SCALEFORM_PARAM) //"YES" - Positive
|
|
|
|
LEGACY_SCALEFORM_MOVIE_METHOD_WITH_NUMBER_AND_STRING (SF_MovieIndex, "SET_SOFT_KEYS", BADGER_NEG, 1,
|
|
14, INVALID_SCALEFORM_PARAM, INVALID_SCALEFORM_PARAM) //"NO" - Negative
|
|
|
|
ENDIF
|
|
|
|
LEGACY_SCALEFORM_MOVIE_METHOD_WITH_NUMBER_AND_STRING (SF_MovieIndex, "SET_SOFT_KEYS", BADGER_OTHER, 0,
|
|
1, INVALID_SCALEFORM_PARAM, INVALID_SCALEFORM_PARAM) //"Error!" - Other
|
|
CLEAR_BIT (BitSet_CellphoneDisplay, g_BS_OTHER_OPTION_IS_DISPLAYED)
|
|
|
|
|
|
b_DoSharingRoutine = TRUE
|
|
|
|
SETTIMERA (0)
|
|
|
|
|
|
|
|
ENDIF
|
|
|
|
|
|
|
|
|
|
ENDIF
|
|
ENDIF
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ENDPROC
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PROC Cleanup_and_Terminate()
|
|
|
|
|
|
#if IS_DEBUG_BUILD
|
|
|
|
PRINTNL()
|
|
PRINTSTRING ("AppZIT - appZit exiting...")
|
|
PRINTNL()
|
|
|
|
#endif
|
|
|
|
|
|
b_DoSharingRoutine = FALSE //Tidy up any sharing stuff here also?
|
|
|
|
|
|
|
|
TERMINATE_THIS_THREAD()
|
|
|
|
|
|
ENDPROC
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SCRIPT
|
|
|
|
//Ensure this script persists during network game
|
|
NETWORK_SET_SCRIPT_IS_SAFE_FOR_NETWORK_GAME()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//DO NOT CHECK IN PERMANENTLY!
|
|
/*
|
|
#if IS_DEBUG_BUILD
|
|
|
|
Temp_Setup_Of_Test_Song_Data()
|
|
|
|
#endif
|
|
*/
|
|
|
|
|
|
REQUEST_ADDITIONAL_TEXT (ZitPhoneBlock, PHONE_TEXT_SLOT)
|
|
|
|
WHILE NOT HAS_ADDITIONAL_TEXT_LOADED (PHONE_TEXT_SLOT)
|
|
WAIT(0)
|
|
ENDWHILE
|
|
|
|
|
|
Get_Song_Data_From_Audio()
|
|
|
|
|
|
|
|
Place_Song_Data_in_App()
|
|
|
|
|
|
STOCK_MARKET_MUSIC_ZIT_STATION_CHECK()
|
|
SETTIMERA (0) //Initialise here for the purposes of checking "listening" timer.
|
|
|
|
|
|
|
|
WHILE TRUE
|
|
|
|
WAIT(0)
|
|
|
|
|
|
|
|
IF b_DoSharingRoutine
|
|
|
|
IF i_SharingProgress < 101
|
|
|
|
IF TIMERA() > 30
|
|
|
|
i_SharingProgress ++ //TEMP! This number should be obtained from some kind of magic get Social Club upload progress command!
|
|
|
|
BEGIN_SCALEFORM_MOVIE_METHOD (SF_MovieIndex, "SET_DATA_SLOT")
|
|
|
|
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT (23) //System
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT (0) //System
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT (1) //Sharing screen
|
|
|
|
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_STRING ("CELL_4005")
|
|
|
|
|
|
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT (i_SharingProgress) //Progress bar...
|
|
|
|
END_SCALEFORM_MOVIE_METHOD()
|
|
|
|
LEGACY_SCALEFORM_MOVIE_METHOD_WITH_NUMBER (SF_MovieIndex, "DISPLAY_VIEW", 23, TO_FLOAT(0))
|
|
|
|
SETTIMERA (0)
|
|
|
|
ENDIF
|
|
|
|
|
|
ELSE
|
|
|
|
//Sharing finished successfully. Show splash screen.
|
|
|
|
BEGIN_SCALEFORM_MOVIE_METHOD (SF_MovieIndex, "SET_DATA_SLOT")
|
|
|
|
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT (23) //System
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT (0) //System
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT (2) //Share Success screen
|
|
|
|
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_STRING ("CELL_4006")
|
|
SCALEFORM_MOVIE_METHOD_ADD_PARAM_STRING ("CELL_4007")
|
|
|
|
|
|
END_SCALEFORM_MOVIE_METHOD()
|
|
|
|
LEGACY_SCALEFORM_MOVIE_METHOD_WITH_NUMBER (SF_MovieIndex, "DISPLAY_VIEW", 23, TO_FLOAT(0))
|
|
|
|
b_ShareComplete = TRUE
|
|
|
|
b_DoSharingRoutine = FALSE
|
|
|
|
|
|
ENDIF
|
|
|
|
|
|
|
|
ENDIF
|
|
|
|
|
|
|
|
|
|
|
|
IF g_Cellphone.PhoneDS <> PDS_ONGOING_CALL //i.e a phonecall is not attempting to get through to the player.
|
|
|
|
SWITCH g_Cellphone.PhoneDS
|
|
|
|
|
|
|
|
CASE PDS_RUNNINGAPP
|
|
|
|
|
|
Check_For_Share_Selection()
|
|
|
|
|
|
IF b_OkayToUseShareButton = FALSE
|
|
|
|
Run_Listening_Timer()
|
|
|
|
ENDIF
|
|
|
|
|
|
|
|
BREAK
|
|
|
|
|
|
|
|
CASE PDS_COMPLEXAPP
|
|
|
|
|
|
IF Is_Phone_Control_Just_Pressed (FRONTEND_CONTROL, INT_TO_ENUM (CONTROL_ACTION, PHONE_GO_BACK_INPUT)) //Go back action - user opted to return to full text message list from single message display.
|
|
|
|
|
|
Play_Back_Beep()
|
|
|
|
|
|
b_DoSharingRoutine = FALSE //Tidy up any sharing technical stuff here also!
|
|
b_ShareComplete = FALSE
|
|
|
|
|
|
g_InputButtonJustPressed = TRUE
|
|
|
|
|
|
Place_Song_Data_in_App()
|
|
|
|
IF g_CellPhone.PhoneDS > PDS_AWAY //make sure that the following state assignment cannot interfere with AWAY or DISABLED assignment.
|
|
|
|
g_Cellphone.PhoneDS = PDS_RUNNINGAPP
|
|
|
|
#if IS_DEBUG_BUILD
|
|
cdPrintnl()
|
|
cdPrintstring("STATE ASSIGNMENT 213. AppZit assigns PDS_RUNNINGAPP")
|
|
cdPrintnl()
|
|
#endif
|
|
|
|
ENDIF
|
|
|
|
ENDIF
|
|
|
|
BREAK
|
|
|
|
|
|
|
|
DEFAULT
|
|
|
|
#if IS_DEBUG_BUILD
|
|
|
|
PRINTSTRING("AppZit in default state. Should terminate if exit check in place.")
|
|
PRINTNL()
|
|
|
|
#endif
|
|
|
|
BREAK
|
|
|
|
|
|
|
|
ENDSWITCH
|
|
|
|
|
|
|
|
IF CHECK_FOR_APPLICATION_EXIT()
|
|
|
|
Cleanup_and_Terminate()
|
|
|
|
ENDIF
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ELSE
|
|
|
|
|
|
|
|
//This is an important section! It tells this script what to do when a call, be it answerphone or other phonecall, comes through.
|
|
//It is important to look at how appTextMessage interacts with any change to this section as it relies upon this script to make a call to any message sender.
|
|
|
|
BeforeCallPhoneDS = PDS_MAXIMUM //After a call has finished the phone display state usually alters to whatever it was before the call came through.
|
|
//We don't really want to go back to the "calling Repeat" screen after an answerphone message so we set it to PDS_MAXIMUM
|
|
//here. We could just as easily put the phone completely away if need be.
|
|
//NB - This also means that when browsing the Repeats list, if a calls comes through and it terminates then we default
|
|
//back to MAXIMUM mode not browsing the Repeats list.
|
|
|
|
Cleanup_and_Terminate() //Likewise, having this here will make sure this script is terminated should any call come through...
|
|
|
|
|
|
|
|
|
|
ENDIF
|
|
|
|
|
|
|
|
IF CHECK_FOR_ABNORMAL_EXIT()
|
|
|
|
Cleanup_and_Terminate()
|
|
|
|
ENDIF
|
|
|
|
|
|
|
|
|
|
|
|
ENDWHILE
|
|
|
|
|
|
ENDSCRIPT
|
|
|
|
|
|
/*
|
|
[CELL_4001]
|
|
Listening...
|
|
|
|
|
|
[CELL_4002]
|
|
Times played:
|
|
|
|
[CELL_4003]
|
|
Last heard on:
|
|
|
|
[CELL_4004]
|
|
TEMP Share?
|
|
|
|
[CELL_4005]
|
|
TEMP Sharing...
|
|
|
|
[CELL_4006]
|
|
TEMP Success!
|
|
|
|
[CELL_4007]
|
|
TEMP Shared to Social Club
|
|
|
|
|
|
[CELL_4100]
|
|
Temp Song Title
|
|
|
|
[CELL_4101]
|
|
Temp Artist
|
|
|
|
[CELL_4102]
|
|
K_TEMP_FM
|
|
*/
|