diff --git a/Readme.adoc b/Readme.adoc index aae846d..56ed3aa 100644 --- a/Readme.adoc +++ b/Readme.adoc @@ -38,8 +38,4 @@ A printout of the thread with those golden informations which kick started me on == Current State -As I just started to convert the project to kotlin (the original Java code will remain private as ther is a lot of chaos...) -the REST interface itself is not yet implemented (also because I do not know which framework I want to use. -Spring boot seems not to be appropriate anymore along with kotlin and Micronaut seems to be abandonded and my -current experience with the latter during my professional work life is not so good. - +For now things here are pretty basic as I start with implementing all models needed and basic interface access. diff --git a/docs/hardware/yamaha/RX AX10 VX71 Series Function Tree-1.xls b/docs/hardware/yamaha/RX AX10 VX71 Series Function Tree-1.xls new file mode 100644 index 0000000..ddeb896 Binary files /dev/null and b/docs/hardware/yamaha/RX AX10 VX71 Series Function Tree-1.xls differ diff --git a/docs/hardware/yamaha/YXC_API_Spec_Advanced-1.pdf b/docs/hardware/yamaha/YXC_API_Spec_Advanced-1.pdf new file mode 100644 index 0000000..7328767 Binary files /dev/null and b/docs/hardware/yamaha/YXC_API_Spec_Advanced-1.pdf differ diff --git a/docs/hardware/yamaha/YXC_API_Spec_Basic.pdf b/docs/hardware/yamaha/YXC_API_Spec_Basic.pdf new file mode 100644 index 0000000..94ab961 Binary files /dev/null and b/docs/hardware/yamaha/YXC_API_Spec_Basic.pdf differ diff --git a/docs/hardware/yamaha/rx-v673_dec.xml b/docs/hardware/yamaha/rx-v673_dec.xml new file mode 100644 index 0000000..75eb342 --- /dev/null +++ b/docs/hardware/yamaha/rx-v673_dec.xml @@ -0,0 +1,2968 @@ + + + Title_1 + + + On + Off + + Param_1 + + On + Off + + + + + + + Param_1 + + Available + Unavailable + + + + + + + Param_1 + + 1,15,UTF-8 + + + + Param_1 + + 1,15,UTF-8 + + + + + + On + Standby + + + On + Off + + Param_1 + + On + Off + + + + + + Disable + Enable + + Param_1 + + Disable + Enable + + + + + System,Misc,Event,Notice + System,Power_Control,Power + System,Misc,Network,Network_Name + System,Misc,Network,Network_Standby + System,Misc,Network,DMC_Control + System,Party_Mode,Mode + System,Misc,Event,Notice + System,Misc,Network,Network_Name + System,Misc,Network,Network_Standby + System,Misc,Update,YAMAHA_Network_Site,Status + System,Misc,Network,DMC_Control + System,Party_Mode,Mode + + + + + + Param_1 + + 1,9,Latin-1 + + + + Name,Zone=Param_1 + + 1,9,Latin-1 + + + + + + + Param_1 + + + + + + Input,Input_Sel=Param_1 + + + + + + + + Param_1 + + + + + + Input,Input_Sel=Param_1 + + + + + + + + + + Val=Param_1:Exp=Param_2:Unit=Param_3 + + -805,165,5 + + + 1 + + + dB + + + + Volume,Lvl,Val=Param_1:Volume,Lvl,Exp=Param_2:Volume,Lvl,Unit=Param_3 + + -805,165,5 + + + 1 + + + dB + + + + + On + Off + + Volume,Mute=Param_1 + + On + Off + + + + + + + On + Standby + + Power_Control,Power=Param_1 + + On + Standby + + + + + Last + 120 min + 90 min + 60 min + 30 min + Off + + Power_Control,Sleep=Param_1 + + 120 min + 90 min + 60 min + 30 min + Off + + + + + + + Play + Pause + Stop + + + Skip Fwd + Skip Rev + + + + + Up + Down + Left + Right + Return + Sel + Return to Home + On Screen + Top Menu + Menu + Option + Display + + + + + + + Param_1 + + Hall in Munich + Hall in Vienna + Chamber + Cellar Club + The Roxy Theatre + The Bottom Line + Sports + Action Game + Roleplaying Game + Music Video + Standard + Spectacle + Sci-Fi + Adventure + Drama + Mono Movie + Surround Decoder + 2ch Stereo + 7ch Stereo + + + + Surround,Program_Sel,Current,Sound_Program=Param_1 + + Hall in Munich + Hall in Vienna + Chamber + Cellar Club + The Roxy Theatre + The Bottom Line + Sports + Action Game + Roleplaying Game + Music Video + Standard + Spectacle + Sci-Fi + Adventure + Drama + Mono Movie + Surround Decoder + 2ch Stereo + 7ch Stereo + + + + + On + Off + + Surround,Program_Sel,Current,Straight=Param_1 + + On + Off + + + + + On + Off + + Surround,Program_Sel,Current,Enhancer=Param_1 + + On + Off + + + + + + + + Val=Param_1:Exp=Param_2:Unit=Param_3 + + -60,60,5 + + + 1 + + + dB + + + + Sound_Video,Tone,Bass,Val=Param_1:Sound_Video,Tone,Bass,Exp=Param_2:Sound_Video,Tone,Bass,Unit=Param_3 + + -60,60,5 + + + 1 + + + dB + + + + + + Val=Param_1:Exp=Param_2:Unit=Param_3 + + -60,60,5 + + + 1 + + + dB + + + + Sound_Video,Tone,Treble,Val=Param_1:Sound_Video,Tone,Treble,Exp=Param_2:Sound_Video,Tone,Treble,Unit=Param_3 + + -60,60,5 + + + 1 + + + dB + + + + + + + Val=Param_1:Exp=Param_2:Unit=Param_3 + + -60,60,5 + + + 1 + + + dB + + + + Volume,Subwoofer_Trim,Val=Param_1:Volume,Subwoofer_Trim,Exp=Param_2:Volume,Subwoofer_Trim,Unit=Param_3 + + -60,60,5 + + + 1 + + + dB + + + + + Auto + Off + + Sound_Video,Adaptive_DRC=Param_1 + + Auto + Off + + + + + Auto + Off + + Surround,_3D_Cinema_DSP=Param_1 + + Auto + Off + + + + + + Param_1 + + 0,5,1 + + + + Sound_Video,Dialogue_Adjust,Dialogue_Lift=Param_1 + + 0,5,1 + + + + + + Param_1 + + 0,3,1 + + + + Sound_Video,Dialogue_Adjust,Dialogue_Lvl=Param_1 + + 0,3,1 + + + + + On + Off + + Sound_Video,Pure_Direct,Mode=Param_1 + + On + Off + + + + + + Sound_Video,HDMI,Standby_Through_Info=Param_1 + + On + Off + + + + + + Main_Zone,Power_Control,Power + Main_Zone,Volume,Lvl + Main_Zone,Volume,Mute + Main_Zone,Input,Input_Sel + Main_Zone,Config,Name,Zone + Main_Zone,Scene,Scene_Sel + Main_Zone,Sound_Video,Tone,Bass + Main_Zone,Sound_Video,Tone,Treble + Main_Zone,Surround,Program_Sel,Current,Sound_Program + Main_Zone,Surround,Program_Sel,Current,Straight + Main_Zone,Surround,Program_Sel,Current,Enhancer + Main_Zone,Sound_Video,Adaptive_DRC + Main_Zone,Surround,_3D_Cinema_DSP + Main_Zone,Sound_Video,Dialogue_Adjust,Dialogue_Lift + System,Sound_Video,HDMI,Video,Preset_Sel,Current + Main_Zone,Sound_Video,Pure_Direct,Mode + Main_Zone,List_Control,Cursor + Main_Zone,List_Control,Menu_Control + Main_Zone,Surround,Enhancer_Type + Main_Zone,Sound_Video,Dialogue_Adjust,Dialogue_Lvl + Main_Zone,Volume,Subwoofer_Trim + Main_Zone,Power_Control,Sleep + Main_Zone,Play_Control,Playback + Main_Zone,Basic_Status + Main_Zone,Input,Input_Sel_Item + Main_Zone,Config + Main_Zone,Scene,Scene_Sel_Item + + + + + + Param_1 + + 1,9,Latin-1 + + + + Name,Zone=Param_1 + + 1,9,Latin-1 + + + + + + Param_1 + + + + + + Input,Input_Sel=Param_1 + + + + + + + + + Val=Param_1:Exp=Param_2:Unit=Param_3 + + -805,165,5 + + + 1 + + + dB + + + + Volume,Lvl,Val=Param_1:Volume,Lvl,Exp=Param_2:Volume,Lvl,Unit=Param_3 + + -805,165,5 + + + 1 + + + dB + + + + + On + Off + + Volume,Mute=Param_1 + + On + Off + + + + + + Volume,Output_Info=Param_1 + + Fixed + Variable + + + + + + + On + Standby + + Power_Control,Power=Param_1 + + On + Standby + + + + + Last + 120 min + 90 min + 60 min + 30 min + Off + + Power_Control,Sleep=Param_1 + + 120 min + 90 min + 60 min + 30 min + Off + + + + + + + Play + Pause + Stop + + + Skip Fwd + Skip Rev + + + + Zone_2,Power_Control,Power + Zone_2,Volume,Lvl + Zone_2,Volume,Mute + Zone_2,Input,Input_Sel + Zone_2,Config,Name,Zone + Zone_2,Scene,Scene_Sel + Zone_2,Sound_Video,Tone,Bass + Zone_2,Sound_Video,Tone,Treble + Zone_2,List_Control,Cursor + Zone_2,List_Control,Menu_Control + Zone_2,Volume,Output + Zone_2,Power_Control,Sleep + Zone_2,Play_Control,Playback + Zone_2,Basic_Status + Zone_2,Input,Input_Sel_Item + Zone_2,Config + Zone_2,Scene,Scene_Sel_Item + + + + + + Feature_Availability=Param_1 + + Ready + Not Ready + + + + + + + Auto Up + Auto Down + Cancel + + Tuning,Freq,AM,Val=Param_1:Tuning,Freq,AM,Exp=Param_2:Tuning,Freq,AM,Unit=Param_3 + + Auto Up + Auto Down + 531,1611,9 + + + + 0 + + + + kHz + + + + + Auto Up + Auto Down + Cancel + + Tuning,Freq,FM,Val=Param_1:Tuning,Freq,FM,Exp=Param_2:Tuning,Freq,FM,Unit=Param_3 + + Auto Up + Auto Down + TP Up + TP Down + 8750,10800,5 + + + + 2 + + + + MHz + + + + + TP Up + TP Down + Cancel + + Tuning,Freq,FM,Val=Param_1:Tuning,Freq,FM,Exp=Param_2:Tuning,Freq,FM,Unit=Param_3 + + Auto Up + Auto Down + TP Up + TP Down + 8750,10800,5 + + + + 2 + + + + MHz + + + + + Up + Down + + Preset,Preset_Sel=Param_1 + + + + + + + + AM + FM + + Tuning,Band=Param_1 + + AM + FM + + + + + + + Val=Param_1:Exp=Param_2:Unit=Param_3 + + 531,1611,9 + + + 0 + + + kHz + + + + Tuning,Freq,AM,Val=Param_1:Tuning,Freq,AM,Exp=Param_2:Tuning,Freq,AM,Unit=Param_3 + + Auto Up + Auto Down + 531,1611,9 + + + + 0 + + + + kHz + + + + + + Val=Param_1:Exp=Param_2:Unit=Param_3 + + 8750,10800,5 + + + 2 + + + MHz + + + + Tuning,Freq,FM,Val=Param_1:Tuning,Freq,FM,Exp=Param_2:Tuning,Freq,FM,Unit=Param_3 + + Auto Up + Auto Down + TP Up + TP Down + 8750,10800,5 + + + + 2 + + + + MHz + + + + + + + Param_1 + + + + + + Preset,Preset_Sel=Param_1 + + + + + + + + + + Tuning,Band=Param_1 + + AM + FM + + + + + + Tuning,Freq,Current,Val=Param_1:Tuning,Freq,Current,Exp=Param_2:Tuning,Freq,Current,Unit=Param_3 + + Auto Up + Auto Down + TP Up + TP Down + 531,1611,9 + 8750,10800,5 + + + + 0 + 2 + + + + kHz + MHz + + + + + + Meta_Info,Program_Type=Param_1 + + 0,8,Ascii + + + + + + Meta_Info,Program_Service=Param_1 + + 0,8,Ascii + + + + + + Meta_Info,Radio_Text_A=Param_1 + + 0,64,Ascii + + + + + + Meta_Info,Radio_Text_B=Param_1 + + 0,64,Ascii + + + + + + Meta_Info,Clock_Time=Param_1 + + 0,5,Ascii + + + + + + + Signal_Info,Tuned=Param_1 + + Negate + Assert + + + + + + Signal_Info,Stereo=Param_1 + + Negate + Assert + + + + + + + + "Play Info." + + + "Play Info." + "Play Control","Frequency","AM" + "Play Control","Frequency","FM" + "Play Control","Preset" + + + + + + Tuner,Play_Control,Search_Mode + Tuner,Play_Control,Preset,Preset_Sel + Tuner,Play_Control,Tuning,Band + Tuner,Play_Control,Tuning,Freq + Tuner,Play_Control,Auto_Freq + Tuner,Play_Control,Tuning,Freq,FM + Tuner,Play_Control,Tuning,Freq,AM + Tuner,Play_Control,Tuning,Freq,FM,Val + Tuner,Play_Control,Tuning,Freq,AM,Val + Tuner,Play_Info + Tuner,Config + Tuner,Play_Control,Preset,Preset_Sel_Item + + + + + + Feature_Availability=Param_1 + + Ready + Not Ready + + + + + + Play + Pause + + Playback_Info=Param_1 + + Play + Stop + + + + + Skip Fwd + Skip Rev + + + + + + Meta_Info,Artist=Param_1 + + 0,128,UTF-8 + + + + + + Meta_Info,Album=Param_1 + + 0,128,UTF-8 + + + + + + Meta_Info,Song=Param_1 + + 0,128,UTF-8 + + + + + + Feature_Availability=Param_1 + + Ready + Not Ready + + + + + + Playback_Info=Param_1 + + Play + Stop + + + + + + Album_ART,URL=Param_1 + + 0,128,UTF-8 + + + + + + Album_ART,ID=Param_1 + + 0,255,1 + + + + + + Album_ART,Format=Param_1 + + BMP + YMF + + + + + + Input_Logo,URL_S=Param_1 + + 0,128,UTF-8 + + + + + + "List Browse" + "Play Info." + + + "Play Info." + "Play Control","Shuffle" + "Play Control","Repeat" + + + + "Play Control","Shuffle" + "Play Control","Repeat" + "Play Info." + + + + + Play + + + Pause + + + Stop + + + Skip Fwd + + + Skip Rev + + + + AirPlay,Play_Control,Playback + AirPlay,Play_Info + AirPlay,Config + + + + + Extended + + + + Feature_Availability=Param_1 + + Ready + Not Ready + + + + + + Off + One + All + + Play_Mode,Repeat=Param_1 + + Off + One + All + + + + + Off + Songs + Albums + + Play_Mode,Shuffle=Param_1 + + Off + Songs + Albums + + + + + Play + Pause + Stop + + Playback_Info=Param_1 + + Play + Pause + Stop + + + + + Skip Fwd + Skip Rev + + + + + + Meta_Info,Artist=Param_1 + + 0,128,UTF-8 + + + + + + Meta_Info,Album=Param_1 + + 0,128,UTF-8 + + + + + + Meta_Info,Song=Param_1 + + 0,128,UTF-8 + + + + + + Feature_Availability=Param_1 + + Ready + Not Ready + + + + + + Playback_Info=Param_1 + + Play + Pause + Stop + + + + + + Play_Mode,Repeat=Param_1 + + Off + One + All + + + + + + Play_Mode,Shuffle=Param_1 + + Off + Songs + Albums + + + + + + Album_ART,URL=Param_1 + + 0,128,UTF-8 + + + + + + Album_ART,ID=Param_1 + + 0,255,1 + + + + + + Album_ART,Format=Param_1 + + BMP + YMF + + + + + + + + + Param_1 + + 1,8,1,Line_% + + + + + Up + Down + Return + Sel + Return to Home + + + + Param_1 + + 1,65536,1 + + + + + Up + Down + + + + + + Menu_Status=Param_1 + + Ready + Busy + + + + + + Menu_Layer=Param_1 + + 1,16,1 + + + + + + Menu_Name=Param_1 + + 0,128,UTF-8 + + + + + + Line_1 + + Current_List,Line_1,Txt=Param_1:Current_List,Line_1,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + Line_2 + + Current_List,Line_2,Txt=Param_1:Current_List,Line_2,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + Line_3 + + Current_List,Line_3,Txt=Param_1:Current_List,Line_3,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + Line_4 + + Current_List,Line_4,Txt=Param_1:Current_List,Line_4,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + Line_5 + + Current_List,Line_5,Txt=Param_1:Current_List,Line_5,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + Line_6 + + Current_List,Line_6,Txt=Param_1:Current_List,Line_6,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + Line_7 + + Current_List,Line_7,Txt=Param_1:Current_List,Line_7,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + Line_8 + + Current_List,Line_8,Txt=Param_1:Current_List,Line_8,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + + + Cursor_Position,Current_Line=Param_1 + + 1,65536,1 + + + + + + Cursor_Position,Max_Line=Param_1 + + 0,65536,1 + + + + + + + "List Browse" + "Play Info." + + + "Play Info." + "Play Control","Shuffle" + "Play Control","Repeat" + + + + "Play Control","Shuffle" + "Play Control","Repeat" + "Play Info." + + + + + Play + + + Pause + + + Stop + + + Skip Fwd + + + Skip Rev + + + + iPod_USB,Play_Control,Playback + iPod_USB,List_Control,Direct_Sel + iPod_USB,List_Control,Jump_Line + iPod_USB,List_Control,Cursor + iPod_USB,List_Control,Page + iPod_USB,List_Control,Others + iPod_USB,Play_Control,Play_Mode,Repeat + iPod_USB,Play_Control,Play_Mode,Shuffle + iPod_USB,Play_Control,iPod_Mode + iPod_USB,Play_Info + iPod_USB,List_Info + iPod_USB,Config + + + + + + Feature_Availability=Param_1 + + Ready + Not Ready + + + + + + Off + One + All + + Play_Mode,Repeat=Param_1 + + Off + One + All + + + + + Off + On + + Play_Mode,Shuffle=Param_1 + + Off + On + + + + + Play + Pause + Stop + + Playback_Info=Param_1 + + Play + Pause + Stop + + + + + Skip Fwd + Skip Rev + + + + + + Meta_Info,Artist=Param_1 + + 0,64,UTF-8 + + + + + + Meta_Info,Album=Param_1 + + 0,64,UTF-8 + + + + + + Meta_Info,Song=Param_1 + + 0,64,UTF-8 + + + + + + Feature_Availability=Param_1 + + Ready + Not Ready + + + + + + Playback_Info=Param_1 + + Play + Pause + Stop + + + + + + Play_Mode,Repeat=Param_1 + + Off + One + All + + + + + + Play_Mode,Shuffle=Param_1 + + Off + On + + + + + + Album_ART,URL=Param_1 + + 0,128,UTF-8 + + + + + + Album_ART,ID=Param_1 + + 0,255,1 + + + + + + Album_ART,Format=Param_1 + + BMP + YMF + + + + + + + + + Param_1 + + 1,8,1,Line_% + + + + + Up + Down + Return + Sel + Return to Home + + + + Param_1 + + 1,65536,1 + + + + + Up + Down + + + + + + Menu_Status=Param_1 + + Ready + Busy + + + + + + Menu_Layer=Param_1 + + 1,16,1 + + + + + + Menu_Name=Param_1 + + 0,128,UTF-8 + + + + + + Line_1 + + Current_List,Line_1,Txt=Param_1:Current_List,Line_1,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + Line_2 + + Current_List,Line_2,Txt=Param_1:Current_List,Line_2,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + Line_3 + + Current_List,Line_3,Txt=Param_1:Current_List,Line_3,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + Line_4 + + Current_List,Line_4,Txt=Param_1:Current_List,Line_4,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + Line_5 + + Current_List,Line_5,Txt=Param_1:Current_List,Line_5,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + Line_6 + + Current_List,Line_6,Txt=Param_1:Current_List,Line_6,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + Line_7 + + Current_List,Line_7,Txt=Param_1:Current_List,Line_7,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + Line_8 + + Current_List,Line_8,Txt=Param_1:Current_List,Line_8,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + + + Cursor_Position,Current_Line=Param_1 + + 1,65536,1 + + + + + + Cursor_Position,Max_Line=Param_1 + + 0,65536,1 + + + + + + + "Play Info." + "Play Control","Shuffle" + "Play Control","Repeat" + "Play Control","Preset" + + + "List Browse" + "Play Info." + + + + "Play Control","Shuffle" + "Play Control","Repeat" + "Play Info." + + + + + Play + + + Stop + + + Skip Fwd + + + Skip Rev + + + + USB,Play_Control,Play_Mode,Repeat + USB,Play_Control,Play_Mode,Shuffle + USB,Play_Control,Playback + USB,Play_Control,Preset,Preset_Sel + USB,List_Control,Direct_Sel + USB,List_Control,Jump_Line + USB,List_Control,Cursor + USB,List_Control,Page + USB,Play_Info + USB,List_Info + USB,Config + USB,Play_Control,Preset,Preset_Sel_Item + + + + + + Feature_Availability=Param_1 + + Ready + Not Ready + + + + + + Play + Stop + + Playback_Info=Param_1 + + Play + Stop + + + + + + + + Meta_Info,Station=Param_1 + + 0,128,UTF-8 + + + + + + Meta_Info,Album=Param_1 + + 0,128,UTF-8 + + + + + + Meta_Info,Song=Param_1 + + 0,128,UTF-8 + + + + + + Feature_Availability=Param_1 + + Ready + Not Ready + + + + + + Playback_Info=Param_1 + + Play + Stop + + + + + + Album_ART,URL=Param_1 + + 0,128,UTF-8 + + + + + + Album_ART,ID=Param_1 + + 0,255,1 + + + + + + Album_ART,Format=Param_1 + + BMP + YMF + + + + + + + + + Param_1 + + 1,8,1,Line_% + + + + + Up + Down + Return + Sel + Return to Home + + + + Param_1 + + 1,65536,1 + + + + + Up + Down + + + + + + Menu_Status=Param_1 + + Ready + Busy + + + + + + Menu_Layer=Param_1 + + 1,16,1 + + + + + + Menu_Name=Param_1 + + 0,128,UTF-8 + + + + + + Line_1 + + Current_List,Line_1,Txt=Param_1:Current_List,Line_1,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + Line_2 + + Current_List,Line_2,Txt=Param_1:Current_List,Line_2,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + Line_3 + + Current_List,Line_3,Txt=Param_1:Current_List,Line_3,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + Line_4 + + Current_List,Line_4,Txt=Param_1:Current_List,Line_4,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + Line_5 + + Current_List,Line_5,Txt=Param_1:Current_List,Line_5,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + Line_6 + + Current_List,Line_6,Txt=Param_1:Current_List,Line_6,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + Line_7 + + Current_List,Line_7,Txt=Param_1:Current_List,Line_7,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + Line_8 + + Current_List,Line_8,Txt=Param_1:Current_List,Line_8,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + + + Cursor_Position,Current_Line=Param_1 + + 1,65536,1 + + + + + + Cursor_Position,Max_Line=Param_1 + + 0,65536,1 + + + + + + + "Play Info." + "Play Control","Preset" + + + "List Browse" + "Play Info." + + + + "Play Info." + + + + + Play + + + Stop + + + + NET_RADIO,Play_Control,Playback + NET_RADIO,List_Control,Direct_Sel + NET_RADIO,List_Control,Jump_Line + NET_RADIO,List_Control,Cursor + NET_RADIO,List_Control,Page + NET_RADIO,Play_Control,Preset,Preset_Sel + NET_RADIO,List_Control,Bookmark + NET_RADIO,Play_Info + NET_RADIO,List_Info + NET_RADIO,Config + NET_RADIO,Play_Control,Preset,Preset_Sel_Item + + + + + + Feature_Availability=Param_1 + + Ready + Not Ready + + + + + + Off + One + All + + Play_Mode,Repeat=Param_1 + + Off + One + All + + + + + Off + On + + Play_Mode,Shuffle=Param_1 + + Off + On + + + + + Play + Pause + Stop + + Playback_Info=Param_1 + + Play + Pause + Stop + + + + + Skip Fwd + Skip Rev + + + + + + Meta_Info,Artist=Param_1 + + 0,128,UTF-8 + + + + + + Meta_Info,Album=Param_1 + + 0,128,UTF-8 + + + + + + Meta_Info,Song=Param_1 + + 0,128,UTF-8 + + + + + + Feature_Availability=Param_1 + + Ready + Not Ready + + + + + + Playback_Info=Param_1 + + Play + Pause + Stop + + + + + + Play_Mode,Repeat=Param_1 + + Off + One + All + + + + + + Play_Mode,Shuffle=Param_1 + + Off + On + + + + + + Album_ART,URL=Param_1 + + 0,128,UTF-8 + + + + + + Album_ART,ID=Param_1 + + 0,255,1 + + + + + + Album_ART,Format=Param_1 + + BMP + YMF + + + + + + + + + Param_1 + + 1,8,1,Line_% + + + + + Up + Down + Return + Sel + Return to Home + + + + Param_1 + + 1,65536,1 + + + + + Up + Down + + + + + + Menu_Status=Param_1 + + Ready + Busy + + + + + + Menu_Layer=Param_1 + + 1,16,1 + + + + + + Menu_Name=Param_1 + + 0,128,UTF-8 + + + + + + Line_1 + + Current_List,Line_1,Txt=Param_1:Current_List,Line_1,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + Line_2 + + Current_List,Line_2,Txt=Param_1:Current_List,Line_2,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + Line_3 + + Current_List,Line_3,Txt=Param_1:Current_List,Line_3,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + Line_4 + + Current_List,Line_4,Txt=Param_1:Current_List,Line_4,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + Line_5 + + Current_List,Line_5,Txt=Param_1:Current_List,Line_5,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + Line_6 + + Current_List,Line_6,Txt=Param_1:Current_List,Line_6,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + Line_7 + + Current_List,Line_7,Txt=Param_1:Current_List,Line_7,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + Line_8 + + Current_List,Line_8,Txt=Param_1:Current_List,Line_8,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + + + + + + + Cursor_Position,Current_Line=Param_1 + + 1,65536,1 + + + + + + Cursor_Position,Max_Line=Param_1 + + 0,65536,1 + + + + + + + "Play Info." + "Play Control","Shuffle" + "Play Control","Repeat" + "Play Control","Preset" + + + "List Browse" + "Play Info." + + + + "Play Control","Shuffle" + "Play Control","Repeat" + "Play Info." + + + + + Play + + + Pause + + + Stop + + + Skip Fwd + + + Skip Rev + + + + SERVER,Play_Control,Play_Mode,Repeat + SERVER,Play_Control,Play_Mode,Shuffle + SERVER,Play_Control,Playback + SERVER,Play_Control,Preset,Preset_Sel + SERVER,List_Control,Direct_Sel + SERVER,List_Control,Jump_Line + SERVER,List_Control,Cursor + SERVER,List_Control,Page + SERVER,Play_Control,Play_URI + SERVER,Play_Info + SERVER,List_Info + SERVER,Config + SERVER,Play_Control,Preset,Preset_Sel_Item + + + + + + Feature_Availability=Param_1 + + Ready + Not Ready + + + + + + Off + One + All + + Play_Mode,Repeat=Param_1 + + Off + One + All + + + + + Off + On + + Play_Mode,Shuffle=Param_1 + + Off + On + + + + + Play + Pause + Stop + + Playback_Info=Param_1 + + Play + Pause + Stop + + + + + Skip Fwd + Skip Rev + + + + + + Meta_Info,Artist=Param_1 + + 0,128,UTF-8 + + + + + + Meta_Info,Album=Param_1 + + 0,128,UTF-8 + + + + + + Meta_Info,Song=Param_1 + + 0,128,UTF-8 + + + + + + Feature_Availability=Param_1 + + Ready + Not Ready + + + + + + Playback_Info=Param_1 + + Play + Pause + Stop + + + + + + Play_Mode,Repeat=Param_1 + + Off + One + All + + + + + + Play_Mode,Shuffle=Param_1 + + Off + On + + + + + + Album_ART,URL=Param_1 + + 0,128,UTF-8 + + + + + + Album_ART,ID=Param_1 + + 0,255,1 + + + + + + Album_ART,Format=Param_1 + + BMP + YMF + + + + + + Input_Logo,URL_S=Param_1 + + 0,128,UTF-8 + + + + + + + + + Param_1 + + 1,8,1,Line_% + + + + + + Line=Param_1:Keyword=Param_2 + + 1,8,1,Line_% + + + 0,30,Ascii + + + + + Up + Down + Return + Sel + Return to Home + + + + Param_1 + + 1,65536,1 + + + + + Up + Down + + + + + + Menu_Status=Param_1 + + Ready + Busy + + + + + + Menu_Layer=Param_1 + + 1,16,1 + + + + + + Menu_Name=Param_1 + + 0,128,UTF-8 + + + + + + Line_1 + + Current_List,Line_1,Txt=Param_1:Current_List,Line_1,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + Keyword + + + + + Line_2 + + Current_List,Line_2,Txt=Param_1:Current_List,Line_2,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + Keyword + + + + + Line_3 + + Current_List,Line_3,Txt=Param_1:Current_List,Line_3,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + Keyword + + + + + Line_4 + + Current_List,Line_4,Txt=Param_1:Current_List,Line_4,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + Keyword + + + + + Line_5 + + Current_List,Line_5,Txt=Param_1:Current_List,Line_5,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + Keyword + + + + + Line_6 + + Current_List,Line_6,Txt=Param_1:Current_List,Line_6,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + Keyword + + + + + Line_7 + + Current_List,Line_7,Txt=Param_1:Current_List,Line_7,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + Keyword + + + + + Line_8 + + Current_List,Line_8,Txt=Param_1:Current_List,Line_8,Attribute=Param_2 + + 0,128,UTF-8 + + + Container + Unplayable Item + Item + Unselectable + Keyword + + + + + + + Cursor_Position,Current_Line=Param_1 + + 1,65536,1 + + + + + + Cursor_Position,Max_Line=Param_1 + + 0,65536,1 + + + + + + + "Play Info." + "Play Control","Shuffle" + "Play Control","Repeat" + "Play Control","Preset" + + + "List Browse" + "Play Info." + + + + "Play Control","Shuffle" + "Play Control","Repeat" + "Play Info." + + + + + Play + + + Pause + + + Stop + + + Skip Fwd + + + Skip Rev + + + + Napster,Play_Control,Play_Mode,Repeat + Napster,Play_Control,Play_Mode,Shuffle + Napster,Play_Control,Playback + Napster,Play_Control,Preset,Preset_Sel + Napster,List_Control,Direct_Sel + Napster,List_Control,Jump_Line + Napster,List_Control,Cursor + Napster,List_Control,Page + Napster,List_Control,Direct_Sel_with_Keyword + Napster,Play_Info + Napster,List_Info + Napster,Config + Napster,Play_Control,Preset,Preset_Sel_Item + + + \ No newline at end of file diff --git a/klanglicht-core/pom.xml b/klanglicht-core/pom.xml index b3cb5fa..5a2e6a6 100644 --- a/klanglicht-core/pom.xml +++ b/klanglicht-core/pom.xml @@ -16,56 +16,6 @@ ${revision} - - - - org.apache.commons - commons-lang3 - 3.12.0 - - - commons-codec - commons-codec - 1.15 - - - com.google.guava - guava - 31.1-jre - - - - - com.fasterxml.jackson.core - jackson-core - ${version.jackson} - - - com.fasterxml.jackson.core - jackson-annotations - ${version.jackson} - - - com.fasterxml.jackson.core - jackson-databind - ${version.jackson} - - - com.fasterxml.jackson.dataformat - jackson-dataformat-xml - ${version.jackson} - - - com.fasterxml.jackson.module - jackson-module-kotlin - ${version.jackson} - - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - ${version.jackson} - - io.github.java-native diff --git a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/dmx/DMXInterface.kt b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/dmx/DMXInterface.kt index dc8ea41..f764e99 100644 --- a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/dmx/DMXInterface.kt +++ b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/dmx/DMXInterface.kt @@ -1,5 +1,7 @@ package de.visualdigits.kotlin.klanglicht.dmx +import de.visualdigits.kotlin.klanglicht.model.dmx.DMXInterfaceType +import de.visualdigits.kotlin.klanglicht.model.dmx.DmxFrame import jssc.SerialPort import jssc.SerialPortException import org.apache.commons.lang3.StringUtils diff --git a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/Color.kt b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/Color.kt index b8784d3..53104c7 100644 --- a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/Color.kt +++ b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/Color.kt @@ -1,6 +1,8 @@ package de.visualdigits.kotlin.klanglicht.model.color -interface Color { +import de.visualdigits.kotlin.klanglicht.model.parameter.Parameter + +interface Color> : Parameter { fun value(): Long @@ -17,6 +19,4 @@ interface Color { fun toRGBW(): RGBWColor fun toRGBA(): RGBAColor - - fun toColorParameter(): ColorParameter } diff --git a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/ColorParameter.kt b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/ColorParameter.kt deleted file mode 100644 index 288c97b..0000000 --- a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/ColorParameter.kt +++ /dev/null @@ -1,71 +0,0 @@ -package de.visualdigits.kotlin.klanglicht.model.color - -import de.visualdigits.kotlin.klanglicht.model.parameter.Parameter -import org.apache.commons.lang3.StringUtils - - -data class ColorParameter( - val red: Int = 0, - val green: Int = 0, - val blue: Int = 0, - val white: Int = 0, - val amber: Int = 0, -) : Parameter(), Color { - - init { - parameterMap.putAll(mapOf( - "Red" to red, - "Green" to green, - "Blue" to blue, - "White" to white, - "Amber" to amber - )) - } - - inline fun color(): T { - return when (T::class) { - RGBWAColor::class -> RGBWAColor(red, green, blue, white, amber) as T - RGBWColor::class -> RGBWColor(red, green, blue, white) as T - RGBAColor::class -> RGBAColor(red, green, blue, amber) as T - else -> RGBColor(red, green, blue) as T - } - } - - fun mix(other: Color, factor: Double): ColorParameter { - val mixedColor = color().mix(other, factor) - return ColorParameter( - red = mixedColor.red, - green = mixedColor.green, - blue = mixedColor.blue, - white = mixedColor.white - ) - } - - override fun value(): Long = red.toLong() shl 16 or (green.toLong() shl 8) or blue.toLong() - - override fun hex(): String = StringUtils.leftPad(java.lang.Long.toHexString(value()), 6, '0') - - override fun web(): String = "#${hex()}" - - override fun ansiColor(): String = "\u001B[39m\u001B[48;2;$red;$green;${blue}m \u001B[0m" - - override fun toRGB(): RGBColor { - return color() - } - - override fun toHSV(): HSVColor { - return color().toHSV() - } - - override fun toRGBW(): RGBWColor { - return color() - } - - override fun toRGBA(): RGBAColor { - return color() - } - - override fun toColorParameter(): ColorParameter { - return this - } -} diff --git a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/HSVColor.kt b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/HSVColor.kt index 05850c1..2609dd1 100644 --- a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/HSVColor.kt +++ b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/HSVColor.kt @@ -1,6 +1,9 @@ package de.visualdigits.kotlin.klanglicht.model.color +import de.visualdigits.kotlin.klanglicht.model.parameter.IntParameter +import de.visualdigits.kotlin.klanglicht.model.parameter.Parameter import org.apache.commons.lang3.StringUtils +import java.lang.IllegalArgumentException import kotlin.math.floor import kotlin.math.roundToInt @@ -11,7 +14,7 @@ class HSVColor( var s: Int = 0, /** 0 -100 */ var v: Int = 0 -) : Color { +) : Color { override fun toString(): String { return "[" + StringUtils.join(listOf(h, s, v), ", ") + "]" @@ -21,6 +24,21 @@ class HSVColor( return "RGBColor(hex='${web()}', h=$h, s=$s , v=$v)" } + override fun parameterMap(): Map { + val rgbColor = toRGB() + return mapOf( + "Red" to rgbColor.red, + "Green" to rgbColor.green, + "Blue" to rgbColor.blue, + ) + } + + override fun fade(other: Parameter<*>, factor: Double): HSVColor { + return if (other is HSVColor) { + other.toRGB().fade(other.toRGB(), factor).toHSV() + } else throw IllegalArgumentException("Cannot fade different parameter type") + } + override fun toRGB(): RGBColor { val h = (this.h / 360.0) val s = (this.s / 100.0) @@ -51,10 +69,6 @@ class HSVColor( ) } - inline fun mix(other: Color, factor: Double): T { - return toRGB().mix(other, factor) - } - override fun value(): Long { return toRGB().value() } @@ -82,8 +96,4 @@ class HSVColor( override fun toRGBA(): RGBAColor { return toRGB().toRGBA() } - - override fun toColorParameter(): ColorParameter { - return toRGB().toColorParameter() - } } diff --git a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/NamedParameter.kt b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/NamedParameter.kt deleted file mode 100644 index 27cad0d..0000000 --- a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/NamedParameter.kt +++ /dev/null @@ -1,13 +0,0 @@ -package de.visualdigits.kotlin.klanglicht.model.color - -import de.visualdigits.kotlin.klanglicht.model.parameter.Parameter - -class NamedParameter( - val name: String, - val value: Int = 0 -) : Parameter() { - - init { - parameterMap.put(name, value) - } -} diff --git a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/RGBAColor.kt b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/RGBAColor.kt index 03392a8..bc35fbb 100644 --- a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/RGBAColor.kt +++ b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/RGBAColor.kt @@ -1,6 +1,8 @@ package de.visualdigits.kotlin.klanglicht.model.color +import de.visualdigits.kotlin.klanglicht.model.parameter.Parameter import org.apache.commons.lang3.StringUtils +import java.lang.IllegalArgumentException import kotlin.math.min import kotlin.math.roundToInt import java.lang.Long.decode @@ -10,7 +12,7 @@ class RGBAColor( green: Int = 0, blue: Int = 0, var amber: Int = 0 -) : RGBColor(red, green, blue) { +) : RGBBaseColor(red, green, blue) { companion object { const val AMBER_RED = 255.0 @@ -35,12 +37,22 @@ class RGBAColor( return "RGBColor(hex='${web()}', r=$red, g=$green , b=$blue, a=$amber)" } - override fun toRGB(): RGBColor { - return RGBColor( - red = min(255, red + (amber / AMBER_FACTOR).roundToInt()), - green = min(255, green + (amber * AMBER_FACTOR).roundToInt()), - blue = blue - ) + override fun parameterMap(): Map = mapOf( + "Red" to red, + "Green" to green, + "Blue" to blue, + "Amber" to amber + ) + + override fun fade(other: Parameter<*>, factor: Double): RGBAColor { + return if (other is RGBAColor) { + RGBAColor( + red = min(255, (red + factor * (other.red - red)).roundToInt()), + green = min(255, (green + factor * (other.green - green)).roundToInt()), + blue = min(255, (blue + factor * (other.blue - blue)).roundToInt()), + amber = min(255, (amber + factor * (other.amber - amber)).roundToInt()) + ) + } else throw IllegalArgumentException("Cannot fade different parameter type") } override fun value(): Long = (red.toLong() shl 24) or (green.toLong() shl 16) or (blue.toLong() shl 8) or amber.toLong() @@ -53,6 +65,14 @@ class RGBAColor( return toRGB().ansiColor() } + override fun toRGB(): RGBColor { + return RGBColor( + red = min(255, red + (amber / AMBER_FACTOR).roundToInt()), + green = min(255, green + (amber * AMBER_FACTOR).roundToInt()), + blue = blue + ) + } + override fun toHSV(): HSVColor { return toRGB().toHSV() } diff --git a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/RGBBaseColor.kt b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/RGBBaseColor.kt new file mode 100644 index 0000000..2248824 --- /dev/null +++ b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/RGBBaseColor.kt @@ -0,0 +1,139 @@ +package de.visualdigits.kotlin.klanglicht.model.color + +import org.apache.commons.lang3.StringUtils +import java.lang.Long.decode +import java.lang.Long.toHexString +import kotlin.math.max +import kotlin.math.min +import kotlin.math.roundToInt + + +abstract class RGBBaseColor>( + var red: Int = 0, + var green: Int = 0, + var blue: Int = 0 +) : Color { + + constructor(value: Long) : this( + red = min(a = 255, b = (value and 0x00ff0000L shr 16).toInt()), + green = min(a = 255, b = (value and 0x0000ff00L shr 8).toInt()), + blue = min(a = 255, b = (value and 0x000000ffL).toInt()) + ) + + constructor(hex: String) : this(decode(if (hex.startsWith("#") || hex.startsWith("0x")) hex else "#$hex")) + + override fun toString(): String { + return "[" + StringUtils.join(listOf(red, green, blue), ", ") + "]" + } + + open fun repr(): String { + return "RGBColor(hex='${web()}', r=$red, g=$green , b=$blue)" + } + + override fun value(): Long = red.toLong() shl 16 or (green.toLong() shl 8) or blue.toLong() + + override fun hex(): String = StringUtils.leftPad(toHexString(value()), 6, '0') + + override fun web(): String = "#${hex()}" + + override fun ansiColor(): String = "\u001B[39m\u001B[48;2;$red;$green;${blue}m \u001B[0m" + + inline fun > convert(): T { + return when (T::class) { + RGBWColor::class -> toRGBW() as T + RGBAColor::class -> toRGBA() as T + HSVColor::class -> toHSV() as T + RGBBaseColor::class -> toRGB() as T + else -> throw IllegalStateException("Unsupported color type") + } + } + + override fun toRGB(): RGBColor { + return RGBColor( + red = red, + green = green, + blue = blue + ) + } + + override fun toHSV(): HSVColor { + val r = red.toDouble() / 255 + val g = green.toDouble() / 255 + val b = blue.toDouble() / 255 + val min = min(r, min(g, b)) + val max = max(r, max(g, b)) + val delta = max - min + val s: Double + var h: Double + if (max == 0.0) { + s = 0.0 + h = 0.0 + } else { + s = delta / max + h = if (r == max) { + (g - b) / delta + } else if (g == max) { + 2 + (b - r) / delta + } else { + 4 + (r - g) / delta + } + h *= 60.0 + if (h < 0) { + h += 360.0 + } + if (java.lang.Double.isNaN(h)) { + h = 0.0 + } + } + return HSVColor(h.toInt(), (100 * s).toInt(), (100 * max).toInt()) + } + + override fun toRGBW(): RGBWColor { + val white = min(red, min(green, blue)) + return RGBWColor( + red = red - white, + green = green - white, + blue = blue - white, + white = white + ) + } + + override fun toRGBA(): RGBAColor { + val amber: Int + var r = 0 + var g = 0 + if (red > green) { + amber = green + g = 0 + r -= (amber / RGBAColor.AMBER_FACTOR).roundToInt() + } else { + amber = red + r = 0 + g -= (amber * RGBAColor.AMBER_FACTOR).roundToInt() + } + return RGBAColor( + red = r - amber, + green = g - amber, + blue = blue, + amber = amber + ) + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as RGBBaseColor<*> + + if (red != other.red) return false + if (green != other.green) return false + return blue == other.blue + } + + override fun hashCode(): Int { + var result = red + result = 31 * result + green + result = 31 * result + blue + return result + } +} diff --git a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/RGBColor.kt b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/RGBColor.kt index c44cd1d..063a9d0 100644 --- a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/RGBColor.kt +++ b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/RGBColor.kt @@ -1,156 +1,30 @@ package de.visualdigits.kotlin.klanglicht.model.color -import org.apache.commons.lang3.StringUtils -import java.lang.Long.decode -import java.lang.Long.toHexString -import kotlin.math.max +import de.visualdigits.kotlin.klanglicht.model.parameter.Parameter +import java.lang.IllegalArgumentException import kotlin.math.min import kotlin.math.roundToInt -open class RGBColor( - var red: Int = 0, - var green: Int = 0, - var blue: Int = 0 -) : Color { +class RGBColor( + red: Int = 0, + green: Int = 0, + blue: Int = 0 +) : RGBBaseColor(red, green, blue) { - constructor(value: Long) : this( - red = min(a = 255, b = (value and 0x00ff0000L shr 16).toInt()), - green = min(a = 255, b = (value and 0x0000ff00L shr 8).toInt()), - blue = min(a = 255, b = (value and 0x000000ffL).toInt()) + override fun parameterMap(): Map = mapOf( + "Red" to red, + "Green" to green, + "Blue" to blue, ) - override fun toString(): String { - return "[" + StringUtils.join(listOf(red, green, blue), ", ") + "]" - } - - open fun repr(): String { - return "RGBColor(hex='${web()}', r=$red, g=$green , b=$blue)" - } - - constructor(hex: String) : this(decode(if (hex.startsWith("#") || hex.startsWith("0x")) hex else "#$hex")) - - override fun value(): Long = red.toLong() shl 16 or (green.toLong() shl 8) or blue.toLong() - - override fun hex(): String = StringUtils.leftPad(toHexString(value()), 6, '0') - - override fun web(): String = "#${hex()}" - - override fun ansiColor(): String = "\u001B[39m\u001B[48;2;$red;$green;${blue}m \u001B[0m" - - inline fun mix(other: Color, factor: Double): T { - val thisRGB = toRGB() - val otherRGB = other.toRGB() - val rgb = RGBColor( - red = min(255, (thisRGB.red + factor * (otherRGB.red - thisRGB.red)).roundToInt()), - green = min(255, (thisRGB.green + factor * (otherRGB.green - thisRGB.green)).roundToInt()), - blue = min(255, (thisRGB.blue + factor * (otherRGB.blue - thisRGB.blue)).roundToInt()) - ) - return rgb.convert() - } - - inline fun convert(): T { - return when (T::class) { - RGBWColor::class -> toRGBW() as T - RGBAColor::class -> toRGBA() as T - HSVColor::class -> toHSV() as T - ColorParameter::class -> toColorParameter() as T - else -> toRGB() as T - } - } - - override fun toRGB(): RGBColor { - return this - } - - override fun toHSV(): HSVColor { - val r = red.toDouble() / 255 - val g = green.toDouble() / 255 - val b = blue.toDouble() / 255 - val min = min(r, min(g, b)) - val max = max(r, max(g, b)) - val delta = max - min - val s: Double - var h: Double - if (max == 0.0) { - s = 0.0 - h = 0.0 - } else { - s = delta / max - h = if (r == max) { - (g - b) / delta - } else if (g == max) { - 2 + (b - r) / delta - } else { - 4 + (r - g) / delta - } - h *= 60.0 - if (h < 0) { - h += 360.0 - } - if (java.lang.Double.isNaN(h)) { - h = 0.0 - } - } - return HSVColor(h.toInt(), (100 * s).toInt(), (100 * max).toInt()) - } - - override fun toRGBW(): RGBWColor { - val white = min(red, min(green, blue)) - return RGBWColor( - red = red - white, - green = green - white, - blue = blue - white, - white = white - ) - } - - override fun toRGBA(): RGBAColor { - val amber: Int - var r = 0 - var g = 0 - if (red > green) { - amber = green - g = 0 - r -= (amber / RGBAColor.AMBER_FACTOR).roundToInt() - } else { - amber = red - r = 0 - g -= (amber * RGBAColor.AMBER_FACTOR).roundToInt() - } - return RGBAColor( - red = r - amber, - green = g - amber, - blue = blue, - amber = amber - ) - } - - override fun toColorParameter(): ColorParameter { - val color = toRGBW() - return ColorParameter( - red = color.red, - green = color.green, - blue = color.blue, - white = color.white - ) - } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - - other as RGBColor - - if (red != other.red) return false - if (green != other.green) return false - return blue == other.blue - } - - override fun hashCode(): Int { - var result = red - result = 31 * result + green - result = 31 * result + blue - return result + override fun fade(other: Parameter<*>, factor: Double): RGBColor { + return if (other is RGBColor) { + RGBColor( + red = min(255, (red + factor * (other.red - red)).roundToInt()), + green = min(255, (green + factor * (other.green - green)).roundToInt()), + blue = min(255, (blue + factor * (other.blue - blue)).roundToInt()) + ) + } else throw IllegalArgumentException("Cannot fade different parameter type") } } diff --git a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/RGBWAColor.kt b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/RGBWAColor.kt index d2b293b..e2915d3 100644 --- a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/RGBWAColor.kt +++ b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/RGBWAColor.kt @@ -1,8 +1,11 @@ package de.visualdigits.kotlin.klanglicht.model.color +import de.visualdigits.kotlin.klanglicht.model.parameter.Parameter import org.apache.commons.lang3.StringUtils +import java.lang.IllegalArgumentException import kotlin.math.min import java.lang.Long.decode +import kotlin.math.roundToInt class RGBWAColor( red: Int = 0, @@ -10,7 +13,7 @@ class RGBWAColor( blue: Int = 0, var white: Int = 0, var amber: Int = 0 -) : RGBColor(red, green, blue) { +) : RGBBaseColor(red, green, blue) { constructor(value: Long) : this( red = min(a = 255, b = (value and 0xff00000000L shr 32).toInt()), @@ -30,9 +33,53 @@ class RGBWAColor( return "RGBColor(hex='${web()}', r=$red, g=$green , b=$blue, w=$white, a=$amber)" } + override fun parameterMap(): Map = mapOf( + "Red" to red, + "Green" to green, + "Blue" to blue, + "White" to white, + "Amber" to amber + ) + + override fun fade(other: Parameter<*>, factor: Double): RGBWAColor { + return if (other is RGBWAColor) { + RGBWAColor( + red = min(255, (red + factor * (other.red - red)).roundToInt()), + green = min(255, (green + factor * (other.green - green)).roundToInt()), + blue = min(255, (blue + factor * (other.blue - blue)).roundToInt()), + white = min(255, (white + factor * (other.white - white)).roundToInt()), + amber = min(255, (amber + factor * (other.amber - amber)).roundToInt()) + ) + } else throw IllegalArgumentException("Cannot fade different parameter type") + } + override fun value(): Long = (red.toLong() shl 32) or (green.toLong() shl 24) or (blue.toLong() shl 16) or (white.toLong() shl 8) or amber.toLong() override fun hex(): String = StringUtils.leftPad(java.lang.Long.toHexString(value()), 10, '0') override fun web(): String = "#${hex()}" + + override fun ansiColor(): String { + return toRGB().ansiColor() + } + + override fun toRGB(): RGBColor { + return RGBColor( + red = min(255, red + (amber / RGBAColor.AMBER_FACTOR).roundToInt()) + white, + green = min(255, green + (amber * RGBAColor.AMBER_FACTOR).roundToInt() + white), + blue = min(255, blue + white) + ) + } + + override fun toHSV(): HSVColor { + return toRGB().toHSV() + } + + override fun toRGBW(): RGBWColor { + return toRGB().toRGBW() + } + + override fun toRGBA(): RGBAColor { + return toRGB().toRGBA() + } } diff --git a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/RGBWColor.kt b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/RGBWColor.kt index 8f7d7de..03de114 100644 --- a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/RGBWColor.kt +++ b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/color/RGBWColor.kt @@ -1,15 +1,18 @@ package de.visualdigits.kotlin.klanglicht.model.color +import de.visualdigits.kotlin.klanglicht.model.parameter.Parameter import org.apache.commons.lang3.StringUtils +import java.lang.IllegalArgumentException import kotlin.math.min import java.lang.Long.decode +import kotlin.math.roundToInt class RGBWColor( red: Int = 0, green: Int = 0, blue: Int = 0, var white: Int = 0 -) : RGBColor(red, green, blue) { +) : RGBBaseColor(red, green, blue) { constructor(value: Long) : this( red = min(a = 255, b = (value and 0xff000000L shr 24).toInt()), @@ -18,6 +21,8 @@ class RGBWColor( white = min(a = 255, b = (value and 0x000000ffL).toInt()), ) + constructor(hex: String) : this(decode(if (hex.startsWith("#") || hex.startsWith("0x")) hex else "#$hex")) + init { if (white == 0) { white = min(red, min(green, blue)) @@ -27,8 +32,6 @@ class RGBWColor( } } - constructor(hex: String) : this(decode(if (hex.startsWith("#") || hex.startsWith("0x")) hex else "#$hex")) - override fun toString(): String { return "[" + StringUtils.join(listOf(red, green, blue, white), ", ") + "]" } @@ -37,12 +40,22 @@ class RGBWColor( return "RGBColor(hex='${web()}', r=$red, g=$green , b=$blue, w=$white)" } - override fun toRGB(): RGBColor { - return RGBColor( - red = min(255, red + white), - green = min(255, green + white), - blue = min(255, blue + white), - ) + override fun parameterMap(): Map = mapOf( + "Red" to red, + "Green" to green, + "Blue" to blue, + "White" to white + ) + + override fun fade(other: Parameter<*>, factor: Double): RGBWColor { + return if (other is RGBWColor) { + RGBWColor( + red = min(255, (red + factor * (other.red - red)).roundToInt()), + green = min(255, (green + factor * (other.green - green)).roundToInt()), + blue = min(255, (blue + factor * (other.blue - blue)).roundToInt()), + white = min(255, (white + factor * (other.white - white)).roundToInt()) + ) + } else throw IllegalArgumentException("Cannot fade different parameter type") } override fun value(): Long = (red.toLong() shl 24) or (green.toLong() shl 16) or (blue.toLong() shl 8) or white.toLong() @@ -55,6 +68,14 @@ class RGBWColor( return toRGB().ansiColor() } + override fun toRGB(): RGBColor { + return RGBColor( + red = min(255, red + white), + green = min(255, green + white), + blue = min(255, blue + white), + ) + } + override fun toHSV(): HSVColor { return toRGB().toHSV() } diff --git a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/dmx/DMXInterfaceType.kt b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/dmx/DMXInterfaceType.kt similarity index 55% rename from klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/dmx/DMXInterfaceType.kt rename to klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/dmx/DMXInterfaceType.kt index 4d43e8c..25f63d4 100644 --- a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/dmx/DMXInterfaceType.kt +++ b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/dmx/DMXInterfaceType.kt @@ -1,4 +1,4 @@ -package de.visualdigits.kotlin.klanglicht.dmx +package de.visualdigits.kotlin.klanglicht.model.dmx enum class DMXInterfaceType { diff --git a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/dmx/DmxFrame.kt b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/dmx/DmxFrame.kt similarity index 97% rename from klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/dmx/DmxFrame.kt rename to klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/dmx/DmxFrame.kt index bcbca15..18efd30 100644 --- a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/dmx/DmxFrame.kt +++ b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/dmx/DmxFrame.kt @@ -1,4 +1,4 @@ -package de.visualdigits.kotlin.klanglicht.dmx +package de.visualdigits.kotlin.klanglicht.model.dmx import com.google.common.primitives.Bytes import org.apache.commons.lang3.StringUtils diff --git a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/fixture/Fixture.kt b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/fixture/Fixture.kt index 0eb6ecc..1afbd12 100644 --- a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/fixture/Fixture.kt +++ b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/fixture/Fixture.kt @@ -1,15 +1,100 @@ package de.visualdigits.kotlin.klanglicht.model.fixture -import de.visualdigits.kotlin.klanglicht.model.color.ColorParameter +import com.fasterxml.jackson.annotation.JsonIgnoreProperties +import com.fasterxml.jackson.module.kotlin.jacksonMapperBuilder +import de.visualdigits.kotlin.klanglicht.model.parameter.IntParameter +import de.visualdigits.kotlin.klanglicht.model.parameter.Parameter +import de.visualdigits.kotlin.klanglicht.model.parameter.ParameterSet +import java.io.File +import java.nio.file.Paths +import kotlin.math.max +import kotlin.math.min +import kotlin.math.round +@JsonIgnoreProperties("channelsForCurrentMode") data class Fixture( val calibration: Calibration = Calibration(), val channels: Map> = mapOf(), - val colorPresets: Map = mapOf(), + val colorPresets: Map> = mapOf(), val manufacturer: String? = null, val model: String? = null, val parameters: Map? = null ) { - fun channelsForMode(mode: String):List? = channels[mode] + + var channelsForCurrentMode: Map = mapOf() + + companion object { + fun load(klanglichtDir: File, fixtureName: String): Fixture { + return jacksonMapperBuilder().build().readValue( + Paths.get(klanglichtDir.canonicalPath, "fixtures", "$fixtureName.json").toFile(), + Fixture::class.java + ) + } + } + + /** + * Returns the list of channels for the given mode (if any). + */ + fun channelsForMode(mode: String): List = channels[mode] ?: listOf() + + + /** + * Returns whether the fixture has a pano parameter or not. + */ + fun hasPano(): Boolean = channelsForCurrentMode.containsKey("Pan") + + /** + * Returns the maximum panning angle in degrees. + */ + fun maxPano(): Double = parameters?.get("maxPano")?.let { (it as Int).toDouble() }?:0.0 + + /** + * Returns the maximum value for the pano parameter according to the number of bytes supported within the current mode. + */ + fun maxPanoValue(): Int = if (hasPano()) if (channelsForCurrentMode.containsKey("PanFine")) 65535 else 255 else 0 + + /** + * Returns a parameter set to be used to set the pano according to the given angle + */ + fun panoParameterSet(angle: Double): ParameterSet { + val maxPano = maxPano() + val panoValue = round(maxPanoValue().toDouble() / maxPano * max(min(angle, maxPano), 0.0)).toInt() + return ParameterSet( + parameters = mutableListOf( + IntParameter("Pan", (panoValue and 0xff00) shr 8), + IntParameter("PanFine", panoValue and 0xff) + ) + ) + } + + + /** + * Returns whether the fixture has a tilt parameter or not. + */ + fun hasTilt(): Boolean = channelsForCurrentMode.containsKey("Tilt") + + /** + * Returns the maximum tilting angle in degrees. + */ + fun maxTilt(): Double = parameters?.get("maxTilt")?.let { (it as Int).toDouble() }?:0.0 + + /** + * Returns the maximum value for the tilt parameter according to the number of bytes supported within the current mode. + */ + fun maxTiltValue(): Int = if (hasTilt()) if (channelsForCurrentMode.containsKey("TiltFine")) 65535 else 255 else 0 + + /** + * Returns a parameter set to be used to set the tilt according to the given angle + */ + fun tiltParameterSet(angle: Double): ParameterSet { + val maxTilt = maxTilt() + val tiltValue = round(maxTiltValue().toDouble() / maxTilt * max(min(angle, maxTilt), 0.0)).toInt() + return ParameterSet( + parameters = mutableListOf( + IntParameter("Tilt", (tiltValue and 0xff00) shr 8), + IntParameter("TiltFine", tiltValue and 0xff) + ) + ) + } } diff --git a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/parameter/IntParameter.kt b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/parameter/IntParameter.kt new file mode 100644 index 0000000..6dc8c76 --- /dev/null +++ b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/parameter/IntParameter.kt @@ -0,0 +1,18 @@ +package de.visualdigits.kotlin.klanglicht.model.parameter + +import java.lang.IllegalArgumentException + +class IntParameter( + val name: String, + val value: Int = 0 +) : Parameter { + + override fun parameterMap(): Map = mapOf(name to value) + + override fun fade(other: Parameter<*>, factor: Double): IntParameter { + return if (other is IntParameter) { + if (name != other.name) throw IllegalArgumentException("Cannot fade different parameters") + IntParameter(name, ((value + (other.value - value) * factor).toInt())) + } else throw IllegalArgumentException("Cannot fade different parameter type") + } +} diff --git a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/parameter/Parameter.kt b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/parameter/Parameter.kt index 2a67b0d..9461e7b 100644 --- a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/parameter/Parameter.kt +++ b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/parameter/Parameter.kt @@ -1,5 +1,8 @@ package de.visualdigits.kotlin.klanglicht.model.parameter -abstract class Parameter( - val parameterMap: MutableMap = mutableMapOf() -) : MutableMap by parameterMap +interface Parameter> { + + fun parameterMap(): Map + + fun fade(other: Parameter<*>, factor: Double): T +} diff --git a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/parameter/ParameterSet.kt b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/parameter/ParameterSet.kt index 7eb33d6..c62671c 100644 --- a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/parameter/ParameterSet.kt +++ b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/parameter/ParameterSet.kt @@ -2,16 +2,40 @@ package de.visualdigits.kotlin.klanglicht.model.parameter import com.fasterxml.jackson.annotation.JsonIgnoreProperties -@JsonIgnoreProperties("parameterObjects") +@JsonIgnoreProperties("parameterValues") class ParameterSet( val baseChannel: Int = 0, - val parameters: MutableMap = mutableMapOf(), + val parameters: MutableList> = mutableListOf(), ) { - constructor( - baseChannel: Int = 0, - parameterObjects: Set = setOf() - ) : this(baseChannel, parameterObjects.fold(mutableMapOf()) { a, b -> - a.putAll(b.parameterMap) - a - }) + + val parameterMap: MutableMap = mutableMapOf() + + init { + updateParameterValues(parameters) + } + + private fun updateParameterValues(parameters: MutableList>) { + parameterMap.putAll(parameters.flatMap { param -> param.parameterMap().toList() }.toMap().toMutableMap()) + } + + + /** + * Puts all parameters from the given parameter set. + */ + fun join(other: ParameterSet): ParameterSet { + parameters.addAll(other.parameters) + updateParameterValues(other.parameters) + return this + } + + fun fade(other: ParameterSet, factor: Double): ParameterSet { + return ParameterSet( + baseChannel = baseChannel, + parameters = parameters + .zip(other.parameters) + .map { it.first.fade(it.second, factor) } + .toMutableList() + ) + } } + diff --git a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/parameter/RotationParameter.kt b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/parameter/RotationParameter.kt new file mode 100644 index 0000000..9bba529 --- /dev/null +++ b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/parameter/RotationParameter.kt @@ -0,0 +1,54 @@ +package de.visualdigits.kotlin.klanglicht.model.parameter + +import de.visualdigits.kotlin.klanglicht.model.fixture.Fixture +import java.lang.IllegalArgumentException +import kotlin.math.* + +class RotationParameter( + + /** The fixture for this rotation (needed to calculate raw values). */ + val fixture: Fixture, + + val panDegrees: Double, + + val tiltDegrees: Double +) : Parameter { + + private val DEG2RAD: Double = (Math.PI / 180.0) + + private val RAD2DEG: Double = (180.0 / Math.PI) + + override fun parameterMap(): Map = + fixture.panoParameterSet(panDegrees).parameterMap + fixture.tiltParameterSet(tiltDegrees).parameterMap + + + override fun fade(other: Parameter<*>, factor: Double): RotationParameter { + return if (other is RotationParameter) { + + // use great circle to determine intermediate steps + // adapted from page http://compastic.blogspot.co.uk/2011/07/how-to-draw-great-circle-on-map-in.html + // which was adapted from page http://maps.forum.nu/gm_flight_path.html + + val lat1: Double = tiltDegrees * DEG2RAD + val lon1: Double = panDegrees * DEG2RAD + val lat2: Double = other.tiltDegrees * DEG2RAD + val lon2: Double = other.panDegrees * DEG2RAD + + val d = 2 * asin(sqrt(sin((lat1 - lat2) / 2).pow(2.0) + cos(lat1) * cos(lat2) * sin((lon1 - lon2) / 2).pow(2.0))) + + val A = sin((1 - factor) * d) / sin(d) + val B = sin(factor * d) / sin(d) + val x = A * cos(lat1) * cos(lon1) + B * cos(lat2) * cos(lon2) + val y = A * cos(lat1) * sin(lon1) + B * cos(lat2) * sin(lon2) + val z = A * sin(lat1) + B * sin(lat2) + + val latN = atan2(z, sqrt(x.pow(2.0) + y.pow(2.0))) + val lonN = atan2(y, x) + + val panDegrees: Double = lonN * RAD2DEG + val tiltDegrees: Double = latN * RAD2DEG + + RotationParameter(fixture, panDegrees, tiltDegrees) + } else throw IllegalArgumentException("Cannot fade different parameter type") + } +} diff --git a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/parameter/Scene.kt b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/parameter/Scene.kt index d52eba4..48e157d 100644 --- a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/parameter/Scene.kt +++ b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/parameter/Scene.kt @@ -5,7 +5,7 @@ import java.io.File class Scene( val name: String, - val parameterSet: Set + val parameterSet: List ) { companion object { private val mapper = jacksonMapperBuilder().build() diff --git a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/preferences/Preferences.kt b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/preferences/Preferences.kt index ba17e02..3ae089b 100644 --- a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/preferences/Preferences.kt +++ b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/preferences/Preferences.kt @@ -1,8 +1,9 @@ package de.visualdigits.kotlin.klanglicht.model.preferences +import com.fasterxml.jackson.annotation.JsonIgnoreProperties import com.fasterxml.jackson.module.kotlin.jacksonMapperBuilder import de.visualdigits.kotlin.klanglicht.dmx.DMXInterface -import de.visualdigits.kotlin.klanglicht.dmx.DMXInterfaceType +import de.visualdigits.kotlin.klanglicht.model.dmx.DMXInterfaceType import de.visualdigits.kotlin.klanglicht.model.fixture.Channel import de.visualdigits.kotlin.klanglicht.model.fixture.Fixtures import de.visualdigits.kotlin.klanglicht.model.parameter.Scene @@ -11,6 +12,7 @@ import java.io.File import java.nio.file.Paths +@JsonIgnoreProperties("klanglichtDir") data class Preferences( val dividerPositions: List = listOf(), val dmxFrameTime: Long? = null, @@ -28,6 +30,9 @@ data class Preferences( val uiLanguage: String? = null, val yamahaReceiverUrl: String? = null ) { + + var klanglichtDir: File? = null + companion object { private val mapper = jacksonMapperBuilder().build() @@ -43,6 +48,8 @@ data class Preferences( Paths.get(klanglichtDir.canonicalPath, "preferences", preferencesFileName).toFile(), Preferences::class.java ) + preferences?.klanglichtDir = klanglichtDir + val fixtures = Fixtures.load(klanglichtDir) val stage = Stage.load(klanglichtDir, preferences?.stageSetupName!!) stage.fixtures.forEach { stageFixture -> @@ -52,7 +59,7 @@ data class Preferences( } } } - dmxInterface = DMXInterface.load(preferences?.dmxInterfaceType?:DMXInterfaceType.Dummy) + dmxInterface = DMXInterface.load(preferences?.dmxInterfaceType?: DMXInterfaceType.Dummy) dmxInterface?.open(preferences?.dmxPort!!) } return preferences!! @@ -73,7 +80,7 @@ data class Preferences( scene.parameterSet.forEach { parameterSet -> val bc = parameterSet.baseChannel val bytes = (fixtures[bc]?.map { channel -> - (parameterSet.parameters[channel.name]?:0).toByte() + (parameterSet.parameterMap[channel.name]?:0).toByte() }?:listOf()) .toByteArray() dmxInterface?.dmxFrame!!.set(bc, bytes) diff --git a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/stage/Stage.kt b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/stage/Stage.kt index 7cc4d63..be05a4e 100644 --- a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/stage/Stage.kt +++ b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/stage/Stage.kt @@ -1,20 +1,35 @@ package de.visualdigits.kotlin.klanglicht.model.stage +import com.fasterxml.jackson.annotation.JsonIgnoreProperties import com.fasterxml.jackson.module.kotlin.jacksonMapperBuilder +import de.visualdigits.kotlin.klanglicht.model.fixture.Fixture import java.io.File import java.nio.file.Paths +@JsonIgnoreProperties("fixturesResolved") data class Stage( val name: String = "", val fixtures: List = listOf() ) { + companion object { fun load(klanglichtDir: File, stageName: String): Stage { - return jacksonMapperBuilder().build().readValue( + val stage = jacksonMapperBuilder().build().readValue( Paths.get(klanglichtDir.canonicalPath, "stages", "$stageName.json").toFile(), Stage::class.java ) + + stage.fixtures.forEach { stageFixture -> + val fixtureName = "${stageFixture.manufacturer}_${stageFixture.model}" + stageFixture.fixture = Fixture.load(klanglichtDir, fixtureName) + stageFixture.fixture?.channelsForCurrentMode = + stageFixture.fixture + ?.channelsForMode(stageFixture.mode) + ?.associate { Pair(it.name!!, it) } + ?:mapOf() + } + return stage } } } diff --git a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/stage/StageFixture.kt b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/stage/StageFixture.kt index ffa8511..8b0e1bb 100644 --- a/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/stage/StageFixture.kt +++ b/klanglicht-core/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/stage/StageFixture.kt @@ -1,9 +1,13 @@ package de.visualdigits.kotlin.klanglicht.model.stage +import de.visualdigits.kotlin.klanglicht.model.fixture.Fixture + data class StageFixture( val baseChannel: Int = 0, val manufacturer: String = "", val mode: String = "", val model: String = "" -) +) { + var fixture: Fixture? = null +} diff --git a/klanglicht-core/src/test/kotlin/de/visualdigits/kotlin/klanglicht/dmx/DMXInterfaceTest.kt b/klanglicht-core/src/test/kotlin/de/visualdigits/kotlin/klanglicht/dmx/DMXInterfaceTest.kt index fb3641e..8db44b2 100644 --- a/klanglicht-core/src/test/kotlin/de/visualdigits/kotlin/klanglicht/dmx/DMXInterfaceTest.kt +++ b/klanglicht-core/src/test/kotlin/de/visualdigits/kotlin/klanglicht/dmx/DMXInterfaceTest.kt @@ -1,12 +1,13 @@ package de.visualdigits.kotlin.klanglicht.dmx -import de.visualdigits.kotlin.klanglicht.model.color.ColorParameter -import de.visualdigits.kotlin.klanglicht.model.color.NamedParameter import de.visualdigits.kotlin.klanglicht.model.color.RGBColor +import de.visualdigits.kotlin.klanglicht.model.color.RGBWColor +import de.visualdigits.kotlin.klanglicht.model.parameter.IntParameter import de.visualdigits.kotlin.klanglicht.model.parameter.ParameterSet +import de.visualdigits.kotlin.klanglicht.model.parameter.RotationParameter import de.visualdigits.kotlin.klanglicht.model.parameter.Scene import de.visualdigits.kotlin.klanglicht.model.preferences.Preferences -import kotlinx.coroutines.* +import de.visualdigits.kotlin.klanglicht.model.stage.Stage import org.junit.jupiter.api.Test import java.io.File import kotlin.math.ceil @@ -29,15 +30,13 @@ internal class DMXInterfaceTest { fun testInterfaceFromModel1() { val scene = Scene( name = "test", - parameterSet = setOf( + parameterSet = listOf( ParameterSet( baseChannel = 15, - parameters = mutableMapOf( - "MasterDimmer" to 255, - "Stroboscope" to 0, - "Red" to 255, - "Green" to 0, - "Blue" to 0 + parameters = mutableListOf( + IntParameter("MasterDimmer", 255), + IntParameter("Stroboscope", 0), + RGBColor(255, 0, 0) ) ) ) @@ -50,15 +49,13 @@ internal class DMXInterfaceTest { fun testBlackout() { val scene = Scene( name = "test", - parameterSet = setOf( + parameterSet = listOf( ParameterSet( baseChannel = 15, - parameters = mutableMapOf( - "MasterDimmer" to 0, - "Stroboscope" to 0, - "Red" to 0, - "Green" to 0, - "Blue" to 0 + parameters = mutableListOf( + IntParameter("MasterDimmer", 0), + IntParameter("Stroboscope", 0), + RGBColor() ) ) ) @@ -69,65 +66,96 @@ internal class DMXInterfaceTest { @Test fun testMovinghead() { -// val repeater = Repeater.instance(prefs) + val stage = Stage.load(prefs.klanglichtDir!!, "home-lab-movinghead") + val repeater = Repeater(prefs) repeater.start() - val color1 = RGBColor( - red = 255, - green = 0, - blue = 0 - ) - val color2 = RGBColor( - red = 0, - green = 255, - blue = 0 - ) - fade(48, color1, color2, 2000) + testReset() + + Thread.sleep(2000) + + fade(stage) repeater.join() } @Test - fun testInterfaceFromModel2() { - val color1 = RGBColor( - red = 255, - green = 0, - blue = 0 - ) - val color2 = RGBColor( - red = 0, - green = 255, - blue = 0 + fun testReset() { + val scene = Scene( + name = "test", + parameterSet = listOf( + ParameterSet( + baseChannel = 35, + parameters = mutableListOf( + IntParameter("Speed", 0), + IntParameter("Pan", 0), + IntParameter("PanFine", 0), + IntParameter("Tilt", 0), + IntParameter("TiltFine", 0), + RGBWColor() + ) + ) + ) ) - val fadeDuration = 2000 // millis + prefs.setScene(scene) + } + + @Test + fun testRotation() { + val stage = Stage.load(prefs.klanglichtDir!!, "home-lab-movinghead") + val stageFixture = stage.fixtures.first() + val fixture = stageFixture.fixture!! + + println(fixture.panoParameterSet(0.0).parameters.map { it.parameterMap().toString() }) + println(fixture.panoParameterSet(90.0).parameters.map { it.parameterMap().toString() }) + println(fixture.panoParameterSet(180.0).parameters.map { it.parameterMap().toString() }) + println(fixture.panoParameterSet(360.0).parameters.map { it.parameterMap().toString() }) + println(fixture.panoParameterSet(540.0).parameters.map { it.parameterMap().toString() }) - fade(15, color1, color2, fadeDuration) + println(fixture.tiltParameterSet(0.0).parameters.map { it.parameterMap().toString() }) + println(fixture.tiltParameterSet(90.0).parameters.map { it.parameterMap().toString() }) + println(fixture.tiltParameterSet(180.0).parameters.map { it.parameterMap().toString() }) } private fun fade( - baseChannel: Int, - color1: RGBColor, - color2: RGBColor, - fadeDuration: Int + stage: Stage, ) { + val stageFixture = stage.fixtures.first() + val baseChannel = stageFixture.baseChannel + val fixture = stageFixture.fixture!! + + val fadeDuration = 3000 + + val parameterSet1 = ParameterSet( + baseChannel = baseChannel, + parameters = mutableListOf( + RGBWColor(128, 0, 0, 0), + IntParameter("Speed", 0), + RotationParameter(fixture, 0.0, 0.0) + ) + ) + + val parameterSet2 = ParameterSet( + baseChannel = baseChannel, + parameters = mutableListOf( + RGBWColor(0, 128, 0, 0), + IntParameter("Speed", 0), + RotationParameter(fixture, 80.0, 60.0) + ) + ) + val dmxFrameTime = prefs.dmxFrameTime!! // millis val steps = ceil(fadeDuration.toDouble() / dmxFrameTime.toDouble()).toInt() val step = 1.0 / steps - for (f in 0..steps + 1) { + for (f in 0..steps) { val factor = step * f - val color = color1.mix(color2, min(1.0, factor)) + val frame = parameterSet1.fade(parameterSet2, factor) +// println(frame.parameters.map { it.parameterMap().toString() }) val scene = Scene( - name = "test", - parameterSet = setOf( - ParameterSet( - baseChannel = baseChannel, - parameterObjects = setOf( - NamedParameter("MasterDimmer", 255), - NamedParameter("Stroboscope", 0), - color - ) - ) + name = "frame_$f", + parameterSet = listOf( + frame ) ) prefs.setScene(scene) diff --git a/klanglicht-core/src/test/kotlin/de/visualdigits/kotlin/klanglicht/model/color/RGBWColorTest.kt b/klanglicht-core/src/test/kotlin/de/visualdigits/kotlin/klanglicht/model/color/RGBWColorTest.kt index aee8ab5..4700b74 100644 --- a/klanglicht-core/src/test/kotlin/de/visualdigits/kotlin/klanglicht/model/color/RGBWColorTest.kt +++ b/klanglicht-core/src/test/kotlin/de/visualdigits/kotlin/klanglicht/model/color/RGBWColorTest.kt @@ -49,7 +49,7 @@ internal class RGBWColorTest { fun mixTestTwoColors() { val color1 = RGBWColor("#ff000000") val color2 = RGBWColor("#0000ff00") - val mixed = color1.mix(color2, 0.5) + val mixed = color1.fade(color2, 0.5) assertEquals("#80008000", mixed.web()) } @@ -58,14 +58,14 @@ internal class RGBWColorTest { // tests that two colors containing white in different notations end up with white regardless of the facor val color1 = RGBWColor("#ffffff00") val color2 = RGBWColor("#000000ff") - assertEquals("#000000ff", color1.mix(color2, 0.1).web()) - assertEquals("#000000ff", color1.mix(color2, 0.2).web()) - assertEquals("#000000ff", color1.mix(color2, 0.3).web()) - assertEquals("#000000ff", color1.mix(color2, 0.4).web()) - assertEquals("#000000ff", color1.mix(color2, 0.5).web()) - assertEquals("#000000ff", color1.mix(color2, 0.6).web()) - assertEquals("#000000ff", color1.mix(color2, 0.7).web()) - assertEquals("#000000ff", color1.mix(color2, 0.8).web()) - assertEquals("#000000ff", color1.mix(color2, 0.9).web()) + assertEquals("#000000ff", color1.fade(color2, 0.1).web()) + assertEquals("#000000ff", color1.fade(color2, 0.2).web()) + assertEquals("#000000ff", color1.fade(color2, 0.3).web()) + assertEquals("#000000ff", color1.fade(color2, 0.4).web()) + assertEquals("#000000ff", color1.fade(color2, 0.5).web()) + assertEquals("#000000ff", color1.fade(color2, 0.6).web()) + assertEquals("#000000ff", color1.fade(color2, 0.7).web()) + assertEquals("#000000ff", color1.fade(color2, 0.8).web()) + assertEquals("#000000ff", color1.fade(color2, 0.9).web()) } } diff --git a/klanglicht-core/src/test/kotlin/de/visualdigits/kotlin/klanglicht/model/stage/StageTest.kt b/klanglicht-core/src/test/kotlin/de/visualdigits/kotlin/klanglicht/model/stage/StageTest.kt new file mode 100644 index 0000000..8be0484 --- /dev/null +++ b/klanglicht-core/src/test/kotlin/de/visualdigits/kotlin/klanglicht/model/stage/StageTest.kt @@ -0,0 +1,22 @@ +package de.visualdigits.kotlin.klanglicht.model.stage + +import de.visualdigits.kotlin.klanglicht.model.preferences.Preferences +import org.junit.jupiter.api.Test +import java.io.File + +class StageTest { + + private val prefs = Preferences.instance( + klanglichtDir = File(ClassLoader.getSystemResource(".klanglicht").toURI()), + preferencesFileName = System.getenv("preferencesFileName")?:"preferences.json" + ) + + @Test + fun testStage() { + val stage = Stage.load(prefs.klanglichtDir!!, "home-lab-movinghead") + stage.fixtures.forEach { stageFixture -> + val fixture = stageFixture.fixture!! + println("${stageFixture.manufacturer}_${stageFixture.model}_${stageFixture.mode} [${stageFixture.baseChannel}] hasPano: ${fixture.hasPano()} [max value ${fixture.maxPanoValue()}] hasTilt: ${fixture.hasTilt()} [max value ${fixture.maxTiltValue()}]") + } + } +} diff --git a/klanglicht-core/src/test/resources/.klanglicht/preferences/preferences.json b/klanglicht-core/src/test/resources/.klanglicht/preferences/preferences.json index 666613c..cf365ec 100644 --- a/klanglicht-core/src/test/resources/.klanglicht/preferences/preferences.json +++ b/klanglicht-core/src/test/resources/.klanglicht/preferences/preferences.json @@ -1,5 +1,5 @@ { - "dmxPort" : "COM5", + "dmxPort" : "COM8", "dmxInterfaceType" : "Dummy", "dmxFrameTime" : 40, "remoteUrl" : null, diff --git a/klanglicht-core/src/test/resources/.klanglicht/preferences/preferences_home.json b/klanglicht-core/src/test/resources/.klanglicht/preferences/preferences_home.json new file mode 100644 index 0000000..423d846 --- /dev/null +++ b/klanglicht-core/src/test/resources/.klanglicht/preferences/preferences_home.json @@ -0,0 +1,67 @@ +{ + "dmxPort" : "COM8", + "dmxInterfaceType" : "Serial", + "dmxFrameTime" : 40, + "remoteUrl" : null, + "lightmanagerUrl" : "http://192.168.178.28", + "yamahaReceiverUrl" : "http://192.168.178.21", + "stageSetupName" : "wohnzimmer_full", + "stageParameters": { + "shellyDevices": { + "Starwars": { + "model": "shelly-rgbw", + "ipAddress": "192.168.178.54", + "gain": 30 + }, + "Rgbw": { + "model": "shelly-rgbw", + "ipAddress": "192.168.178.48", + "gain": 1 + }, + "Bar": { + "model": "shelly-rgbw", + "ipAddress": "192.168.178.55", + "gain": 20 + }, + "Flur": { + "model": "shelly-1", + "ipAddress": "192.168.178.38", + "gain": 0 + }, + "Schlafzimmer": { + "model": "shelly-1", + "ipAddress": "192.168.178.40", + "gain": 0 + }, + "Wohnzimmer": { + "model": "shelly-2.5", + "ipAddress": "192.168.178.37", + "gain": 0 + }, + "Kristall": { + "model": "plug-s", + "ipAddress": "192.168.178.51", + "gain": 0 + }, + "Regal": { + "model": "shelly-plug-s", + "ipAddress": "192.168.178.39", + "gain": 0 + } + }, + "dmxDevices": { + "1": { + "gain": 0.5 + }, + "15": { + "gain": 0.5 + }, + "21": { + "gain": 1.0 + }, + "29": { + "gain": 0.5 + } + } + } +} diff --git a/klanglicht-core/src/test/resources/.klanglicht/resources/themes/StarWars/images/bg_anakin-vs-obiwan.png b/klanglicht-core/src/test/resources/.klanglicht/resources/themes/StarWars/images/bg_anakin-vs-obiwan.png new file mode 100644 index 0000000..7580f44 Binary files /dev/null and b/klanglicht-core/src/test/resources/.klanglicht/resources/themes/StarWars/images/bg_anakin-vs-obiwan.png differ diff --git a/klanglicht-core/src/test/resources/.klanglicht/resources/themes/StarWars/images/bg_darth-vader_1.jpg b/klanglicht-core/src/test/resources/.klanglicht/resources/themes/StarWars/images/bg_darth-vader_1.jpg new file mode 100644 index 0000000..ebd5315 Binary files /dev/null and b/klanglicht-core/src/test/resources/.klanglicht/resources/themes/StarWars/images/bg_darth-vader_1.jpg differ diff --git a/klanglicht-core/src/test/resources/.klanglicht/resources/themes/StarWars/images/bg_darth-vader_2.jpg b/klanglicht-core/src/test/resources/.klanglicht/resources/themes/StarWars/images/bg_darth-vader_2.jpg new file mode 100644 index 0000000..9fb91b2 Binary files /dev/null and b/klanglicht-core/src/test/resources/.klanglicht/resources/themes/StarWars/images/bg_darth-vader_2.jpg differ diff --git a/klanglicht-core/src/test/resources/.klanglicht/resources/themes/StarWars/images/bg_starwars_1.jpg b/klanglicht-core/src/test/resources/.klanglicht/resources/themes/StarWars/images/bg_starwars_1.jpg new file mode 100644 index 0000000..14a464e Binary files /dev/null and b/klanglicht-core/src/test/resources/.klanglicht/resources/themes/StarWars/images/bg_starwars_1.jpg differ diff --git a/klanglicht-core/src/test/resources/.klanglicht/resources/themes/StarWars/images/bg_stormtrooper.png b/klanglicht-core/src/test/resources/.klanglicht/resources/themes/StarWars/images/bg_stormtrooper.png new file mode 100644 index 0000000..e127ade Binary files /dev/null and b/klanglicht-core/src/test/resources/.klanglicht/resources/themes/StarWars/images/bg_stormtrooper.png differ diff --git a/klanglicht-core/src/test/resources/.klanglicht/resources/themes/StarWars/images/bg_yoda.jpg b/klanglicht-core/src/test/resources/.klanglicht/resources/themes/StarWars/images/bg_yoda.jpg new file mode 100644 index 0000000..f3a2e93 Binary files /dev/null and b/klanglicht-core/src/test/resources/.klanglicht/resources/themes/StarWars/images/bg_yoda.jpg differ diff --git a/klanglicht-core/src/test/resources/.klanglicht/resources/themes/StarWars/images/bg_yoda_crop.jpg b/klanglicht-core/src/test/resources/.klanglicht/resources/themes/StarWars/images/bg_yoda_crop.jpg new file mode 100644 index 0000000..289ca3d Binary files /dev/null and b/klanglicht-core/src/test/resources/.klanglicht/resources/themes/StarWars/images/bg_yoda_crop.jpg differ diff --git a/klanglicht-core/src/test/resources/.klanglicht/stages/home-lab-movinghead.json b/klanglicht-core/src/test/resources/.klanglicht/stages/home-lab-movinghead.json new file mode 100644 index 0000000..7931c03 --- /dev/null +++ b/klanglicht-core/src/test/resources/.klanglicht/stages/home-lab-movinghead.json @@ -0,0 +1,14 @@ +{ + "name": "home-lab-rgb-movinghead", + "fixtures": [{ + "manufacturer": "Renkforce", + "model": "Moving Head GM107", + "mode": "13-Channel Mode", + "baseChannel": 35 + }, { + "manufacturer": "Renkforce", + "model": "Moving Head GM107", + "mode": "13-Channel Mode", + "baseChannel": 48 + }] +} \ No newline at end of file diff --git a/klanglicht-core/src/test/resources/.klanglicht/stages/home-lab-rgb-movinghead.json b/klanglicht-core/src/test/resources/.klanglicht/stages/home-lab-rgb-movinghead.json new file mode 100644 index 0000000..a88c3a6 --- /dev/null +++ b/klanglicht-core/src/test/resources/.klanglicht/stages/home-lab-rgb-movinghead.json @@ -0,0 +1,29 @@ +{ + "name": "home-lab-rgb-movinghead", + "fixtures": [{ + "manufacturer": "Cameo", + "model": "Flat PAR Can RGB 10 IR", + "mode": "6-Channel Mode", + "baseChannel": 1 + }, { + "manufacturer": "Cameo", + "model": "Flat PAR Can RGB 10 IR", + "mode": "6-Channel Mode", + "baseChannel": 15 + }, { + "manufacturer": "Cameo", + "model": "Flat PAR Can RGB 10 IR", + "mode": "6-Channel Mode", + "baseChannel": 29 + }, { + "manufacturer": "Renkforce", + "model": "Moving Head GM107", + "mode": "13-Channel Mode", + "baseChannel": 35 + }, { + "manufacturer": "Renkforce", + "model": "Moving Head GM107", + "mode": "13-Channel Mode", + "baseChannel": 48 + }] +} \ No newline at end of file diff --git a/klanglicht-core/src/test/resources/.klanglicht/stages/home-lab-rgb-rgbw-movinghead.json b/klanglicht-core/src/test/resources/.klanglicht/stages/home-lab-rgb-rgbw-movinghead.json new file mode 100644 index 0000000..5ccfa90 --- /dev/null +++ b/klanglicht-core/src/test/resources/.klanglicht/stages/home-lab-rgb-rgbw-movinghead.json @@ -0,0 +1,39 @@ +{ + "name": "home-lab-rgb-rgbw-movinghead", + "fixtures": [{ + "manufacturer": "Cameo", + "model": "Flat PAR Can RGB 10 IR", + "mode": "6-Channel Mode", + "baseChannel": 1 + }, { + "manufacturer": "Cameo", + "model": "Flat PAR Can RGBW", + "mode": "8-Channel Mode", + "baseChannel": 7 + }, { + "manufacturer": "Cameo", + "model": "Flat PAR Can RGB 10 IR", + "mode": "6-Channel Mode", + "baseChannel": 15 + }, { + "manufacturer": "Cameo", + "model": "Flat PAR Can RGBW", + "mode": "8-Channel Mode", + "baseChannel": 21 + }, { + "manufacturer": "Cameo", + "model": "Flat PAR Can RGB 10 IR", + "mode": "6-Channel Mode", + "baseChannel": 29 + }, { + "manufacturer": "Renkforce", + "model": "Moving Head GM107", + "mode": "13-Channel Mode", + "baseChannel": 35 + }, { + "manufacturer": "Renkforce", + "model": "Moving Head GM107", + "mode": "13-Channel Mode", + "baseChannel": 48 + }] +} \ No newline at end of file diff --git a/klanglicht-core/src/test/resources/.klanglicht/stages/home-lab-rgb-rgbw.json b/klanglicht-core/src/test/resources/.klanglicht/stages/home-lab-rgb-rgbw.json new file mode 100644 index 0000000..8fde00b --- /dev/null +++ b/klanglicht-core/src/test/resources/.klanglicht/stages/home-lab-rgb-rgbw.json @@ -0,0 +1,29 @@ +{ + "name": "home-lab-rgb-rgbw-movinghead", + "fixtures": [{ + "manufacturer": "Cameo", + "model": "Flat PAR Can RGB 10 IR", + "mode": "6-Channel Mode", + "baseChannel": 1 + }, { + "manufacturer": "Cameo", + "model": "Flat PAR Can RGBW", + "mode": "8-Channel Mode", + "baseChannel": 7 + }, { + "manufacturer": "Cameo", + "model": "Flat PAR Can RGB 10 IR", + "mode": "6-Channel Mode", + "baseChannel": 15 + }, { + "manufacturer": "Cameo", + "model": "Flat PAR Can RGBW", + "mode": "8-Channel Mode", + "baseChannel": 21 + }, { + "manufacturer": "Cameo", + "model": "Flat PAR Can RGB 10 IR", + "mode": "6-Channel Mode", + "baseChannel": 29 + }] +} \ No newline at end of file diff --git a/klanglicht-core/src/test/resources/.klanglicht/stages/home-lab-rgb.json b/klanglicht-core/src/test/resources/.klanglicht/stages/home-lab-rgb.json new file mode 100644 index 0000000..144609a --- /dev/null +++ b/klanglicht-core/src/test/resources/.klanglicht/stages/home-lab-rgb.json @@ -0,0 +1,19 @@ +{ + "name": "home-lab-rgb", + "fixtures": [{ + "manufacturer": "Cameo", + "model": "Flat PAR Can RGB 10 IR", + "mode": "6-Channel Mode", + "baseChannel": 1 + }, { + "manufacturer": "Cameo", + "model": "Flat PAR Can RGB 10 IR", + "mode": "6-Channel Mode", + "baseChannel": 15 + }, { + "manufacturer": "Cameo", + "model": "Flat PAR Can RGB 10 IR", + "mode": "6-Channel Mode", + "baseChannel": 29 + }] +} \ No newline at end of file diff --git a/klanglicht-core/src/test/resources/.klanglicht/stages/home-lab-rgbw-movinghead.json b/klanglicht-core/src/test/resources/.klanglicht/stages/home-lab-rgbw-movinghead.json new file mode 100644 index 0000000..19f71ea --- /dev/null +++ b/klanglicht-core/src/test/resources/.klanglicht/stages/home-lab-rgbw-movinghead.json @@ -0,0 +1,24 @@ +{ + "name": "home-lab-rgbw-movinghead", + "fixtures": [{ + "manufacturer": "Cameo", + "model": "Flat PAR Can RGBW", + "mode": "8-Channel Mode", + "baseChannel": 7 + }, { + "manufacturer": "Cameo", + "model": "Flat PAR Can RGBW", + "mode": "8-Channel Mode", + "baseChannel": 21 + }, { + "manufacturer": "Renkforce", + "model": "Moving Head GM107", + "mode": "13-Channel Mode", + "baseChannel": 35 + }, { + "manufacturer": "Renkforce", + "model": "Moving Head GM107", + "mode": "13-Channel Mode", + "baseChannel": 48 + }] +} \ No newline at end of file diff --git a/klanglicht-core/src/test/resources/.klanglicht/stages/home-lab-rgbw.json b/klanglicht-core/src/test/resources/.klanglicht/stages/home-lab-rgbw.json new file mode 100644 index 0000000..cea4901 --- /dev/null +++ b/klanglicht-core/src/test/resources/.klanglicht/stages/home-lab-rgbw.json @@ -0,0 +1,14 @@ +{ + "name": "home-lab-rgbw", + "fixtures": [{ + "manufacturer": "Cameo", + "model": "Flat PAR Can RGBW", + "mode": "8-Channel Mode", + "baseChannel": 7 + }, { + "manufacturer": "Cameo", + "model": "Flat PAR Can RGBW", + "mode": "8-Channel Mode", + "baseChannel": 21 + }] +} \ No newline at end of file diff --git a/klanglicht-core/src/test/resources/.klanglicht/stages/wohnzimmer.json b/klanglicht-core/src/test/resources/.klanglicht/stages/wohnzimmer.json new file mode 100644 index 0000000..25a6604 --- /dev/null +++ b/klanglicht-core/src/test/resources/.klanglicht/stages/wohnzimmer.json @@ -0,0 +1,29 @@ +{ + "name" : "wohnzimmer", + "fixtures" : [ { + "manufacturer" : "Cameo", + "model" : "Flat PAR Can RGB 10 IR", + "mode" : "6-Channel Mode", + "baseChannel" : 1 + }, { + "manufacturer" : "Cameo", + "model" : "Flat PAR Can RGBW", + "mode" : "8-Channel Mode", + "baseChannel" : 7 + }, { + "manufacturer" : "Cameo", + "model" : "Flat PAR Can RGB 10 IR", + "mode" : "6-Channel Mode", + "baseChannel" : 15 + }, { + "manufacturer" : "Cameo", + "model" : "Flat PAR Can RGBW", + "mode" : "8-Channel Mode", + "baseChannel" : 21 + }, { + "manufacturer" : "Cameo", + "model" : "Flat PAR Can RGB 10 IR", + "mode" : "6-Channel Mode", + "baseChannel" : 29 + } ] +} diff --git a/klanglicht-core/src/test/resources/.klanglicht/stages/wohnzimmer_full.json b/klanglicht-core/src/test/resources/.klanglicht/stages/wohnzimmer_full.json new file mode 100644 index 0000000..fb5bc69 --- /dev/null +++ b/klanglicht-core/src/test/resources/.klanglicht/stages/wohnzimmer_full.json @@ -0,0 +1,39 @@ +{ + "name": "home-lab-rgb-rgbw-movinghead", + "fixtures": [{ + "manufacturer": "Renkforce", + "model": "Moving Head GM107", + "mode": "13-Channel Mode", + "baseChannel": 48 + }, { + "manufacturer": "Cameo", + "model": "Flat PAR Can RGB 10 IR", + "mode": "6-Channel Mode", + "baseChannel": 1 + }, { + "manufacturer": "Cameo", + "model": "Flat PAR Can RGBW", + "mode": "8-Channel Mode", + "baseChannel": 7 + }, { + "manufacturer": "Cameo", + "model": "Flat PAR Can RGB 10 IR", + "mode": "6-Channel Mode", + "baseChannel": 15 + }, { + "manufacturer": "Cameo", + "model": "Flat PAR Can RGBW", + "mode": "8-Channel Mode", + "baseChannel": 21 + }, { + "manufacturer": "Cameo", + "model": "Flat PAR Can RGB 10 IR", + "mode": "6-Channel Mode", + "baseChannel": 29 + }, { + "manufacturer": "Renkforce", + "model": "Moving Head GM107", + "mode": "13-Channel Mode", + "baseChannel": 35 + }] +} \ No newline at end of file diff --git a/klanglicht-yamaha/pom.xml b/klanglicht-yamaha/pom.xml new file mode 100644 index 0000000..edb3482 --- /dev/null +++ b/klanglicht-yamaha/pom.xml @@ -0,0 +1,45 @@ + + + 4.0.0 + jar + + + de.visualdigits.kotlin + klanglicht-kt + ${revision} + ../pom.xml + + + klanglicht-yamaha + ${revision} + + + 12.1 + + + + + + io.github.openfeign + feign-okhttp + ${version.feign} + + + io.github.openfeign + feign-gson + ${version.feign} + + + io.github.openfeign + feign-slf4j + ${version.feign} + + + io.github.openfeign.form + feign-form + 3.8.0 + + + diff --git a/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/feign/YamahaAvantageReceiverClient.kt b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/feign/YamahaAvantageReceiverClient.kt new file mode 100644 index 0000000..bd32eb0 --- /dev/null +++ b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/feign/YamahaAvantageReceiverClient.kt @@ -0,0 +1,80 @@ +package de.visualdigits.kotlin.klanglicht.feign + +import com.fasterxml.jackson.core.JsonProcessingException +import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper +import de.visualdigits.kotlin.klanglicht.model.yamahaavantage.deviceinfo.DeviceInfo +import de.visualdigits.kotlin.klanglicht.model.yamahaavantage.ResponseCode +import de.visualdigits.kotlin.klanglicht.model.yamahaavantage.SoundProgramList +import de.visualdigits.kotlin.klanglicht.model.yamahaavantage.features.Features +import java.net.URL +import java.nio.charset.StandardCharsets + + +class YamahaAvantageReceiverClient(val yamahaReceiverUrl: String) { + + fun deviceInfo(): DeviceInfo { + val deviceInfo = URL("$yamahaReceiverUrl/v1/system/getDeviceInfo").readText(StandardCharsets.UTF_8) + return mapper.readValue(deviceInfo, DeviceInfo::class.java) + } + + fun features(): Features { + val features = URL("$yamahaReceiverUrl/YamahaExtendedControl/v1/system/getFeatures").readText(StandardCharsets.UTF_8) + return mapper.readValue(features, Features::class.java) + } + + fun soundProgramList(): SoundProgramList { + val soundProgramList = URL("$yamahaReceiverUrl/YamahaExtendedControl/v1/main/getSoundProgramList").readText(StandardCharsets.UTF_8) + return mapper.readValue(soundProgramList, SoundProgramList::class.java) + } + + fun setVolume(volume: Int) { + URL("$yamahaReceiverUrl/YamahaExtendedControl/v1/main/setVolume?volume=$volume").readText(StandardCharsets.UTF_8) + } + + fun setSurroundProgram(program: String): ResponseCode { + println("Setting program '${mapPrograms[program]}'") + return try { + mapPrograms[program] + ?.let { URL("$yamahaReceiverUrl/YamahaExtendedControl/v1/main/setSoundProgram?program=$it").readText(StandardCharsets.UTF_8) } + ?.let { mapper.readValue(it, ResponseCode::class.java) } + ?: ResponseCode(0) + + } catch (e: JsonProcessingException) { + throw IllegalStateException("Could not read from api", e) + } + } + + companion object { + + private val mapper = jacksonObjectMapper() + + private val mapPrograms: MutableMap = HashMap() + + + init { + mapPrograms["Standard"] = "standard" + mapPrograms["Sci-Fi"] = "sci-fi" + mapPrograms["Spectacle"] = "spectacle" + mapPrograms["Adventure"] = "adventure" + mapPrograms["Drama"] = "drama"; + mapPrograms["Sports"] = "sports"; + mapPrograms["Music Video"] = "music_video"; + mapPrograms["Action Game"] = "action_game"; + mapPrograms["Roleplaying Game"] = "roleplaying_game"; + mapPrograms["Mono Movie"] = "mono_movie"; + + mapPrograms["The Roxy Theatre"] = "roxy_theatre" + mapPrograms["The Bottom Line"] = "bottom_line" + mapPrograms["Cellar Club"] = "cellar_club"; + mapPrograms["Chamber"] = "chamber"; + mapPrograms["Hall in Munich"] = "munich" + mapPrograms["Hall in Vienna"] = "vienna" + + mapPrograms["2ch Stereo"] = "all_ch_stereo" + mapPrograms["7ch Stereo"] = "all_ch_stereo" + mapPrograms["Straight"] = "straight"; + + mapPrograms["Surround Decoder"] = "surr_decoder" + } + } +} diff --git a/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/ResponseCode.kt b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/ResponseCode.kt new file mode 100644 index 0000000..f2a49e1 --- /dev/null +++ b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/ResponseCode.kt @@ -0,0 +1,9 @@ +package de.visualdigits.kotlin.klanglicht.model.yamahaavantage + +import com.fasterxml.jackson.annotation.JsonProperty + + +class ResponseCode( + @JsonProperty("response_code") val responseCode: Int = 0 +) + diff --git a/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/SoundProgramList.kt b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/SoundProgramList.kt new file mode 100644 index 0000000..f1f522f --- /dev/null +++ b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/SoundProgramList.kt @@ -0,0 +1,9 @@ +package de.visualdigits.kotlin.klanglicht.model.yamahaavantage + + +import com.fasterxml.jackson.annotation.JsonProperty + +data class SoundProgramList( + @JsonProperty("response_code") val responseCode: Int = 0, + @JsonProperty("sound_program_list") val soundProgramList: List = listOf() +) diff --git a/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/deviceinfo/AnalyticsInfo.kt b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/deviceinfo/AnalyticsInfo.kt new file mode 100644 index 0000000..975618a --- /dev/null +++ b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/deviceinfo/AnalyticsInfo.kt @@ -0,0 +1,6 @@ +package de.visualdigits.kotlin.klanglicht.model.yamahaavantage.deviceinfo + + +data class AnalyticsInfo( + val uuid: String = "" +) diff --git a/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/deviceinfo/DeviceInfo.kt b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/deviceinfo/DeviceInfo.kt new file mode 100644 index 0000000..bc0016a --- /dev/null +++ b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/deviceinfo/DeviceInfo.kt @@ -0,0 +1,24 @@ +package de.visualdigits.kotlin.klanglicht.model.yamahaavantage.deviceinfo + + +import com.fasterxml.jackson.annotation.JsonProperty + +data class DeviceInfo( + @JsonProperty("response_code") val responseCode: Int = 0, + @JsonProperty("model_name") val modelName: String = "", + val destination: String = "", + @JsonProperty("device_id") val deviceId: String = "", + @JsonProperty("system_id") val systemId: String = "", + @JsonProperty("system_version") val systemVersion: Double = 0.0, + @JsonProperty("api_version") val apiVersion: Double = 0.0, + @JsonProperty("netmodule_generation") val netmoduleGeneration: Int = 0, + @JsonProperty("netmodule_version") val netmoduleVersion: String = "", + @JsonProperty("netmodule_checksum") val netmoduleChecksum: String = "", + @JsonProperty("serial_number") val serialNumber: String = "", + @JsonProperty("category_code") val categoryCode: Int = 0, + @JsonProperty("operation_mode") val operationMode: String = "", + @JsonProperty("update_error_code") val updateErrorCode: String = "", + @JsonProperty("net_module_num") val netModuleNum: Int = 0, + @JsonProperty("update_data_type") val updateDataType: Int = 0, + @JsonProperty("analytics_info") val analyticsInfo: AnalyticsInfo = AnalyticsInfo() +) diff --git a/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Bluetooth.kt b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Bluetooth.kt new file mode 100644 index 0000000..a7d8f3c --- /dev/null +++ b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Bluetooth.kt @@ -0,0 +1,9 @@ +package de.visualdigits.kotlin.klanglicht.model.yamahaavantage.features + + +import com.fasterxml.jackson.annotation.JsonProperty + +data class Bluetooth( + @JsonProperty("update_cancelable") val updateCancelable: Boolean = false, + @JsonProperty("tx_connectivity_type_max") val txConnectivityTypeMax: Int = 0 +) diff --git a/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Ccs.kt b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Ccs.kt new file mode 100644 index 0000000..c1ddda2 --- /dev/null +++ b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Ccs.kt @@ -0,0 +1,8 @@ +package de.visualdigits.kotlin.klanglicht.model.yamahaavantage.features + + +import com.fasterxml.jackson.annotation.JsonProperty + +data class Ccs( + val supported: Boolean = false +) diff --git a/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Distribution.kt b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Distribution.kt new file mode 100644 index 0000000..2f07dc3 --- /dev/null +++ b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Distribution.kt @@ -0,0 +1,12 @@ +package de.visualdigits.kotlin.klanglicht.model.yamahaavantage.features + + +import com.fasterxml.jackson.annotation.JsonProperty + +data class Distribution( + val version: Double = 0.0, + @JsonProperty("compatible_client") val compatibleClient: List = listOf(), + @JsonProperty("client_max") val clientMax: Int = 0, + @JsonProperty("server_zone_list") val serverZoneList: List = listOf(), + @JsonProperty("mc_surround") val mcSurround: McSurround = McSurround() +) diff --git a/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Features.kt b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Features.kt new file mode 100644 index 0000000..cc115c7 --- /dev/null +++ b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Features.kt @@ -0,0 +1,14 @@ +package de.visualdigits.kotlin.klanglicht.model.yamahaavantage.features + + +import com.fasterxml.jackson.annotation.JsonProperty + +data class Features( + @JsonProperty("response_code") val responseCode: Int = 0, + val system: System = System(), + val zone: List = listOf(), + val tuner: Tuner = Tuner(), + val netusb: Netusb = Netusb(), + val distribution: Distribution = Distribution(), + val ccs: Ccs = Ccs() +) diff --git a/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Input.kt b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Input.kt new file mode 100644 index 0000000..6805501 --- /dev/null +++ b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Input.kt @@ -0,0 +1,12 @@ +package de.visualdigits.kotlin.klanglicht.model.yamahaavantage.features + + +import com.fasterxml.jackson.annotation.JsonProperty + +data class Input( + val id: String = "", + @JsonProperty("distribution_enable") val distributionEnable: Boolean = false, + @JsonProperty("rename_enable") val renameEnable: Boolean = false, + @JsonProperty("account_enable") val accountEnable: Boolean = false, + @JsonProperty("play_info_type") val playInfoType: String = "" +) diff --git a/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/MasterRole.kt b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/MasterRole.kt new file mode 100644 index 0000000..ca0d899 --- /dev/null +++ b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/MasterRole.kt @@ -0,0 +1,10 @@ +package de.visualdigits.kotlin.klanglicht.model.yamahaavantage.features + + +import com.fasterxml.jackson.annotation.JsonProperty + +data class MasterRole( + @JsonProperty("surround_pair") val surroundPair: Boolean = false, + @JsonProperty("stereo_pair") val stereoPair: Boolean = false, + @JsonProperty("subwoofer_pair") val subwooferPair: Boolean = false +) diff --git a/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/McPlaylist.kt b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/McPlaylist.kt new file mode 100644 index 0000000..2ca146c --- /dev/null +++ b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/McPlaylist.kt @@ -0,0 +1,9 @@ +package de.visualdigits.kotlin.klanglicht.model.yamahaavantage.features + + +import com.fasterxml.jackson.annotation.JsonProperty + +data class McPlaylist( + val size: Int = 0, + val num: Int = 0 +) diff --git a/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/McSurround.kt b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/McSurround.kt new file mode 100644 index 0000000..f6310a0 --- /dev/null +++ b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/McSurround.kt @@ -0,0 +1,11 @@ +package de.visualdigits.kotlin.klanglicht.model.yamahaavantage.features + + +import com.fasterxml.jackson.annotation.JsonProperty + +data class McSurround( + val version: Double = 0.0, + @JsonProperty("func_list") val funcList: List = listOf(), + @JsonProperty("master_role") val masterRole: MasterRole = MasterRole(), + @JsonProperty("slave_role") val slaveRole: SlaveRole = SlaveRole() +) diff --git a/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Netusb.kt b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Netusb.kt new file mode 100644 index 0000000..473a9d1 --- /dev/null +++ b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Netusb.kt @@ -0,0 +1,15 @@ +package de.visualdigits.kotlin.klanglicht.model.yamahaavantage.features + + +import com.fasterxml.jackson.annotation.JsonProperty + +data class Netusb( + @JsonProperty("func_list") val funcList: List = listOf(), + val preset: PresetX = PresetX(), + @JsonProperty("recent_info") val recentInfo: RecentInfo = RecentInfo(), + @JsonProperty("play_queue") val playQueue: PlayQueue = PlayQueue(), + @JsonProperty("mc_playlist") val mcPlaylist: McPlaylist = McPlaylist(), + @JsonProperty("net_radio_type") val netRadioType: String = "", + val tidal: Tidal = Tidal(), + val qobuz: Qobuz = Qobuz() +) diff --git a/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/PlayQueue.kt b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/PlayQueue.kt new file mode 100644 index 0000000..73796d9 --- /dev/null +++ b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/PlayQueue.kt @@ -0,0 +1,8 @@ +package de.visualdigits.kotlin.klanglicht.model.yamahaavantage.features + + +import com.fasterxml.jackson.annotation.JsonProperty + +data class PlayQueue( + val size: Int = 0 +) diff --git a/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Preset.kt b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Preset.kt new file mode 100644 index 0000000..2dac0f9 --- /dev/null +++ b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Preset.kt @@ -0,0 +1,9 @@ +package de.visualdigits.kotlin.klanglicht.model.yamahaavantage.features + + +import com.fasterxml.jackson.annotation.JsonProperty + +data class Preset( + val type: String = "", + val num: Int = 0 +) diff --git a/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/PresetX.kt b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/PresetX.kt new file mode 100644 index 0000000..f5b5c92 --- /dev/null +++ b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/PresetX.kt @@ -0,0 +1,8 @@ +package de.visualdigits.kotlin.klanglicht.model.yamahaavantage.features + + +import com.fasterxml.jackson.annotation.JsonProperty + +data class PresetX( + val num: Int = 0 +) diff --git a/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Qobuz.kt b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Qobuz.kt new file mode 100644 index 0000000..27f4467 --- /dev/null +++ b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Qobuz.kt @@ -0,0 +1,8 @@ +package de.visualdigits.kotlin.klanglicht.model.yamahaavantage.features + + +import com.fasterxml.jackson.annotation.JsonProperty + +data class Qobuz( + @JsonProperty("login_type") val loginType: String = "" +) diff --git a/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/RangeStep.kt b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/RangeStep.kt new file mode 100644 index 0000000..eb31e52 --- /dev/null +++ b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/RangeStep.kt @@ -0,0 +1,11 @@ +package de.visualdigits.kotlin.klanglicht.model.yamahaavantage.features + + +import com.fasterxml.jackson.annotation.JsonProperty + +data class RangeStep( + val id: String = "", + val min: Double = 0.0, + val max: Double = 0.0, + val step: Double = 0.0 +) diff --git a/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/RangeStepX.kt b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/RangeStepX.kt new file mode 100644 index 0000000..544046c --- /dev/null +++ b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/RangeStepX.kt @@ -0,0 +1,11 @@ +package de.visualdigits.kotlin.klanglicht.model.yamahaavantage.features + + +import com.fasterxml.jackson.annotation.JsonProperty + +data class RangeStepX( + val id: String = "", + val min: Int = 0, + val max: Int = 0, + val step: Int = 0 +) diff --git a/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/RecentInfo.kt b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/RecentInfo.kt new file mode 100644 index 0000000..b04a8c2 --- /dev/null +++ b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/RecentInfo.kt @@ -0,0 +1,8 @@ +package de.visualdigits.kotlin.klanglicht.model.yamahaavantage.features + + +import com.fasterxml.jackson.annotation.JsonProperty + +data class RecentInfo( + val num: Int = 0 +) diff --git a/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/SlaveRole.kt b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/SlaveRole.kt new file mode 100644 index 0000000..586ac1d --- /dev/null +++ b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/SlaveRole.kt @@ -0,0 +1,10 @@ +package de.visualdigits.kotlin.klanglicht.model.yamahaavantage.features + + +import com.fasterxml.jackson.annotation.JsonProperty + +data class SlaveRole( + @JsonProperty("surround_pair_l_or_r") val surroundPairLOrR: Boolean = false, + @JsonProperty("surround_pair_lr") val surroundPairLr: Boolean = false, + @JsonProperty("subwoofer_pair") val subwooferPair: Boolean = false +) diff --git a/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/System.kt b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/System.kt new file mode 100644 index 0000000..221a7b5 --- /dev/null +++ b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/System.kt @@ -0,0 +1,14 @@ +package de.visualdigits.kotlin.klanglicht.model.yamahaavantage.features + + +import com.fasterxml.jackson.annotation.JsonProperty + +data class System( + @JsonProperty("func_list") val funcList: List = listOf(), + @JsonProperty("zone_num") val zoneNum: Int = 0, + @JsonProperty("input_list") val inputList: List = listOf(), + val bluetooth: Bluetooth = Bluetooth(), + @JsonProperty("web_control_url") val webControlUrl: String = "", + @JsonProperty("party_volume_list") val partyVolumeList: List = listOf(), + @JsonProperty("hdmi_standby_through_list") val hdmiStandbyThroughList: List = listOf() +) diff --git a/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Tidal.kt b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Tidal.kt new file mode 100644 index 0000000..27760a0 --- /dev/null +++ b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Tidal.kt @@ -0,0 +1,8 @@ +package de.visualdigits.kotlin.klanglicht.model.yamahaavantage.features + + +import com.fasterxml.jackson.annotation.JsonProperty + +data class Tidal( + val mode: String = "" +) diff --git a/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Tuner.kt b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Tuner.kt new file mode 100644 index 0000000..5aa28d7 --- /dev/null +++ b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Tuner.kt @@ -0,0 +1,10 @@ +package de.visualdigits.kotlin.klanglicht.model.yamahaavantage.features + + +import com.fasterxml.jackson.annotation.JsonProperty + +data class Tuner( + @JsonProperty("func_list") val funcList: List = listOf(), + @JsonProperty("range_step") val rangeStep: List = listOf(), + val preset: Preset = Preset() +) diff --git a/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Zone.kt b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Zone.kt new file mode 100644 index 0000000..fd5ee71 --- /dev/null +++ b/klanglicht-yamaha/src/main/kotlin/de/visualdigits/kotlin/klanglicht/model/yamahaavantage/features/Zone.kt @@ -0,0 +1,22 @@ +package de.visualdigits.kotlin.klanglicht.model.yamahaavantage.features + + +import com.fasterxml.jackson.annotation.JsonProperty + +data class Zone( + val id: String = "", + @JsonProperty("func_list") val funcList: List = listOf(), + @JsonProperty("input_list") val inputList: List = listOf(), + @JsonProperty("sound_program_list") val soundProgramList: List? = listOf(), + @JsonProperty("surr_decoder_type_list") val surrDecoderTypeList: List? = listOf(), + @JsonProperty("tone_control_mode_list") val toneControlModeList: List = listOf(), + @JsonProperty("link_control_list") val linkControlList: List = listOf(), + @JsonProperty("link_audio_delay_list") val linkAudioDelayList: List? = listOf(), + @JsonProperty("range_step") val rangeStep: List = listOf(), + @JsonProperty("scene_num") val sceneNum: Int = 0, + @JsonProperty("cursor_list") val cursorList: List? = listOf(), + @JsonProperty("menu_list") val menuList: List? = listOf(), + @JsonProperty("actual_volume_mode_list") val actualVolumeModeList: List = listOf(), + @JsonProperty("ccs_supported") val ccsSupported: List? = listOf(), + @JsonProperty("zone_b") val zoneB: Boolean? = false +) diff --git a/klanglicht-yamaha/src/test/kotlin/de/visualdigits/kotlin/klanglicht/feign/YamahaAvantageReceiverClientTest.kt b/klanglicht-yamaha/src/test/kotlin/de/visualdigits/kotlin/klanglicht/feign/YamahaAvantageReceiverClientTest.kt new file mode 100644 index 0000000..d62579a --- /dev/null +++ b/klanglicht-yamaha/src/test/kotlin/de/visualdigits/kotlin/klanglicht/feign/YamahaAvantageReceiverClientTest.kt @@ -0,0 +1,37 @@ +package de.visualdigits.kotlin.klanglicht.feign + +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test + +internal class YamahaAvantageReceiverClientTest { + + private val URL = "http://192.168.178.46" + + @Test + fun testSet() { + val client = YamahaAvantageReceiverClient(URL) + val responseCode = client.setSurroundProgram("Sci-Fi") + assertEquals(0, responseCode.responseCode) + } + + @Test + fun testInfo() { + val client = YamahaAvantageReceiverClient(URL) + val deviceInfo = client.deviceInfo() + println(deviceInfo) + } + + @Test + fun testFeatures() { + val client = YamahaAvantageReceiverClient(URL) + val features = client.features() + println(features) + } + + @Test + fun testSoundProgramList() { + val client = YamahaAvantageReceiverClient(URL) + val soundProgramList = client.soundProgramList() + println(soundProgramList) + } +} diff --git a/pom.xml b/pom.xml index 1d09166..a1774fd 100644 --- a/pom.xml +++ b/pom.xml @@ -14,6 +14,7 @@ klanglicht-core klanglicht-rest + klanglicht-yamaha @@ -56,6 +57,55 @@ 1.5.0 + + + org.apache.commons + commons-lang3 + 3.12.0 + + + commons-codec + commons-codec + 1.15 + + + com.google.guava + guava + 31.1-jre + + + + + com.fasterxml.jackson.core + jackson-core + ${version.jackson} + + + com.fasterxml.jackson.core + jackson-annotations + ${version.jackson} + + + com.fasterxml.jackson.core + jackson-databind + ${version.jackson} + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + ${version.jackson} + + + com.fasterxml.jackson.module + jackson-module-kotlin + ${version.jackson} + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${version.jackson} + + org.slf4j