/* LoopWidget * Copyleft (C) 2000 David Griffiths * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "Fl_Loop.h" #include #include #include #include #include ///////////////////////////////////////////////////////////////////////////// static const int REZ = 1000; static const float RADCONV = 0.017453292; static const int INDW = 3; // indicator width static const int UPDATECYCLES = 4; static const int POSMARKER_MAX = 50; Fl_Loop::Fl_Loop(int x, int y, int w, int h, const char* label) : Fl_Group(x,y,w,h,label), m_data(NULL), m_MainWin(NULL), m_Length(1000), m_InnerRad((int)(w/2*0.75f)), m_OuterRad((int)(w/2*0.95f)), m_BorderRad(w/2), m_IndSX(0), m_IndSY(0), m_IndEX(0), m_IndEY(0), m_StartAngle(0), m_EndAngle(1), m_MoveAngle(0.0f), m_RangeStart(0), m_RangeEnd(0), m_Angle(0), m_Pos(0), m_Update(true), m_StopUpdate(false), m_WaveSize(1.0f), m_Move(0), m_LastMove(0), m_Snap(false), m_SnapDegrees(45), m_PosMarkerCount(0), cb_Move(NULL), m_BGColour (FL_BLACK), m_WaveColour (FL_GREEN), m_SelColour (FL_WHITE), m_IndColour (FL_BLUE), m_MrkColour (FL_YELLOW) { box(FL_NO_BOX); m_MidX=(w/2)+x; m_MidY=(h/2)+y-20; } void Fl_Loop::SetData(float const *set, const int Len) { if (m_data!=NULL) delete[] m_data; m_data = new float[Len]; memcpy((void*)m_data,(void*)set,Len*sizeof(float)); SetLength(Len); } void Fl_Loop::SetLength(const int Len) { m_Length=Len; // recalc start and end points m_RangeStart=(long)(m_StartAngle*(m_Length/360.0f)); while (m_RangeStart < 0) m_RangeStart += m_Length; while (m_RangeStart > m_Length) m_RangeStart -= m_Length; m_RangeEnd=(long)(m_EndAngle*(m_Length/360.0f)); while (m_RangeEnd < 0) m_RangeEnd += m_Length; while (m_RangeEnd > m_Length) m_RangeEnd -= m_Length; } void Fl_Loop::SelectAll() { m_RangeStart=0; m_RangeEnd=m_Length; } void Fl_Loop::DrawWav() { int Thickness=(m_OuterRad-m_InnerRad)/2; int n=0,X=0,Y=0,ox=0,oy=0, c=0; bool FirstTime=true, DrawnSnap=false; float Angle=0; float Sample=0; float SampleAngle=360.0f/(float)(REZ); fl_color (m_WaveColour); while(m_Length>0 && n1) Sample=1; if (Sample<-1) Sample=-1; } Angle=c*SampleAngle; ox=X; oy=Y; float pos=Sample*Thickness+m_InnerRad+Thickness; X=(int)(m_MidX+x()+sin(Angle*RADCONV)*pos); Y=(int)(m_MidY+y()+cos(Angle*RADCONV)*pos); if (Angle>m_StartAngle && Anglevisible() || !parent()->visible()) return; window()->make_current(); float Angle=(m_Pos/m_Length)*360.0; fl_line_style(FL_SOLID, 3, NULL); #if !__APPLE__ XSetFunction(fl_display,fl_gc,GXxor); #endif fl_line(m_IndSX,m_IndSY,m_IndEX,m_IndEY); fl_color (m_IndColour); m_IndSX=(int)(m_MidX+x()+sin(Angle*RADCONV)*m_InnerRad); m_IndSY=(int)(m_MidY+y()+cos(Angle*RADCONV)*m_InnerRad); m_IndEX=(int)(m_MidX+x()+sin(Angle*RADCONV)*m_OuterRad); m_IndEY=(int)(m_MidY+y()+cos(Angle*RADCONV)*m_OuterRad); fl_line(m_IndSX,m_IndSY,m_IndEX,m_IndEY); fl_line_style(FL_SOLID, 1, NULL); #if !__APPLE__ XSetFunction(fl_display,fl_gc,GXcopy); #endif if (m_PosMarkerCount>POSMARKER_MAX) { redraw(); m_PosMarkerCount=0; } m_PosMarkerCount++; //Last->make_current(); } void Fl_Loop::DrawWidgets() { Fl_Group::draw(); } void Fl_Loop::DrawEveryThing() { if (damage() & (FL_DAMAGE_EXPOSE|FL_DAMAGE_ALL)) { if (m_PosMarkerCount>POSMARKER_MAX) { m_PosMarkerCount=0; } //fl_color(color()); //fl_rectf(x(),y(),w(),h()); m_InnerRad-=5; m_OuterRad+=5; fl_color (m_BGColour); fl_pie(m_MidX+x()-m_OuterRad, m_MidY+y()-m_OuterRad, m_OuterRad*2, m_OuterRad*2, 0, 360); fl_color (color()); fl_pie(m_MidX+x()-m_InnerRad, m_MidY+y()-m_InnerRad, m_InnerRad*2, m_InnerRad*2, 0, 360); m_OuterRad-=5; m_InnerRad+=5; DrawWav(); } DrawWidgets(); } void Fl_Loop::draw() { DrawEveryThing(); } int Fl_Loop::handle(int event) { static int LastButtonPushed=0; // call base if (!Fl_Group::handle(event)) { switch (event) { case FL_PUSH: LastButtonPushed=Fl::event_button(); // fall through case FL_DRAG: { int mx = Fl::event_x()-(m_MidX+x()); int my = Fl::event_y()-(m_MidY+y()); if (!mx && !my) break; double angle = 90+atan2((float)-my, (float)mx)*180/M_PI; while (angle < m_Angle-180) angle += 360; while (angle > m_Angle+180) angle -= 360; while (angle < 0) angle += 360; while (angle > 360) angle -= 360; m_Angle=angle; // snap if (m_Snap) { m_Angle-=(int)m_Angle%m_SnapDegrees; } if (LastButtonPushed==2) { m_Pos=m_Angle*(m_Length/360.0f); while (m_Pos < 0) m_Pos += m_Length; while (m_Pos > m_Length) m_Pos -= m_Length; } else if (LastButtonPushed==1) { switch (event) { case FL_PUSH: { m_StartAngle=m_Angle; m_EndAngle=m_Angle; redraw(); } break; case FL_DRAG: { if (m_Angle>m_StartAngle) { m_EndAngle=m_Angle; } else { m_StartAngle=m_Angle; } redraw(); } break; } // convert angle to sample data m_RangeStart=(long)(m_StartAngle*(m_Length/360.0f)); while (m_RangeStart < 0) m_RangeStart += m_Length; while (m_RangeStart > m_Length) m_RangeStart -= m_Length; m_RangeEnd=(long)(m_EndAngle*(m_Length/360.0f)); while (m_RangeEnd < 0) m_RangeEnd += m_Length; while (m_RangeEnd > m_Length) m_RangeEnd -= m_Length; }else if (LastButtonPushed==3) { switch (event) { case FL_PUSH: { m_MoveAngle=m_Angle; // reset the last // convert angle to sample data m_LastMove=(int)(m_MoveAngle*(m_Length/360.0f)); while (m_LastMove < 0) m_LastMove += m_Length; while (m_LastMove > m_Length) m_Move -= m_Length; } break; case FL_DRAG: { m_MoveAngle=m_Angle; redraw(); } break; } // convert angle to sample data m_Move=(int)(m_MoveAngle*(m_Length/360.0f)); while (m_Move < 0) m_Move += m_Length; while (m_Move > m_Length) m_Move -= m_Length; // do the move if (cb_Move) cb_Move(this,m_LastMove-m_Move); m_LastMove=m_Move; } } break; case FL_RELEASE: break; default: return 0; } } return 1; }