; ; KolibriOS system mixer. Version 0.2 ; ; Author: Asper ; Date of issue: 15.08.2010 ; Compiler: FASM ; Target: KolibriOS ; use32 org 0x0 db 'MENUET01' ; 8 byte id dd 38 ; required os dd STARTAPP ; program start dd I_END ; program image size dd I_MEM ; required amount of memory dd I_MEM ; stack heap dd 0x0, 0x0 include 'aspapi.INC' include '../../macros.inc' ;include 'string.inc' ;include 'debug.inc' DEBUG equ 0 ;1 SRV_GETVERSION equ 0 DEV_PLAY equ 1 DEV_STOP equ 2 DEV_CALLBACK equ 3 DEV_SET_BUFF equ 4 DEV_NOTIFY equ 5 DEV_SET_MASTERVOL equ 6 DEV_GET_MASTERVOL equ 7 DEV_GET_INFO equ 8 ;C_UNKNOWN equ ? C_BLACK equ 0x000000 C_GREY equ 0xB0B0B0 ; 0xC0C0C0 C_BLUE equ 0x1070D0 C_GREEN equ 0x70D010 C_RED equ 0xD01010 C_ORANGE equ 0xD07010 C_YELLOW equ 0xE0E010 C_PURPLE equ 0x7010D0 C_PINK equ 0xFF00FF ;C_RESERVED equ ? C_WHITE equ 0xFFFFFF ;C_OTHER equ ? C_KEYCOLOR1 equ 0x0050D250 ; Control button color 1 C_KEYCOLOR2 equ 0x00CBE1E1 ; Control button color 2 C_TEXTCOLOR equ 0x80000000 ; Button caption color BUT_W equ 20 BUT_H equ 20 ;WIN_X equ 30000 ; I hope nobody has screen ;WIN_Y equ 30000 ; with such a big resolution :) WIN_W equ 250;390 WIN_H equ 180 WIN_COLOR equ 0x505050 ;0x0099BB WIN_X_CENTER equ WIN_W/2 FIRST_CTRL_BUTTON_ID equ 7 MAX_CONTROLS_NUM equ 15 ; Bad bounding :/ struc CONTROL { .level dw ? .num_steps dw ? } ; widget node for parsing ;struc HDA_GNODE ;{ ; .nid dw ? ;NID of this widget ; .nconns dw ? ;number of input connections ; .conn_list dd ? ; .slist dw ? ;temporay list ; dw ? ; ; .wid_caps dd ? ;widget capabilities ; .type db ? ;widget type ; .pin_ctl db ? ;pin controls ; .checked db ? ;the flag indicates that the node is already parsed ; .pin_caps dd ? ;pin widget capabilities ; .def_cfg dd ? ;default configuration ; .amp_out_caps dd ? ;AMP out capabilities ; .amp_in_caps dd ? ;AMP in capabilities ; .next dd ? ; struct list_head list ; .sizeof: ;} ;virtual at 0 ; HDA_GNODE HDA_GNODE ;end virtual STARTAPP: ; Initialize memory ; mcall 68, 11 ; or eax,eax ; jz close_app ; Load sound system driver mov eax, 68 mov ebx, 16 mov ecx, drivername int 0x40 mov [hDriver], eax test eax, eax jnz @f loaderr: if DEBUG print "Can't load driver" end if jmp close_app @@: mov [is_hda], 1 call GetDriverVer mov eax, [driver_ver] cmp ax, 0x11DA je @f mov [is_hda], 0 @@: cmp [is_hda], 0 je .init_ac97_controls ; Init volume controls stdcall GetMasterVol, 0 mov ebx, eax mov [LVolume.level], ax shr eax, 16 mov [LVolume.num_steps], ax stdcall GetMasterVol, 1 mov [RVolume.level], ax shr eax, 16 mov [RVolume.num_steps], ax jmp .controls_init_complete ; Asper: temporary workaround on ac97 codecs [ .init_ac97_controls: ;jmp @f mov [is_hda], 0 mov [LVolume.num_steps], 31 mov [RVolume.num_steps], 31 mov ax, [LVolume.level] call convert_ac97_volume_to_level mov [LVolume.level], ax mov [RVolume.level], ax ; Asper: temporary workaround on ac97 codecs ] .controls_init_complete: if DEBUG print "Left level" movzx eax, [LVolume.level] dph eax newline print "Left num_steps" movzx eax, [LVolume.num_steps] dph eax newline print "Right level" movzx eax, [RVolume.level] dph eax newline print "Right num_steps" movzx eax, [RVolume.num_steps] dph eax newline end if mcall 66, 1, 1 ; Set keyboard mode to get scancodes. mcall 37,0 mov cx,ax shl ecx,16 mov cx,WIN_H mov ebx,eax mov bx,WIN_W red: call draw_window still: mcall 10 ; Wait for an event in the queue. cmp al,1 ; redraw request ? jz red cmp al,2 ; key in buffer ? jz key cmp al,3 ; button in buffer ? jz button jmp still key: mcall 2 cmp ah, 1 ;Esc je close_app ; cmp ah, 5 ; '4' ; jne @f ; stdcall GetMasterVol, 0 ; jmp still ; @@: ; ; cmp ah, 6 ; '5' ; jne @f ; stdcall GetMasterVol, 1 ; jmp still ; @@: ; cmp ah, 8 ; '7' ; jne @f ; call GetDriverVer ; jmp still ; @@: ;Left channel Up cmp ah, 71 ; 'Home' jne @f movzx eax, [LVolume.level] inc ax cmp ax, [LVolume.num_steps] jg still mov [LVolume.level], ax call convert_level_to_ac97_volume ;Asper: temporary workaround on ac97 stdcall SetMasterVol, 0, eax jmp red @@: ;Left channel Down cmp ah, 79 ; 'End' jne @f movzx eax, [LVolume.level] dec ax cmp ax, 0 jl still mov [LVolume.level], ax call convert_level_to_ac97_volume ;Asper: temporary workaround on ac97 stdcall SetMasterVol, 0, eax jmp red @@: ;Right channel Up cmp ah, 73 ; 'PageUp' jne @f movzx eax, [RVolume.level] inc ax cmp ax, [RVolume.num_steps] jg still mov [RVolume.level], ax call convert_level_to_ac97_volume ;Asper: temporary workaround on ac97 movzx edx, [is_hda] stdcall SetMasterVol, edx, eax jmp red @@: ;Right channel Down cmp ah, 81 ; 'PageDown' jne @f movzx eax, [RVolume.level] dec ax cmp ax, 0 jl still mov [RVolume.level], ax call convert_level_to_ac97_volume ;Asper: temporary workaround on ac97 .RVdown: movzx edx, [is_hda] stdcall SetMasterVol, edx, eax jmp red @@: jmp still button: mcall 17 ; Get pressed button code cmp ah, 1 ; Test x button je close_app jmp still draw_window: ;start_draw_window WIN_X,WIN_Y,WIN_W,WIN_H,WIN_COLOR,caption;, 12;labellen-labelt mcall 0,,,34000000h+WIN_COLOR,,caption stdcall draw_button, WIN_X_CENTER-BUT_W-55, 30+BUT_H*0,BUT_W,BUT_H,2,C_PINK,aNoText,0,0 stdcall draw_button, WIN_X_CENTER-BUT_W-55, 30+BUT_H*1+10,BUT_W,BUT_H,3,C_GREEN,aNoText,0,0 stdcall draw_button, WIN_X_CENTER-BUT_W-55, 30+BUT_H*2+20,BUT_W,BUT_H,4,C_BLUE,aNoText,0,0 stdcall draw_button, WIN_X_CENTER-BUT_W/2+55, 30+BUT_H*0,BUT_W,BUT_H,5,C_GREY,aNoText,0,0 stdcall draw_button, WIN_X_CENTER-BUT_W/2+55, 30+BUT_H*1+10,BUT_W,BUT_H,6,C_BLACK,aNoText,0,0 stdcall draw_button, WIN_X_CENTER-BUT_W/2+55, 30+BUT_H*2+20,BUT_W,BUT_H,7,C_ORANGE,aNoText,0,0 movzx eax, [LVolume.level] movzx edx, [LVolume.num_steps] stdcall draw_volume_control, WIN_X_CENTER-BUT_W-25, 20, 110, aLVolume, C_BLACK, eax, edx movzx eax, [RVolume.level] movzx edx, [RVolume.num_steps] stdcall draw_volume_control, WIN_X_CENTER+25, 20, 110, aRVolume, C_BLACK, eax, edx stdcall rectangle, WIN_X_CENTER-BUT_W-56, 29+BUT_H*0, BUT_W+2, BUT_H+2, C_BLACK stdcall rectangle, WIN_X_CENTER-BUT_W-56, 29+BUT_H*1+10, BUT_W+2, BUT_H+2, C_BLACK stdcall rectangle, WIN_X_CENTER-BUT_W-56, 29+BUT_H*2+20, BUT_W+2, BUT_H+2, C_BLACK stdcall rectangle, WIN_X_CENTER-BUT_W/2+54, 29+BUT_H*0, BUT_W+2, BUT_H+2, C_BLACK stdcall rectangle, WIN_X_CENTER-BUT_W/2+54, 29+BUT_H*1+10, BUT_W+2, BUT_H+2, C_GREEN stdcall rectangle, WIN_X_CENTER-BUT_W/2+54, 29+BUT_H*2+20, BUT_W+2, BUT_H+2, C_BLACK stdcall rectangle, WIN_X_CENTER-BUT_W-57, 28+BUT_H*0, BUT_W+4, BUT_H+4, C_PINK stdcall rectangle, WIN_X_CENTER-BUT_W-57, 28+BUT_H*1+10, BUT_W+4, BUT_H+4, C_GREEN stdcall rectangle, WIN_X_CENTER-BUT_W-57, 28+BUT_H*2+20, BUT_W+4, BUT_H+4, C_BLUE stdcall rectangle, WIN_X_CENTER-BUT_W/2+53, 28+BUT_H*0, BUT_W+4, BUT_H+4, C_GREY stdcall rectangle, WIN_X_CENTER-BUT_W/2+53, 28+BUT_H*1+10, BUT_W+4, BUT_H+4, C_BLACK; stdcall rectangle, WIN_X_CENTER-BUT_W/2+53, 28+BUT_H*2+20, BUT_W+4, BUT_H+4, C_ORANGE end_draw_window ret proc draw_volume_control stdcall, x:dword, y:dword, ysize:dword, name:dword, textcolor:dword, step:dword, max_steps:dword mov ebx, [x] mov edx, [y] mov eax, [ysize] stdcall bar, ebx, edx, 10, eax, C_GREEN mov ecx, [max_steps] cmp ecx, [step] je .l2 push eax edx mov cl, byte [max_steps] test cl, cl jnz @f mov ecx, [ysize] jmp .l1 @@: div cl mov cl, byte [step] mul cl mov ecx, [ysize] sub ecx, eax .l1: pop edx eax stdcall bar, ebx, edx, 10, ecx, C_RED .l2: dec ebx dec edx inc eax stdcall rectangle, ebx, edx, 11, eax, C_BLACK add edx, eax add edx, 10 sub ebx, 8 stdcall outtextxy, ebx, edx, [name], 0, C_GREEN or 0x80000000 ret endp ;____________________________________ GetDriverVer: push ebx ecx mov [ioctl_code], SRV_GETVERSION and [inp_size], 0 mov [outp_size], 4 mov [output], driver_ver mcall 68,17,ioctl test eax, eax jnz loaderr if DEBUG push eax dps "1.) Driver version = " dph [driver_ver] newline pop eax end if pop ecx ebx ret ;____________________________________ Stop: and [ioctl_code], DEV_STOP and [inp_size], 4 mov [input], 0 ;? stream mov [outp_size], 0 mov [output], 0 mcall 68,17,ioctl test eax, eax jnz loaderr if DEBUG print "Stop device" end if ret ;____________________________________ proc GetMasterVol stdcall, channel:dword push ebx ecx mov [ioctl_code], DEV_GET_MASTERVOL mov [inp_size], 1 mov eax, [channel] mov [input], eax mov [outp_size], 4 mov [output], master_vol mcall 68,17,ioctl if DEBUG push eax dps "Get Master volume = " dph [master_vol] newline pop eax end if mov eax, [master_vol] pop ecx ebx ret endp ;____________________________________ proc SetMasterVol stdcall, channel:dword, val:dword push ebx ecx mov [ioctl_code], DEV_SET_MASTERVOL mov [inp_size], 4 mov eax, [channel] shl eax, 24 or eax, [val] mov [master_vol], eax mov [input], master_vol mov [outp_size], 0 mcall 68,17,ioctl if DEBUG push eax dps "Set Master volume = " dph [val] dps " ch = " dph [channel] newline pop eax end if pop ecx ebx ret endp ;____________________________________ ;GetDevInfo: ; Get pins configurations or controls ; mov [ioctl_code], DEV_GET_INFO ; and [inp_size], 0 ; mov [outp_size], 9*4 ; mov [output], ctrl_info ; mcall 68,17,ioctl ; if DEBUG ; push eax ; print "CTRL_INFO" ; dps ".pci_cmd = " ; dph [ctrl_info] ; newline ; dps ".irq = " ; dph [ctrl_info+4] ; newline ; ;dps ".glob_cntrl = " ; dps ".VIA_REG_OFFSET_CONTROL = " ; dph [ctrl_info+8] ; newline ; ;dps ".glob_sta = " ; dps ".VIA_REG_OFFSET_STATUS = " ; dph [ctrl_info+12] ; newline ; ;dps ".codec_io_base = " ; dps ".VIA_REG_OFFSET_TABLE_PTR = " ; dph [ctrl_info+16] ; newline ; dps ".ctrl_io_base = " ; dph [ctrl_info+20] ; newline ; ;dps ".codec_mem_base = " ; dps ".VIA_REG_OFFSET_STOP_IDX = " ; dph [ctrl_info+24] ; newline ; ;dps ".ctrl_mem_base = " ; dps ".VIA_REG_OFFSET_CURR_COUNT = " ; dph [ctrl_info+28] ; newline ; dps ".codec_id = " ; dph [ctrl_info+32] ; newline ; pop eax ; end if ;ret convert_level_to_ac97_volume: push ebx ecx edx cmp [is_hda], 0 jne .not_ac97 mov [LVolume.level], ax mov [RVolume.level], ax mov bx, ax mov ax, [LVolume.num_steps] sub ax, bx mov cx, 150 mul cx neg eax .not_ac97: pop edx ecx ebx ret convert_ac97_volume_to_level: push ebx ecx edx cmp [is_hda], 0 jne .not_ac97 neg eax mov cx, 150 div cx mov bx, ax mov ax, [LVolume.num_steps] sub ax, bx .not_ac97: pop edx ecx ebx ret close_app: or eax, -1 int 0x40 ;____________________________________ caption db 'Sound Mixer',0 drivername db 'SOUND',0 ;aRamdisk db '/rd/1/',0 ;aStartDriver db 'Start driver',0 ;aStop db 'Stop',0 ;aGetMVol db 'Get Master Volume',0 ;aSetMVol db 'Set Master Volume',0 ;aGetDevInfo db 'Get device info',0 aNoText db 0 aLVolume db 'Left',0 aRVolume db 'Right',0 ; Jack types ;aLineOut db 'Line Out',0 ;aSpeaker db 'Speaker',0 ;aHPOut db 'HP Out',0 ;aSideSpk db '',0 ;aCD db 'CD',0 ;aSPDIFOut db 'SPDIF Out',0 ;aDigitalOut db 'Digital Out',0 ;aModemLine db 'Modem Line',0 ;aModemHand db 'Modem Hand',0 ;aLineIn db 'Line In',0 ;aAUX db 'AUX',0 ;aMic db 'Mic',0 ;aTelephony db 'Telephony',0 ;aSPDIFIn db 'SPDIF In',0 ;aDigitalIn db 'Digital In',0 ;aReserved db 'Reserved',0 ;aOther db 'Other',0 ;Jack locations ;base ;aNA db 'N/A',0 ;aRear db 'Rear',0 ;aFront db 'Front',0 ;aLeft db 'Left',0 ;aRight db 'Right',0 ;aTop db 'Top',0 ;aBottom db 'Bottom',0 ;special ;aRearPanel db 'Rear Panel',0 ;aDriveBar db 'Drive Bar',0 ;aRiser db 'Riser',0 ;aHDMI db 'HDMI',0 ;aATAPI db 'ATAPI',0 ;aMobileIn db 'Mobile-In',0 ;aMobileOut db 'Mobile-Out',0 I_END: align 4 ioctl: hDriver rd 1 ioctl_code rd 1 input rd 1 inp_size rd 1 output rd 1 outp_size rd 1 driver_ver rd 1 master_vol rd 1 ;ctrl_info rd 9 is_hda rb 1 LVolume CONTROL RVolume CONTROL align 4 rb 2048 ; stack I_MEM: