/* 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 ///////////////////////////////////////////////////////////////////////////// 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(NULL), m_Update(false), m_StopUpdate(false), m_WaveSize(1.0f), m_Move(0), m_LastMove(0), m_Snap(false), m_SnapDegrees(45), m_PosMarkerCount(0) { m_MidX=(w/2)+x; m_MidY=(h/2)+y-20; } void Fl_Loop::SetupCopyBufFuncs(cb_CopyBuf1 *Cut, cb_CopyBuf1 *Copy, cb_CopyBuf2 *Paste, cb_CopyBuf2 *PasteMix, cb_CopyBuf1 *ZeroRange, cb_CopyBuf1 *ReverseRange, cb_CopyBuf1 *Halve, cb_CopyBuf1 *Hold, cb_CopyBuf1 *SelectAll, cb_CopyBuf1 *NewTrigger, cb_CopyBuf1 *Move) { cb_Cut = Cut; cb_Copy = Copy; cb_Paste = Paste; cb_PasteMix = PasteMix; cb_ZeroRange = ZeroRange; cb_ReverseRange = ReverseRange; cb_Halve = Halve; cb_Hold = Hold; cb_SelectAll = SelectAll; cb_NewTrigger = NewTrigger; cb_Move = Move; } void Fl_Loop::SetLength(const int Len) { m_Length=Len; // recalc start and end points m_RangeStart=(int)(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=(int)(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::DrawWav() { int Thickness=(m_OuterRad-m_InnerRad)/2; int n=0,X=0,Y=0,ox=0,oy=0, c=0, skip=0; bool FirstTime=true; float Angle=0; float Sample=0; float SampleAngle=360.0f/(float)(REZ); skip=m_Length/REZ; if (skip<1) skip=1; fl_color(100,155,100); 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(); if (m_Pos) { 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(FL_BLUE); 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(20,60,20); 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) { if (m_Pos) { *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=(int)(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=(int)(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 cb_Move(this,m_LastMove-m_Move,0); m_LastMove=m_Move; } } break; case FL_RELEASE: break; case FL_KEYBOARD: case FL_SHORTCUT: { if (Fl::event_key(FL_Control_L) || Fl::event_key(FL_Control_R)) { if (Fl::event_key('c')) cb_Copy(this,m_RangeStart,m_RangeEnd); if (Fl::event_key('v')) cb_Paste(this,m_RangeStart); if (Fl::event_key('x')) cb_Cut(this,m_RangeStart,m_RangeEnd); if (Fl::event_key('b')) cb_PasteMix(this,m_RangeStart); if (Fl::event_key('z')) cb_ZeroRange(this,m_RangeStart,m_RangeEnd); if (Fl::event_key('r')) cb_ReverseRange(this,m_RangeStart,m_RangeEnd); if (Fl::event_key('h')) cb_Halve(this,0,0); if (Fl::event_key('s')) cb_Hold(this,0,0); if (Fl::event_key('a')) { m_StartAngle=0.0f; m_RangeStart=0; m_EndAngle=360.0f; m_RangeEnd=m_Length; redraw(); } if (Fl::event_key('t')) cb_NewTrigger(this,0,0); // move? } } break; default: return 0; } } return 1; }