Changeset 1308

Show
Ignore:
Timestamp:
11/10/07 03:53:24 (11 months ago)
Author:
calvin
Message:

the wave editor control was almost fully rewritten

Location:
trunk/src/buzelib
Files:
6 modified

Legend:

Unmodified
Added
Removed
  • trunk/src/buzelib/MainFrm.cpp

    r1307 r1308  
    801801        // if a sample exists on selected spot, ask if we should overwrite 
    802802        if (wavetableView.getViews() == 0) return 0; 
    803         int i = wavetableView.getView(0)->getSelectedWaveIndex(); 
     803        int i = wavetableView.getView(0)->waveTableList.GetSelectedIndex(); 
    804804        if (i == -1) return 0; 
    805805 
  • trunk/src/buzelib/WaveEditorCtrl.cpp

    r1288 r1308  
    99#include <atlctrlw.h> 
    1010#include "resource.h" 
    11 #include "MainFrm.h" 
    1211#include "WaveEditorCtrl.h" 
    13 #include "WaveTableView.h" 
    1412 
    1513#ifdef min 
     
    2018#endif 
    2119 
    22 using namespace zzub; 
    23  
    24 CWaveEditorCtrl::CWaveEditorCtrl(int index, int level, CWaveTableView* v) { 
    25         this->currentWave=index; 
    26         this->currentLevel=level; 
    27  
    28         this->view=v; 
    29  
    30         paintDelta=0.0f; 
    31         beginSelectSample=endSelectSample= -1; 
    32         beginDisplaySample=endDisplaySample=0; 
    33         beginLoop=endLoop=0; 
    34  
    35         moveType=MoveNothing; 
    36         gridType=WaveEditorSeconds; 
     20template <typename T> 
     21inline bool compareWithEpsilon(const T& v1, const T& v2, const T &epsilon) { 
     22        const T diff = v1 - v2; 
     23        return diff < epsilon && diff > -epsilon; 
     24} 
     25 
     26CWaveEditorCtrl::CWaveEditorCtrl() { 
     27        paintDelta = 0.0f; 
     28        beginSelectSample = -1; 
     29        endSelectSample = 0; 
     30        firstSelectSample = -1; 
     31        lastSelectSample = 0; 
     32        beginDisplaySample = -1; 
     33        numDisplaySamples = 0; 
     34 
     35        moveType = MoveNothing; 
     36        gridType = WaveEditorSamples; 
     37 
     38        memset(&waveInfo, 0, sizeof(EDITWAVEINFO)); 
    3739} 
    3840 
     
    4547} 
    4648 
    47 wave_info_ex* CWaveEditorCtrl::getWave() { 
    48         if (currentWave<0 || currentWave>=view->mainFrame->player->getWaves()) return 0; 
    49  
    50         return view->mainFrame->player->getWave(currentWave); 
    51 } 
    52  
    53 int CWaveEditorCtrl::getWaveLevel() { 
    54         wave_info_ex* entry=getWave(); 
    55         if (entry==0) return -1; 
    56         int numlevels=entry->get_levels(); 
    57         if (currentLevel<0 || currentLevel>=numlevels) return -1; 
    58         return currentLevel; 
    59 } 
    60  
    61  
    62 // assume we're working within 0x8000 
    63 int getSampleAt(void* buffer, int waveChannels, int waveFormat, float sample, int interleave) { 
    64         DWORD temp; 
    65         float tempF; 
    66         float* fbuffer; 
    67         char* cbuffer;//=(char*)buffer; 
    68         switch (waveFormat) { 
    69                 case wave_buffer_type_si16: 
    70                         return ((short*)buffer)[(size_t)sample*waveChannels + interleave*2]; 
    71                 case wave_buffer_type_si24: 
    72                         cbuffer=(char*)buffer;  // aligned by 1 byte?? 
    73                         temp=*(DWORD*)(&cbuffer[(size_t)sample*waveChannels*3 + interleave*3]) & 0x00ffffff; 
    74                         if (temp & 0x00800000) temp = temp | 0xFF000000; 
    75                         return (signed short)((int)temp >> 8) ;//cbuffer[sample*waveChannels*3]; 
    76                 case wave_buffer_type_si32: 
    77                         cbuffer=(char*)buffer; 
    78                         temp=*(DWORD*)(&cbuffer[(size_t)sample*waveChannels*4 + interleave*4]); 
    79                         return (signed short)(temp >> 16) ;//cbuffer[sample*waveChannels*3]; 
    80                 case wave_buffer_type_f32: 
    81                         cbuffer=(char*)buffer; 
    82                         fbuffer=(float*)(&cbuffer[(size_t)sample*waveChannels*4 + interleave*4]); 
    83                         tempF=*fbuffer; 
    84                         tempF*=0x8000; 
    85                         return tempF; 
    86         } 
    87         return 0; 
    88 } 
    8949LRESULT CWaveEditorCtrl::OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { 
    9050 
    91         CPaintDC dc(m_hWnd); 
     51        CPaintDC screenDC(m_hWnd); 
     52        CMemDC dc(screenDC); 
    9253 
    9354        RECT rc; 
    9455        GetClientRect(&rc); 
    9556 
    96         // sizes and positioning are determined by the constants defined on top of this page 
    97         int width=rc.right-rc.left; 
    98         int height=(rc.bottom-rc.top) - 20; // reserve 20px for timeline 
    99  
    100         view->mainFrame->player->lock(); 
    101         wave_info_ex* wave=getWave(); 
    102         if (wave==0) { 
    103                 view->mainFrame->player->unlock(); 
    104                 return DefWindowProc(); 
    105         } 
    106  
    107         int waveChannels=wave->get_stereo()?2:1; 
    108  
    109         int displaySamples=(endDisplaySample-beginDisplaySample)+1; 
    110  
    111         paintDelta=(double)(displaySamples) / (double)width; 
    112  
    113         double sample=beginDisplaySample; 
     57        // paint sample channels 
     58        int width = rc.right-rc.left; 
     59        int height = (rc.bottom-rc.top) - 20; // reserve 20px for timeline 
     60 
     61        int fullHeight = height; 
     62 
     63        if (waveInfo.stereo) { 
     64                height = (height - 4) / 2; 
     65                RECT rcL = { 0, 0, width, height }; 
     66                RECT rcR = { 0, height + 4, width, height * 2 + 4 }; 
     67                paintSampleChannel(dc, rcL, 0); 
     68                paintSampleChannel(dc, rcR, 1); 
     69                // paint splitter 
     70                RECT rcSplit = { 0, height, width, height + 4}; 
     71                dc.FillSolidRect(&rcSplit, GetSysColor(COLOR_3DFACE)); 
     72        } else { 
     73                RECT rcL = { 0, 0, width, height }; 
     74                paintSampleChannel(dc, rcL, 0); 
     75        } 
     76 
     77 
     78        // paint timeline 
     79        CRect tlrc(0, fullHeight+1, width, fullHeight+20); 
     80        paintTimeline(dc, tlrc); 
     81 
     82        // if looping points are set, draw them with protracker-type handles 
     83        int beginLoopX = (float)(waveInfo.beginLoop - beginDisplaySample) / paintDelta; 
     84        int endLoopX = (float)(waveInfo.endLoop - beginDisplaySample) / paintDelta - 1; 
     85 
     86        CPen loopPen; 
     87        loopPen.CreatePen(PS_SOLID, 1, 0x00FF00); 
     88 
     89        dc.SelectPen(loopPen); 
     90        dc.MoveTo(beginLoopX, fullHeight); 
     91        dc.LineTo(beginLoopX, 0); 
     92        dc.LineTo(beginLoopX+8, 0); 
     93        dc.LineTo(beginLoopX+8, 8); 
     94        dc.LineTo(beginLoopX, 8); 
     95 
     96        dc.MoveTo(endLoopX, fullHeight); 
     97        dc.LineTo(endLoopX, 0); 
     98        dc.LineTo(endLoopX-8, 0); 
     99        dc.LineTo(endLoopX-8, 8); 
     100        dc.LineTo(endLoopX, 8); 
     101 
     102        return DefWindowProc(); 
     103} 
     104 
     105inline float sample_scale(wave_buffer_type format, void* buffer) { 
     106        unsigned int i; 
     107        switch (format) { 
     108                case wave_buffer_type_si16: 
     109                        return static_cast<float>(*(short*)buffer) / 0x7fff; 
     110                case wave_buffer_type_si24: 
     111                        i = (*(unsigned int*)buffer) & 0x00ffffff; 
     112                        if (i & 0x00800000) i = i | 0xFF000000; 
     113                        return static_cast<float>((int)i) / 0x007fffff; 
     114                case wave_buffer_type_si32: 
     115                        return static_cast<float>(*(int*)buffer) / 0x7fffffff; 
     116                case wave_buffer_type_f32: 
     117                        return *(float*)buffer; 
     118                default: 
     119                        return 0; 
     120        } 
     121} 
     122 
     123int get_format_bytes(wave_buffer_type format) { 
     124        switch (format) { 
     125                case wave_buffer_type_si16: 
     126                        return 2; 
     127                case wave_buffer_type_si24: 
     128                        return 3; 
     129                case wave_buffer_type_f32: 
     130                case wave_buffer_type_si32: 
     131                        return 4; 
     132                default: 
     133                        return 2; 
     134        } 
     135} 
     136 
     137void scan_min_max(wave_buffer_type format, void* buffer, int num_samples, bool stereo, int channel, float& out_min, float& out_max) { 
     138        int sample_size = get_format_bytes(format); 
     139        out_min = 0;//std::numeric_limits<float>::max(); 
     140        out_max = 0;//std::numeric_limits<float>::min(); 
     141 
     142        char* pbuf = (char*)buffer; 
     143        for (int i = 0; i < num_samples; i++) { 
     144                if (channel == 0) { 
     145                        float s = sample_scale(format, pbuf); 
     146                        if (s < out_min) 
     147                                out_min = s; 
     148                        if (s > out_max) 
     149                                out_max = s; 
     150 
     151                } 
     152                pbuf += sample_size; 
     153                if (stereo) { 
     154                        if (channel == 1) { 
     155                                float s = sample_scale(format, pbuf); 
     156                                if (s < out_min) 
     157                                        out_min = s; 
     158                                if (s > out_max) 
     159                                        out_max = s;                     
     160                        } 
     161                        pbuf += sample_size; 
     162                } 
     163 
     164        } 
     165} 
     166 
     167void CWaveEditorCtrl::paintSampleChannel(CDC& dc, RECT rc, int channel) { 
     168 
     169        int width = rc.right - rc.left; 
     170        int height = rc.bottom - rc.top; 
     171        int waveChannels = waveInfo.stereo?2:1; 
     172 
    114173        CPen selectedPen; 
    115174        selectedPen.CreatePen(PS_SOLID, 1, 0xff0000); 
    116         long minSelect=std::min(beginSelectSample, endSelectSample); 
    117         long maxSelect=std::max(beginSelectSample, endSelectSample); 
    118  
    119         void* sampleBuffer=wave->get_sample_ptr(currentLevel); 
    120  
    121         int sampleSamples=wave->get_sample_count(currentLevel); 
    122         int waveFormat=wave->get_wave_format(currentLevel); 
    123  
    124         int fullHeight=height; 
    125         if (waveChannels==2) { 
    126                 height/=2; 
    127                 height-=2; 
    128         } 
    129  
    130         int x=0, y=height/2, y2=height/2; 
    131  
    132         for (int i=0; i<width; i++) { 
    133                 if (!sampleBuffer) break; 
    134                 int sampleOfs=floor(sample); 
    135                 if (sampleOfs>endDisplaySample || sampleOfs>=sampleSamples) break; 
    136  
    137                 float v=(float)getSampleAt(sampleBuffer, waveChannels, waveFormat, sampleOfs, 0); 
    138                 v = (v/(float)0x8000)*(float)(height/2); 
    139              
    140                 if (sampleOfs>=minSelect && sampleOfs<maxSelect+1) 
    141                         dc.SelectStockPen(WHITE_PEN); else 
    142                         dc.SelectStockPen(BLACK_PEN); 
    143  
    144                 dc.MoveTo(i, 0); 
    145                 dc.LineTo(i, 0+height); 
    146  
    147                 if (sampleOfs>=minSelect && sampleOfs<maxSelect+1) 
     175 
     176        CPenHandle oldpen = dc.SelectPen(selectedPen); 
     177 
     178        int sampleSize = get_format_bytes(waveInfo.type); 
     179 
     180        double sample = beginDisplaySample; 
     181 
     182        dc.FillSolidRect(&rc, 0); 
     183 
     184        double selectDelta = paintDelta>1?paintDelta:0; 
     185 
     186        for (int i = 0; i < width; i++) { 
     187                if (!waveInfo.bits) break; 
     188                int sampleOfs = floor(sample); 
     189                if (sampleOfs > beginDisplaySample + numDisplaySamples || sampleOfs >= waveInfo.samples) break; 
     190 
     191                char* pbuf = (char*)waveInfo.bits + sampleOfs * sampleSize * waveChannels; 
     192 
     193                float out_min, out_max; 
     194                scan_min_max((wave_buffer_type)waveInfo.type, pbuf, paintDelta>1?(int)paintDelta:1, waveInfo.stereo, channel, out_min, out_max); 
     195 
     196                out_min *= (float)height/2; 
     197                out_max *= (float)height/2; 
     198 
     199                if (sampleOfs >= beginSelectSample-selectDelta && sampleOfs <= endSelectSample-selectDelta) { 
     200                        dc.SelectStockPen(WHITE_PEN); 
     201                        dc.MoveTo(i, rc.top); 
     202                        dc.LineTo(i, rc.top+height); 
     203                } 
     204 
     205                if (sampleOfs >= beginSelectSample-selectDelta && sampleOfs <= endSelectSample-selectDelta) 
    148206                        dc.SelectPen(selectedPen); else 
    149207                        dc.SelectStockPen(WHITE_PEN); 
    150208 
    151                 dc.MoveTo(x, 0+y); 
    152                 dc.LineTo(i, 0+v + height/2); 
    153  
    154                 if (waveChannels==2) { 
    155                         // tegne nederste? for svarte - må jo kunne gjøre dette litt smoothere 
    156                         float v2=(float)getSampleAt(sampleBuffer, waveChannels, waveFormat, sampleOfs, 1); 
    157                         v2 = (v2/(float)0x8000)*(float)(height/2); 
    158                      
    159                         if (sampleOfs>=minSelect && sampleOfs<maxSelect+1) 
    160                                 dc.SelectStockPen(WHITE_PEN); else 
    161                                 dc.SelectStockPen(BLACK_PEN); 
    162  
    163                         dc.MoveTo(i, height+4); 
    164                         dc.LineTo(i, height+4+height); 
    165  
    166                         if (sampleOfs>=minSelect && sampleOfs<maxSelect+1) 
    167                                 dc.SelectPen(selectedPen); else 
    168                                 dc.SelectStockPen(WHITE_PEN); 
    169  
    170                         dc.MoveTo(x, height+4+y2); 
    171                         dc.LineTo(i, height+4+v2 + height/2); 
    172  
    173                         y2=v2+height/2; 
    174                 } 
    175  
    176                 x=i; 
    177                 y=v+height/2; 
    178  
    179                 sample+=paintDelta;     // kanskje vi skal gange med channels her? mulig at vi bare får se halve stereosampels 
    180         } 
    181  
    182         view->mainFrame->player->unlock(); 
    183  
    184  
    185         CRect tlrc(0, fullHeight+1, width, fullHeight+20); 
    186         dc.FillRect(&tlrc, COLOR_BTNFACE); 
    187         dc.Draw3dRect(&tlrc, GetSysColor(COLOR_BTNHIGHLIGHT), GetSysColor(COLOR_BTNSHADOW));//0, height, width, height+20); 
     209                dc.MoveTo(i, rc.top + out_min + height/2); 
     210                dc.LineTo(i, rc.top + out_max + height/2 + 1); 
     211 
     212                sample += paintDelta; 
     213        } 
     214 
     215        dc.SelectPen(oldpen); 
     216 
     217} 
     218 
     219void CWaveEditorCtrl::paintTimeline(CDC& dc, RECT rc) { 
     220 
     221        int width = rc.right - rc.left; 
     222        int fullHeight = rc.top; 
     223 
     224        dc.FillRect(&rc, COLOR_BTNFACE); 
     225         
     226        CPen lightPen; 
     227        lightPen.CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNHIGHLIGHT)); 
     228        CPenHandle oldpen = dc.SelectPen(lightPen); 
     229        dc.MoveTo(0, rc.top); 
     230        dc.LineTo(rc.right, rc.top); 
     231//      dc.Draw3dRect(&rc, GetSysColor(COLOR_BTNHIGHLIGHT), GetSysColor(COLOR_BTNSHADOW));//0, height, width, height+20); 
    188232 
    189233        float samplesPerUnit = getSamplesPerUnit(gridType); 
     
    217261        CFont tickFont; 
    218262        tickFont.CreateFont(11, 0, 0, 0, FW_BOLD, FALSE, FALSE, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH|FF_DONTCARE, ""); 
    219         UINT prevAlign=dc.SetTextAlign(TA_CENTER); 
    220  
    221         dc.SelectFont(tickFont); 
    222         int prevBkMode = dc.SetBkMode(TRANSPARENT); 
     263        UINT oldAlign = dc.SetTextAlign(TA_CENTER); 
     264 
     265        CFontHandle oldfont = dc.SelectFont(tickFont); 
     266        int oldBkMode = dc.SetBkMode(TRANSPARENT); 
    223267        while (tickX < width) { 
    224268                dc.MoveTo(tickX, fullHeight+2); 
     
    231275        } 
    232276 
    233         dc.SetBkMode(prevBkMode); 
    234         dc.SetTextAlign(prevAlign); 
    235  
    236         selectedPen.DeleteObject(); 
    237  
    238         // if looping points are set, draw them with protracker-type handles 
    239         int beginLoopX=(float)(beginLoop-beginDisplaySample) / paintDelta; 
    240         int endLoopX=(float)(endLoop-beginDisplaySample) / paintDelta -0.5; 
    241  
    242         CPen loopPen; 
    243         loopPen.CreatePen(PS_SOLID, 1, 0x00FF00); 
    244  
    245         dc.SelectPen(loopPen); 
    246         dc.MoveTo(beginLoopX, fullHeight); 
    247         dc.LineTo(beginLoopX, 0); 
    248         dc.LineTo(beginLoopX+8, 0); 
    249         dc.LineTo(beginLoopX+8, 8); 
    250         dc.LineTo(beginLoopX, 8); 
    251  
    252         dc.MoveTo(endLoopX, fullHeight); 
    253         dc.LineTo(endLoopX, 0); 
    254         dc.LineTo(endLoopX-8, 0); 
    255         dc.LineTo(endLoopX-8, 8); 
    256         dc.LineTo(endLoopX, 8); 
    257  
    258         return DefWindowProc(); 
    259 } 
     277        dc.SetBkMode(oldBkMode); 
     278        dc.SetTextAlign(oldAlign); 
     279        dc.SelectPen(oldpen); 
     280        dc.SelectFont(oldfont); 
     281} 
     282 
    260283 
    261284std::string CWaveEditorCtrl::formatSampleUnit(float units, WaveEditorGridMode mode) { 
     
    290313} 
    291314 
     315void CWaveEditorCtrl::sortSelection() { 
     316        beginSelectSample = std::min(firstSelectSample, lastSelectSample); 
     317        endSelectSample = std::max(firstSelectSample, lastSelectSample); 
     318         
     319        if (beginSelectSample == -1) return ; 
     320 
     321        if (beginSelectSample < 0) beginSelectSample = 0; 
     322        if (endSelectSample < 0) endSelectSample = 0; 
     323 
     324        if (beginSelectSample >= waveInfo.samples) 
     325                beginSelectSample = waveInfo.samples - 1; 
     326 
     327        if (endSelectSample >= waveInfo.samples) 
     328                endSelectSample = waveInfo.samples - 1; 
     329} 
     330 
    292331LRESULT CWaveEditorCtrl::OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) { 
    293332        // vi skal sette et startsample på når vi begynner selecte 
     
    302341 
    303342        // adjust for extreme cases, so we can click on the loop-pixel itself 
    304         rcBeginLoop.left-=1; 
    305         rcEndLoop.right+=1; 
     343        rcBeginLoop.left -= 1; 
     344        rcEndLoop.right += 1; 
    306345 
    307346        if (PtInRect(&rcBeginLoop, pt)) { 
    308                 moveType=MoveLoopStart; 
     347                moveType = MoveLoopStart; 
    309348        } else 
    310349        if (PtInRect(&rcEndLoop, pt)) { 
    311                 moveType=MoveLoopEnd; 
     350                moveType = MoveLoopEnd; 
    312351        } else { 
    313                 beginSelectSample=beginDisplaySample+(float)pt.x*paintDelta; 
    314                 if (beginSelectSample<0) beginSelectSample=0; 
    315                 if (beginSelectSample>endDisplaySample) 
    316                         beginSelectSample=endDisplaySample; 
    317                 moveType=MoveSelection; 
     352                firstSelectSample = lastSelectSample = beginDisplaySample+(float)pt.x*paintDelta; 
     353                if (firstSelectSample < 0) beginSelectSample = 0; 
     354                if (firstSelectSample > beginDisplaySample + numDisplaySamples) 
     355                        firstSelectSample = beginDisplaySample + numDisplaySamples; 
     356                sortSelection(); 
     357                moveType = MoveSelection; 
    318358        } 
    319359        SetCapture(); 
     
    328368 
    329369        // sizes and positioning are determined by the constants defined on top of this page 
    330         int width=rc.right-rc.left; 
    331  
    332         int displaySamples=(endDisplaySample-beginDisplaySample)+1; 
    333  
    334         paintDelta=(float)displaySamples / (float)width; 
    335  
    336         int beginLoopX=(float)(beginLoop-beginDisplaySample) / paintDelta; 
    337         int endLoopX=(float)(endLoop-beginDisplaySample) / paintDelta -0.5; 
    338  
    339         if (type==0) 
     370        int width = rc.right-rc.left; 
     371 
     372        int beginLoopX = (float)(waveInfo.beginLoop - beginDisplaySample) / paintDelta; 
     373        int endLoopX = (float)(waveInfo.endLoop - beginDisplaySample) / paintDelta -0.5; 
     374 
     375        if (type == 0) 
    340376                SetRect(rcOut, beginLoopX, 0, beginLoopX+8, 8); else 
    341377                SetRect(rcOut, endLoopX-8, 0, endLoopX, 8); 
     
    343379} 
    344380 
    345  
    346 void CWaveEditorCtrl::setZoomDisplay(size_t beginSample, size_t endSample) { 
    347  
    348         // update scroll bars 
    349         size_t scrollRange = 0; 
    350         wave_info_ex* wave = getWave(); 
    351         if (wave) { 
    352                 size_t sample_count = wave->get_sample_count(getWaveLevel()); 
    353                 if (sample_count>0)  
    354                         scrollRange = sample_count-1; 
    355                 if (endSample >= sample_count) 
    356                         endSample = sample_count-1; 
    357         } 
    358  
    359         beginDisplaySample = beginSample; 
    360         endDisplaySample = endSample; 
    361  
    362         SetScrollRange(SB_HORZ, 0, scrollRange); 
     381void CWaveEditorCtrl::updateAlign() { 
     382        RECT rcClient; 
     383        GetClientRect(&rcClient); 
     384        if (rcClient.right > 0) { 
     385                paintDelta = (double)numDisplaySamples / (double)rcClient.right; 
     386 
     387                if (paintDelta > 1) { 
     388                        double modval = fmod(beginDisplaySample, paintDelta); 
     389                        const double epsilon = 0.000002; 
     390                        if (!compareWithEpsilon(paintDelta, modval, epsilon) && !compareWithEpsilon(modval, (double)0.0f, epsilon)) 
     391                                beginDisplaySample -= modval; 
     392                } 
     393        } else 
     394                paintDelta = 0; 
     395} 
     396 
     397void CWaveEditorCtrl::updateScrollbars() { 
     398 
     399        updateAlign(); 
     400        double samples = waveInfo.samples - 1; 
    363401 
    364402        SCROLLINFO si; 
    365403        si.cbSize = sizeof(SCROLLINFO); 
    366         si.fMask = SIF_PAGE; 
    367         si.nPage = endSample - beginSample + 1; 
     404        si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; 
     405        si.nPage = numDisplaySamples; 
     406        si.nPos = ceil(beginDisplaySample); 
     407        si.nMin = 0; 
     408        si.nMax = samples; 
    368409        SetScrollInfo(SB_HORZ, &si); 
    369  
    370         SetScrollPos(SB_HORZ, beginSample); 
    371  
    372         RedrawWindow(0, 0, RDW_INVALIDATE|RDW_UPDATENOW); 
     410} 
     411 
     412void CWaveEditorCtrl::setZoomDisplay(double beginSample, long numSamples) { 
     413 
     414        if (beginSample < 0) beginSample = 0; 
     415 
     416        if (beginSample + numSamples > waveInfo.samples) { 
     417                if (numSamples > waveInfo.samples) numSamples = waveInfo.samples; 
     418                beginSample = waveInfo.samples - numSamples; 
     419        } 
     420 
     421        beginDisplaySample = beginSample; 
     422        numDisplaySamples = numSamples; 
     423     
     424        updateScrollbars(); 
     425 
     426        Invalidate(FALSE); 
    373427} 
    374428 
     
    376430        ReleaseCapture(); 
    377431 
    378         wave_info_ex* wave = getWave(); 
    379         if (wave == 0) return 0; 
    380  
    381432        if (moveType == MoveLoopStart || moveType == MoveLoopEnd ) { 
    382                 view->setLoopingPoints(true, beginLoop, endLoop); 
     433                // notify parent 
     434                GetParent().SendMessage(WM_COMMAND, MAKELONG(GetDlgCtrlID(), WEN_LOOPCHANGED), (LPARAM)m_hWnd); 
    383435        } 
    384436 
     
    393445        GetClientRect(&rc); 
    394446 
    395         if (moveType==MoveLoopStart) { 
    396                 beginLoop=beginDisplaySample+(float)pt.x*paintDelta; 
    397                 if (beginLoop<beginDisplaySample) 
    398                         beginLoop=beginDisplaySample; 
    399                 if (beginLoop>endDisplaySample+1) 
    400                         beginLoop=endDisplaySample+1; 
    401                 RedrawWindow(0, 0, RDW_INVALIDATE|RDW_UPDATENOW); 
     447        unsigned int notificationCode; 
     448 
     449        if (moveType == MoveLoopStart) { 
     450                waveInfo.beginLoop = beginDisplaySample + (double)pt.x * paintDelta; 
     451                if (waveInfo.beginLoop < beginDisplaySample) 
     452                        waveInfo.beginLoop = beginDisplaySample; 
     453                if (waveInfo.beginLoop > beginDisplaySample + numDisplaySamples) 
     454                        waveInfo.beginLoop = beginDisplaySample + numDisplaySamples; 
     455                 
     456                notificationCode = WEN_LOOPCHANGED; 
    402457        } else 
    403         if (moveType==MoveLoopEnd) { 
    404                 endLoop=beginDisplaySample+(float)pt.x*paintDelta; 
    405                 if (endLoop<beginDisplaySample) 
    406                         endLoop=beginDisplaySample; 
    407                 if (endLoop>endDisplaySample+1) 
    408                         endLoop=endDisplaySample+1; 
    409                 RedrawWindow(0, 0, RDW_INVALIDATE|RDW_UPDATENOW); 
     458        if (moveType == MoveLoopEnd) { 
     459                waveInfo.endLoop = beginDisplaySample + (double)(pt.x) * paintDelta; 
     460                if (waveInfo.endLoop < 0) 
     461                        waveInfo.endLoop = 0; 
     462                if (waveInfo.endLoop > waveInfo.samples) 
     463                        waveInfo.endLoop = waveInfo.samples; 
     464                notificationCode = WEN_LOOPCHANGED; 
    410465        } else 
    411         if (moveType==MoveSelection) { 
    412                 endSelectSample=(beginDisplaySample+(float)pt.x*paintDelta); 
    413                 if (endSelectSample>endDisplaySample) 
    414                         endSelectSample=endDisplaySample; 
    415                 if (endSelectSample<0) 
    416                         endSelectSample=0; 
    417                 RedrawWindow(0, 0, RDW_INVALIDATE|RDW_UPDATENOW); 
     466        if (moveType == MoveSelection) { 
     467                lastSelectSample = (beginDisplaySample+(float)pt.x*paintDelta); 
     468                sortSelection(); 
     469                notificationCode = WEN_SELECTIONCHANGED; 
     470        } else { 
     471                notificationCode = WEN_MOUSEMOVE; 
    418472        } 
    419473 
    420474        currentCursorSamplePosition = beginDisplaySample+(float)pt.x*paintDelta;  
    421         view->bindStatus();                                      
     475        if (currentCursorSamplePosition < 0) currentCursorSamplePosition = 0; 
     476        if (currentCursorSamplePosition >= waveInfo.samples) currentCursorSamplePosition = waveInfo.samples - 1; 
     477 
     478        GetParent().SendMessage(WM_COMMAND, MAKELONG(GetDlgCtrlID(), notificationCode), (LPARAM)m_hWnd); 
     479 
     480        if (notificationCode != WEN_MOUSEMOVE) Invalidate(FALSE); 
    422481 
    423482        return 0; 
     
    426485 
    427486LRESULT CWaveEditorCtrl::OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) { 
     487        updateScrollbars(); 
    428488        return 0; 
    429489}