Oscillo 3.0 : (mise à jour majeure)
-Correction d'un bug au niveau du verrouillage du mutex pour le canvas. Sous XP, un changement du Wave au Spectre provoque un freeze du canvas, et revenir au Wave freeze l'application. Pourtant tout reste fonctionnel. Je vais chercher le probléme mais je suis un peu paumé sur ce point, puisque sous W10, le même code marche trés bien.
-Ajout d'un mode plein écran. Quand on maximise la fenêtre, l'analyseur de spectre prend alors tout l'écran, et le fond devient transparent, laissant voir le bureau. L'interface devient légérement translucide (un zoli effet "glassy" comme je les aime ) . Il reste possible d'interagir tout a fait normalement avec le bureau en arriére plan au travers de l'Oscillo. En cliquant sur une partie de l'interface (spectre, titre ou barrre de lecture), on revient au mode normal. Ce mode consomme un peu (ou beaucoup) de proco du fait de la transparence.
-Mise en place d'un curseur personnalisé sur l'Oscilloscope. Il reste dans l'esprit rétro "old terminal" de l'application. Le nouveau curseur sera dans le zip de la nouvelle version dés que je l'aurais mis sur mon site. (nb : ce curseur provient de BF3, ce n'est pas une réalisation personnelle,je suis un trop mauvais graphiste pour ca... )
Reporté a la 3.1.
Lien vers la page associée de mon site pour tous les détails.
Lien de téléchargement direct si vous êtes pressé
Edit : le code pour que vous puissiez tester le mode plein écran en attendant que je mette a jour le zip sur mon site ( fait) :
Code : Tout sélectionner
;##### Partie réservée à ceux qui ne disposent pas de la version compléte de PB (c'est a dire moi...), les autres, mettez en commentaire.#####
;#####################################################################################################################
#GWL_EXSTYLE = -20
#GWL_STYLE = -16
#WS_EX_LAYERED = 524288
#LWA_ALPHA = 2
#LWA_COLORKEY = 1
Prototype.i Proto_SetWindowLong_(hWnd,nIndex.i, NewLong.l)
Prototype.b Proto_SetLayeredWindowAttributes_(hWnd,ColorKey,Alpha.b,Flags.w)
Prototype.l Proto_LoadCursorFromFile_(*lpFileName)
If OpenLibrary(1,"user32.dll")
Global SetWindowLong_.Proto_SetWindowLong_ = GetFunction(1,"SetWindowLongW") ;on charge la fonction
Global SetLayeredWindowAttributes_.Proto_SetLayeredWindowAttributes_ = GetFunction(1,"SetLayeredWindowAttributes")
Global LoadCursorFromFile_.Proto_LoadCursorFromFile_ = GetFunction(1,"LoadCursorFromFileW")
Else
MessageRequester("Erreur","Erreur d'accés a user32.dll.",16)
EndIf
;#####################################################################################################################
;#####################################################################################################################
;#### Oscilloscope - Lecteur de musique rétro #####
;#### par JohnJohnsonSHERMAN #####
;#### Purebasic v5.42 LTS - Droopy Lib - Fmod Juillet 2016 #####
;#####################################################################################################################
IncludeFile "fmodex(short).pbi"
Enumeration
#Mainform
#Frame3D_0
#File
#OpenFile
#Play
#Pause
#Stop
#Volume
#Spectrum
#Wave
#Switch
#FontOldComputer
#Progress
#Infos
#Info
#CurrentVol
#Filtres
#BigScreenWnd
#BSW_Canvas
#BSW_close
#BigFontOldComputer
#Pinned
#Unpinned
EndEnumeration
Define.l Event, GEvent, TiEvent
Define y,state,hThreadSpectrum,hThreadWave,i,MouseX,MouseY
Global WindowStyle.i=#PB_Window_SystemMenu|#PB_Window_ScreenCentered
Global fmodsystem.i, Channel.i, Sound.i, Volume.f = 0.5, PauseStatus.b,Analyse,Mutex,Length.i,Name.s,CurrentPos.i
Global File.s,thBSWContinue,PinState
Analyse = 0 ;O= Wave (amplitude), 1= Spectre (fréquences)
Name = "No music loaded"
UsePNGImageDecoder()
LoadImage(0,GetCurrentDirectory()+"OscilloToSpectrum.png")
LoadImage(1,GetCurrentDirectory()+"OscilloToWave.png")
LoadImage(2,GetCurrentDirectory()+"OscilloInTransition.png")
;LoadImage(3,GetCurrentDirectory()+"filtres.png")
LoadImage(#Pinned,GetCurrentDirectory()+"OscilloPinScreen.png")
LoadImage(#Unpinned, GetCurrentDirectory()+"OscilloUnpinScreen.png")
ResizeImage(#Pinned,47,47)
ResizeImage(#Unpinned,47,47)
LoadFont(#FontOldComputer,"Fixedsys",16)
LoadFont(#BigFontOldComputer,"Fixedsys",24)
For i =0 To 2
ResizeImage(i,60,50)
Next
Declare BSW_DrawSpectrum(param)
Procedure ShowSpectrum(param)
Repeat
Protected Dim SpectrumArray.f(1024), i.i, j.i, Max, Position.i,Yspect,YlowSpec
FMOD_Channel_GetSpectrum(Channel, SpectrumArray(), 1024, 0, #FMOD_DSP_FFT_WINDOW_BLACKMANHARRIS)
LockMutex(Mutex)
If Analyse=0
UnlockMutex(Mutex)
While Analyse = 0
Delay(100)
Wend
EndIf
StartDrawing(CanvasOutput(#Wave))
DrawingFont(FontID(#FontOldComputer))
;Clear de l'histogramme
Box(0, 0, 1024, 500, RGB(0,30,0))
;Nom de la musique sur l'oscillo et progressbar
DrawText(2,2,Name,RGB(0,170,0),RGB(0,30,0))
Box(5,475,1014,20,RGB(30,85,15))
Box(6,476,1012,18,RGB(40,200,60))
Box(7,477,1010,16,RGB(0,30,0))
If Length <> 0
Box(7,477,Int((CurrentPos/Length)*1010),16,RGB(50,200,30))
LineXY(Int((CurrentPos/Length)*1010)+7,477,Int((CurrentPos/Length)*1010)+7,492,RGB(30,85,15))
EndIf
;Cadre autour de l'histogramme
DrawingMode(#PB_2DDrawing_Outlined)
Box(0, 0, 1024, 500, RGB(0, 200, 0))
;Dessin des points
DrawingMode(#PB_2DDrawing_Default)
For i=1 To 1024 Step 2
YlowSpec=(SpectrumArray(i)*1000)
;YlowSpec=(10*Log((SpectrumArray(i)/Pow(10,-12)))*1)
Yspect=250-YlowSpec
LineXY(i+1,250,i+1,YlowSpec+250,RGB(0,150,20))
LineXY(i+1,Yspect,i+1,251,RGB(0,200,50))
If Yspect < 99 And Yspect > 1
; Plot(i+1,Yspect,RGB(0,90,0))
EndIf
Next
StopDrawing()
Delay(25)
UnlockMutex(Mutex)
ForEver
EndProcedure
Procedure ShowWaveAmp(param)
Repeat
Protected Dim WaveArray.f(1024), i.i, j.i, Max, Position.i,YCurrentWave,YOldWave
FMOD_Channel_GetWaveData(Channel, WaveArray(), 1024, 0)
LockMutex(Mutex)
If Analyse=1
UnlockMutex(Mutex)
While Analyse = 1
Delay(100)
Wend
EndIf
StartDrawing(CanvasOutput(#Wave))
DrawingFont(FontID(#FontOldComputer))
;Clear de l'histogramme
Box(0, 0, 1024, 500, RGB(0,30,0))
;Nom de la musique sur l'oscillo et progressbar
DrawText(2,2,Name,RGB(0,170,0),RGB(0,30,0))
Box(5,475,1014,20,RGB(30,85,35))
Box(6,476,1012,18,RGB(40,200,60))
Box(7,477,1010,16,RGB(0,30,0))
If Length <> 0
Box(7,477,Int((CurrentPos/Length)*1010),16,RGB(50,200,30))
LineXY(Int((CurrentPos/Length)*1010)+7,477,Int((CurrentPos/Length)*1010)+7,492,RGB(30,85,15))
EndIf
;Cadre autour de l'histogramme
DrawingMode(#PB_2DDrawing_Outlined)
Box(0, 0, 1024, 500, RGB(0, 200, 0))
;Dessin des points
DrawingMode(#PB_2DDrawing_Default)
For i=1 To 1024
YOldWave=(WaveArray(i-1)+1)*250
YCurrentWave=(WaveArray(i)+1)*250
LineXY(i-1,YOldWave,i,YCurrentWave,RGB(0,200,50))
LineXY(i-1,YOldWave+1,i,YCurrentWave+1,RGB(0,90,50))
LineXY(i-1,YOldWave-1,i,YCurrentWave-1,RGB(0,110,50))
Next
StopDrawing()
Delay(25)
UnlockMutex(Mutex)
ForEver
EndProcedure
Procedure ShowLevels(param)
Repeat
Protected Dim Spectrum.f(1024),Dim WaveArray.f(1024),MedFreq.f,MedVol.f,i
FMOD_Channel_GetWaveData(Channel,WaveArray(),1024,0)
;FMOD_Channel_GetSpectrum(Channel,Spectrum(),1024,0,#FMOD_DSP_FFT_WINDOW_BLACKMANHARRIS)
MedVol=0
MedFreq=0
For i=1 To 1024
;MedFreq=MedFreq+Spectrum(i)
MedVol=MedVol+Abs(WaveArray(i))
Next
MedVol=(MedVol/1024)*200
;MedFreq=MedFreq/1024
;UseGadgetList(WindowID(#Infos))
StartDrawing(WindowOutput(#Infos))
Box(10,10,30,180,RGB(0,200,0))
Box(11,11,28,178,RGB(0,30,0))
For i=1 To MedVol Step 2
LineXY(12,190-i,12+25,190-i,RGB(0,200,0))
Next
StopDrawing()
Delay(25)
ForEver
EndProcedure
Procedure ShowLevelBar(param)
Repeat
Protected Dim Spectrum.f(1024),Dim WaveArray.f(1024),MedFreq.f,MedVol.f,i
FMOD_Channel_GetWaveData(Channel,WaveArray(),1024,0)
;FMOD_Channel_GetSpectrum(Channel,Spectrum(),1024,0,#FMOD_DSP_FFT_WINDOW_BLACKMANHARRIS)
MedVol=0
MedFreq=0
For i=1 To 1024
;MedFreq=MedFreq+Spectrum(i)
MedVol=MedVol+Abs(WaveArray(i))
Next
MedVol=(MedVol/1024)*500
;MedFreq=MedFreq/1024
;UseGadgetList(WindowID(#Infos))
StartDrawing(CanvasOutput(#CurrentVol))
Box(0,0,50,500,RGB(0,30,0))
Box(10,10,30,480,RGB(0,200,0))
Box(11,11,28,478,RGB(0,30,0))
For i=1 To MedVol Step 2
LineXY(12,490-i,12+25,490-i,RGB(0,200,0))
Next
StopDrawing()
Delay(25)
ForEver
EndProcedure
Procedure BigScreen()
Protected event2,MouseX,MouseY
ExamineDesktops()
Desk_w=DesktopWidth(0)
Desk_h=DesktopHeight(0)
OpenWindow(#BigScreenWnd,0,0,Desk_w,Desk_h,"Oscilloscope (mode plein écran)",#PB_Window_BorderLess)
SetWindowLong_(WindowID(#BigScreenWnd),#GWL_EXSTYLE,#WS_EX_LAYERED)
SetLayeredWindowAttributes_(WindowID(#BigScreenWnd),RGB(0,30,0),170,#LWA_COLORKEY | #LWA_ALPHA)
CanvasGadget(#BSW_Canvas,0,0,DesktopWidth(0),DesktopHeight(0))
thBSWContinue = 1
thBSW_DrawSpectrum = CreateThread(@BSW_DrawSpectrum(),1)
Repeat
event2= WaitWindowEvent()
Select event2
Case #PB_Event_Gadget
Select EventGadget()
Case #BSW_Canvas
If EventType()=#PB_EventType_LeftClick
MouseX=GetGadgetAttribute(#BSW_Canvas,#PB_Canvas_MouseX)
MouseY=GetGadgetAttribute(#BSW_Canvas,#PB_Canvas_MouseY)
If MouseX < Desk_w-3 And MouseX > Desk_w-47 And MouseY < 75 And MouseY > 25 ;Si on est sur le bouton pin/unpin
If PinState = #Pinned
StickyWindow(#BigScreenWnd,#False)
PinState = #Unpinned
Else
StickyWindow(#BigScreenWnd,#True)
PinState = #Pinned
EndIf
Else
thBSWContinue = 0
WaitThread(thBSW_DrawSpectrum)
CloseWindow(#BigScreenWnd)
ProcedureReturn
EndIf
EndIf
EndSelect
EndSelect
If Length <> 0
FMOD_Channel_GetPosition(Channel,@CurrentPos,1)
If CurrentPos >= Length
FMOD_Channel_Stop(Channel)
FMOD_System_PlaySound(fmodsystem, #FMOD_CHANNEL_FREE, sound, 0, @channel)
FMOD_Channel_SetVolume(Channel, Volume)
EndIf
EndIf
Until event2=#PB_Event_CloseWindow
EndProcedure
Procedure BSW_DrawSpectrum(param)
Repeat
Protected Dim SpectrumArray.f(1024), i.i, j.i, Max, Position.i,Yspect,YlowSpec,Out_width,Out_height
FMOD_Channel_GetSpectrum(Channel, SpectrumArray(), 1024, 0, #FMOD_DSP_FFT_WINDOW_BLACKMANHARRIS)
StartDrawing(CanvasOutput(#BSW_Canvas))
DrawingFont(FontID(#BigFontOldComputer))
Out_width = OutputWidth()
Out_height = OutputHeight()
DeskRatio.f = Out_width / 1024
;Clear de l'histogramme
Box(0, 0, Out_width, Out_height, RGB(0,30,0))
;Nom de la musique sur l'oscillo et progressbar
DrawText(2,2,Name,RGB(0,25,0),RGB(0,210,0))
Box(5,Out_height-25,Out_width-10,20,RGB(30,85,15))
Box(6,Out_height-24,Out_width-12,18,RGB(40,200,60))
Box(7,Out_height-23,Out_width-14,16,RGB(0,30,0))
If Length <> 0
Box(7,Out_height-23,Int((CurrentPos/Length)*Out_width -14),16,RGB(50,200,30))
LineXY(Int((CurrentPos/Length)*Out_width -14)+7,Out_height-23,Int((CurrentPos/Length)*Out_width -14)+7,Out_height-8,RGB(30,85,15))
EndIf
;Boite sous le curseur pour pouvoir cliquer a travers l'interface
Box(DesktopMouseX()-1,DesktopMouseY()-1,2,2,RGB(0,30,0))
;Cadre autour de l'histogramme
DrawingMode(#PB_2DDrawing_Outlined)
Box(0, 0, Out_width, Out_height, RGB(0, 200, 0))
;Bouton pin/unpin
Box(Out_width-52,25,50,50,RGB(0,200,0));Cadre autour du bouton
Box(Out_width-51,26,48,48,RGB(0,30,0))
If PinState = #Pinned
DrawImage(ImageID(#Pinned),Out_width-51,26)
Else
DrawImage(ImageID(#Unpinned),Out_width-51,26)
EndIf
;Dessin des points
DrawingMode(#PB_2DDrawing_Default)
For i=1 To 1024 Step 2
YlowSpec=(SpectrumArray(i)*1000)
;YlowSpec=(10*Log((SpectrumArray(i)/Pow(10,-12)))*1)
;Yspect=250-YlowSpec
Box(i*DeskRatio,(Out_height/2)-YlowSpec,DeskRatio,2+YlowSpec*2,RGB(0,200,0))
Next
StopDrawing()
Delay(25)
Until thBSWContinue = 0
EndProcedure
Enumeration FormFont
#Font_Mainform_0
EndEnumeration
LoadFont(#Font_Mainform_0,"Arial", 16)
Procedure OpenMainform(x = 0, y = 0, width = 1024+50, height = 500)
OpenWindow(#Mainform, x, y, width, height, "Oscilloscope", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
CanvasGadget(#Wave, 0, 0, 1024, 500)
CanvasGadget(#CurrentVol,1024,0,50,500)
ButtonGadget(#OpenFile, 20, 510, 80, 25, "Ouvrir")
TextGadget(#File,110,510,200,25,"Aucun fichier ouvert.")
ButtonGadget(#Pause, 420, 510, 70, 40, "Pause")
SetGadgetFont(#Pause, FontID(#Font_Mainform_0))
ButtonImageGadget(#Switch,500,510,60,60,ImageID(0))
SetGadgetAttribute(#Switch,#PB_Button_PressedImage,ImageID(2))
; ButtonImageGadget(#Filtres,570,510,60,60,ImageID(3))
TrackBarGadget(#Volume, 750, 520, 260, 25, 0, 100)
SetGadgetState(#Volume, 50)
FrameGadget(#Frame3D_0, 740, 500, 280, 50, "Volume")
AddWindowTimer(#MainForm,1,25)
AddWindowTimer(#MainForm,2,500)
OpenWindow(#Infos,WindowX(#Mainform)-150,WindowY(#Mainform),100,200,"Volume",#PB_Window_Tool ,WindowID(#Mainform))
StickyWindow(#Infos,#True)
SetWindowColor(#Infos,RGB(0,30,0))
UseGadgetList(WindowID(#Mainform))
EndProcedure
OpenMainform()
Init_x = WindowX(#Mainform)
Init_y = WindowY(#Mainform)
Init_width = 1024+50
Init_height = 500
FMOD_System_Create(@fmodsystem) ;On crée le systéme Fmod
FMOD_System_Init(fmodsystem, 32, #FMOD_INIT_NORMAL, 0)
Mutex=CreateMutex()
hThreadSpectrum=CreateThread(@ShowSpectrum(),1);Ce thread affiche le spectre du son en cours de lecture
hThreadWave=CreateThread(@ShowWaveAmp(),1) ; Celui ci affiche la sinusoide
hThreadLevelWind=CreateThread(@ShowLevels(),1) ;Affiche le volume dans une sickywindow
hThreadLevelBar=CreateThread(@ShowLevelBar(),1);Affiche le volume dans la fenêtre principale
Debug Analyse
Repeat
Event = WaitWindowEvent(100)
GEvent = EventGadget()
Select Event
Case #PB_Event_MaximizeWindow
PauseThread(hThreadWave)
PauseThread(hThreadSpectrum)
PauseThread(hThreadLevelBar)
PauseThread(hThreadLevelWind)
HideWindow(#Mainform,#True)
HideWindow(#Infos,#True)
ShowDesktop();/!\ Cette fonction fait partie de la librairie 'DroopyLib' de Droopy (utilisateur du forum PB). Code dispo à la fin de ce source.
BigScreen()
ResumeThread(hThreadWave)
ResumeThread(hThreadSpectrum)
ResumeThread(hThreadLevelBar)
ResumeThread(hThreadLevelWind)
ResizeWindow(#Mainform,Init_x,Init_y,Init_width,Init_height)
HideWindow(#Mainform,#False)
HideWindow(#Infos,#False)
Case #PB_Event_Timer
Select EventTimer()
Case 1
If WindowX(#Infos) < WindowX(#Mainform)+WindowWidth(#Mainform) And WindowX(#Infos) > WindowX(#Mainform)+(WindowWidth(#Mainform)-200)
HideWindow(#Infos,#True)
EndIf
If WindowMouseY(#Mainform) > 450 And state=0
For y=0 To 75 Step 3
ResizeWindow(#Mainform,#PB_Ignore,#PB_Ignore,#PB_Ignore,500+y)
WindowEvent()
Delay(10)
Next
state=1
EndIf
Case 2
If Right(Name,1) = "_" ;Clignotement du caret pour un effet "old terminal"
Name = Left(Name,Len(Name)-1)
Else
Name = Name + "_"
EndIf
If WindowMouseY(#Mainform) < 450 And state=1
For y=75 To 0 Step -3
ResizeWindow(#Mainform,#PB_Ignore,#PB_Ignore,#PB_Ignore,500+y)
WindowEvent()
Delay(10)
Next
state=0
EndIf
EndSelect
Case #PB_Event_Gadget
Select GEvent
Case #OpenFile
File = OpenFileRequester("Sélectionner un fichier mp3","","Musique|*.mp3;*.wav;*.ogg;*.flac",0)
If File <> ""
SetGadgetText(#File, GetFilePart(File))
If Sound <> 0
FMOD_Sound_Release(Sound);On détruit l'ancien son
EndIf
FMOD_System_CreateStream(fmodsystem, @File, #FMOD_SOFTWARE, 0, @sound);Et on charge le nouveau
FMOD_System_PlaySound(fmodsystem, #FMOD_CHANNEL_FREE, sound, 0, @channel)
FMOD_Channel_SetVolume(Channel, Volume)
FMOD_Sound_GetLength(Sound,@Length,1)
FMOD_Sound_GetName(Sound,@Name,40)
EndIf
Case #Volume
Volume = GetGadgetState(#Volume)/100
FMOD_Channel_SetVolume(Channel, Volume)
Case #Pause
FMOD_Channel_GetPaused(Channel, @PauseStatus)
If PauseStatus = #False
FMOD_Channel_SetPaused(Channel, #True)
SetGadgetText(#Pause, "Play")
Else
FMOD_Channel_SetPaused(Channel, #False)
SetGadgetText(#Pause, "Pause")
EndIf
Case #Stop
FMOD_Channel_Stop(Channel)
Case #Switch
If Analyse=0
SetGadgetAttribute(#Switch,#PB_Button_Image,ImageID(1))
Analyse=1
Else
SetGadgetAttribute(#Switch,#PB_Button_Image,ImageID(0))
Analyse=0
EndIf
Case #CurrentVol
If EventType()=#PB_EventType_LeftClick
ResizeWindow(#Infos,WindowX(#Mainform)+WindowWidth(#Mainform)+10,#PB_Ignore,#PB_Ignore,#PB_Ignore)
HideWindow(#Infos,#False)
EndIf
Case #Wave
If EventType()=#PB_EventType_LeftClick
MouseX=GetGadgetAttribute(#Wave,#PB_Canvas_MouseX)
MouseY=GetGadgetAttribute(#Wave,#PB_Canvas_MouseY)
If MouseY > 475 And MouseY < 495 And MouseX < 1019 And MouseX > 5
CurrentPos=Int((MouseX/1014)*Length)
FMOD_Channel_SetPosition(Channel,CurrentPos,1)
EndIf
EndIf
EndSelect
Case #PB_Event_CloseWindow
FMOD_Channel_Stop(Channel)
FMOD_System_Release(fmodsystem)
End
EndSelect
If Length <> 0
FMOD_Channel_GetPosition(Channel,@CurrentPos,1)
If CurrentPos >= Length
FMOD_Channel_Stop(Channel)
FMOD_System_PlaySound(fmodsystem, #FMOD_CHANNEL_FREE, sound, 0, @channel)
FMOD_Channel_SetVolume(Channel, Volume)
EndIf
EndIf
ForEver
;Code of the ShowDesktop() function included in the DroopyLib
;-------------------------------------------------------------------------
; ProcedureDLL ShowDesktop() ; Hide all Windows, and Show the Desktop
;
; retour=SendMessage_ (FindWindow_("Shell_TrayWnd", NULL), $111, 419, 0)
; If retour<>0 : retour =0 : Else : retour=1 : EndIf
; ProcedureReturn retour
; EndProcedure
;-------------------------------------------------------------------------