//+--------------------------------------------------------------------------- // // Member: CScrollbar::GetThumbSize // // Synopsis: Calculate the thumb size given the adjusted button width. // // Arguments: direction 0 for horizontal scroll bar, 1 for vertical // rcScrollbar scroll bar bounds // contentSize size of content controlled by scroll bar // containerSize size of container // buttonWidth width of scroll bar buttons // // Returns: width of thumb in pixels // // Notes: // //---------------------------------------------------------------------------- long CScrollbar::GetThumbSize( int direction, const CRect& rcScrollbar, long contentSize, long containerSize, long buttonWidth, CDrawInfo* pDI) { long thumbSize = 0; long trackSize = GetTrackSize(direction, rcScrollbar, buttonWidth); // minimum thumb size is 8 points for // compatibility with IE4. // [alanau] For some reason, I can't put two ternery expressions in a "max()", so it's coded this clumsy way: if(contentSize) { thumbSize = max( (direction==0 ?pDI->WindowFromDocumentCX(HIMETRIC_PER_INCH*8/72) :pDI->WindowFromDocumentCY(HIMETRIC_PER_INCH*8/72)), trackSize*containerSize/contentSize); } else { // Avoid divide-by-zero fault. thumbSize = direction==0 ? pDI->WindowFromDocumentCX(HIMETRIC_PER_INCH*8/72) : pDI->WindowFromDocumentCY(HIMETRIC_PER_INCH*8/72); } return (thumbSize<=trackSize?thumbSize:0); }
int Waveform::GetLengthOfMusicFileInMS(const wxString &filename) { mpg123_handle *mh; int err; int channels, encoding; long rate; mpg123_init(); mh = mpg123_new(NULL, &err); /* open the file and get the decoding format */ mpg123_open(mh, filename.c_str()); mpg123_getformat(mh, &rate, &channels, &encoding); int bits = mpg123_encsize(encoding); /* Get Track Size */ int trackSize = GetTrackSize(mh,bits,channels); mpg123_close(mh); mpg123_delete(mh); mpg123_exit(); float seconds = (float)trackSize * ((float)1/(float)rate); return (int)(seconds * (float)1000); }
// Open Media file and return elapsed time in millseconds int Waveform::OpenfileMediaFile(const wxString &filename, wxString& error) { mpg123_handle *mh = NULL; int err; size_t buffer_size; int channels, encoding; long rate; err = mpg123_init(); if(err != MPG123_OK || (mh = mpg123_new(NULL, &err)) == NULL) { error = wxString::Format("Basic setup goes wrong: %s", mpg123_plain_strerror(err)); if (mh != NULL) { cleanup(mh); } return -1; } /* open the file and get the decoding format */ if( mpg123_open(mh, filename.c_str()) != MPG123_OK || mpg123_getformat(mh, &rate, &channels, &encoding) != MPG123_OK ) { error = wxString::Format("Trouble with mpg123: %s", mpg123_strerror(mh)); cleanup(mh); return -1; } if( encoding != MPG123_ENC_SIGNED_16 ) { error = "Encoding unsupported. Must be signed 16 bit."; cleanup(mh); return -2; } /* set the output format and open the output device */ m_bits = mpg123_encsize(encoding); m_rate = rate; m_channels = channels; /* Get Track Size */ mMediaTrackSize = GetTrackSize(mh,m_bits,m_channels); buffer_size = mpg123_outblock(mh); int size = (mMediaTrackSize+buffer_size)*m_bits*m_channels; char * trackData = (char*)malloc(size); LoadTrackData(mh,trackData, size); // Split data into left and right and normalize -1 to 1 m_left_data = (float*)malloc(sizeof(float)*mMediaTrackSize); if( m_channels == 2 ) { m_right_data = (float*)malloc(sizeof(float)*mMediaTrackSize); SplitTrackDataAndNormalize((signed short*)trackData,mMediaTrackSize,m_left_data,m_right_data); } else if( m_channels == 1 ) { NormalizeMonoTrackData((signed short*)trackData,mMediaTrackSize,m_left_data); } else { error = "More than 2 audio channels is not supported yet."; } views.clear(); float samplesPerLine = GetSamplesPerLineFromZoomLevel(mZoomLevel); WaveView wv(mZoomLevel,samplesPerLine,m_left_data,mMediaTrackSize); views.push_back(wv); mCurrentWaveView = 0; mpg123_close(mh); mpg123_delete(mh); mpg123_exit(); free(trackData); float seconds = (float)mMediaTrackSize * ((float)1/(float)rate); mAudioIsLoaded = true; return (int)(seconds * (float)1000); }
//+--------------------------------------------------------------------------- // // Member: CScrollbarController::MouseMove // // Synopsis: Handle mouse move events. // // Arguments: pt new mouse location // // Notes: // //---------------------------------------------------------------------------- void CScrollbarController::MouseMove(const CPoint& pt) { _ptMouse = pt; _pDispScroller->TransformPoint(&_ptMouse, COORDSYS_GLOBAL, COORDSYS_CONTAINER); switch(_partPressedStart) { case SBP_NONE: case SBP_TRACK: AssertSz(FALSE, "unexpected call to CScrollbarController::MouseMoved"); break; case SBP_THUMB: { LONG contentSize = _pDispScroller->GetContentSize()[_direction]; Assert(contentSize >= 0); LONG trackSize = GetTrackSize(_direction, _rcScrollbar, _buttonWidth) - GetThumbSize(_direction, _rcScrollbar, contentSize, _rcScrollbar.Size(_direction), _buttonWidth, &_drawInfo); if(trackSize <= 0) { break; // can't move thumb } // NOTE: we're not currently checking to see if the mouse point // is out of range perpendicular to the scroll bar axis BOOL fRightToLeft = (_direction==0 && _pDispScroller->IsRightToLeft()); LONG trackPos; if(!fRightToLeft) { trackPos = _ptMouse[_direction] - _rcScrollbar[_direction] - GetScaledButtonWidth(_direction, _rcScrollbar, _buttonWidth) - _mouseInThumb; } else { trackPos = _rcScrollbar.right - GetScaledButtonWidth(_direction, _rcScrollbar, _buttonWidth) - _mouseInThumb - _ptMouse.x; } LONG scrollOffset; if(trackPos <= 0) { scrollOffset = 0; } else { contentSize -= _rcScrollbar.Size(_direction); scrollOffset = MulDivQuick(trackPos, contentSize, trackSize); if(fRightToLeft) { scrollOffset = -scrollOffset; } } _pLayout->OnScroll(_direction, SB_THUMBPOSITION, scrollOffset); } break; default: { // find out what the mouse would be pressing in its new location. // If it's not the same as it used to be, invalidate the part. SCROLLBARPART partPressedOld = _partPressed; LONG contentSize, containerSize, scrollAmount; GetScrollInfo(&contentSize, &containerSize, &scrollAmount); _partPressed = GetPart( _direction, _rcScrollbar, _ptMouse, contentSize, containerSize, scrollAmount, _buttonWidth, &_drawInfo, _pDispScroller->IsRightToLeft()); if(_partPressed != _partPressedStart) { _partPressed = SBP_NONE; } if(_partPressed != partPressedOld) { SCROLLBARPART invalidPart = _partPressed; if(_partPressed != SBP_NONE) { // perform scroll action and set timer OnTick(SB_REPEAT_TIMER); } else { invalidPart = partPressedOld; } Verify(_pLayout->OpenView()); InvalidatePart( invalidPart, _direction, _rcScrollbar, contentSize, containerSize, scrollAmount, _buttonWidth, _pDispScroller, &_drawInfo); } } break; } }
//+--------------------------------------------------------------------------- // // Member: CScrollbarController::StartScrollbarController // // Synopsis: Start a scroll bar controller if necessary. // // Arguments: pLayout layout object to be called on scroll changes // pDispScroller display scroller node // pServerHost server host // buttonWidth custom scroll bar button width // pMessage message that caused creation of controller // // Notes: // //---------------------------------------------------------------------------- void CScrollbarController::StartScrollbarController( CLayout* pLayout, CDispScroller* pDispScroller, CServer* pServerHost, long buttonWidth, CMessage* pMessage) { Assert(pLayout != NULL); Assert(pDispScroller != NULL); Assert(pServerHost != NULL); Assert(pMessage != NULL); BOOL fRightToLeft; CScrollbarController* pSBC = TLS(pSBC); Assert(pSBC != NULL); // just to make sure previous controller is stopped if(pSBC->_pLayout != NULL) { StopScrollbarController(); } pSBC->_direction = (pMessage->htc==HTC_HSCROLLBAR ? 0 : 1); pSBC->_pDispScroller = pDispScroller; pSBC->_drawInfo.Init(pLayout->ElementOwner()); fRightToLeft = (pSBC->_direction==0 && pDispScroller->IsRightToLeft()); // calculate scroll bar rect pDispScroller->GetClientRect( &pSBC->_rcScrollbar, (pSBC->_direction==0?CLIENTRECT_HSCROLLBAR:CLIENTRECT_VSCROLLBAR)); Assert(pSBC->_rcScrollbar.Contains(pMessage->ptContent)); LONG contentSize, containerSize, scrollAmount; pSBC->GetScrollInfo(&contentSize, &containerSize, &scrollAmount); // if the scrollbar is inactive, it doesn't matter what was pressed if(contentSize <= containerSize) { return; } // what was pressed? pSBC->_partPressed = GetPart( pSBC->_direction, pSBC->_rcScrollbar, pMessage->ptContent, contentSize, containerSize, scrollAmount, buttonWidth, pSBC->GetDrawInfo(), pDispScroller->IsRightToLeft()); Assert(pSBC->_partPressed != SBP_NONE); // if inactive track was pressed, no more work to do if(pSBC->_partPressed == SBP_TRACK) { return; } // make scroll bar controller active pSBC->_partPressedStart = pSBC->_partPressed; pSBC->_pLayout = pLayout; pSBC->_pDispScroller = pDispScroller; pSBC->_pServerHost = pServerHost; pSBC->_buttonWidth = buttonWidth; pSBC->_ptMouse = pMessage->ptContent; LONG lScrollTime = MAX_SCROLLTIME; // if thumbing, compute hit point offset from top of thumb if(pSBC->_partPressed == SBP_THUMB) { long trackSize = GetTrackSize( pSBC->_direction, pSBC->_rcScrollbar, pSBC->_buttonWidth); long thumbSize = GetThumbSize( pSBC->_direction, pSBC->_rcScrollbar, contentSize, containerSize, pSBC->_buttonWidth, pSBC->GetDrawInfo()); // _mouseInThumb is the xPos of the mouse in from the left edge of the thumb in LTR cases // and xPos of the mouse in from the right edge of the thumb in RTL HSCROLL cases if(!fRightToLeft) { pSBC->_mouseInThumb = pSBC->_ptMouse[pSBC->_direction] - pSBC->_rcScrollbar[pSBC->_direction] - GetScaledButtonWidth(pSBC->_direction, pSBC->_rcScrollbar, pSBC->_buttonWidth) - GetThumbOffset(contentSize, containerSize, scrollAmount, trackSize, thumbSize); } else { pSBC->_mouseInThumb = pSBC->_rcScrollbar.right - GetScaledButtonWidth(pSBC->_direction, pSBC->_rcScrollbar, pSBC->_buttonWidth) + GetThumbOffset(contentSize, containerSize, scrollAmount, trackSize, thumbSize) - pSBC->_ptMouse.x; } Assert(pSBC->_mouseInThumb >= 0); // no smooth scrolling lScrollTime = 0; } // capture the mouse HWND hwnd = pServerHost->_pInPlace->_hwnd; if(FAILED(GWSetCapture( pSBC, ONMESSAGE_METHOD(CScrollbarController, OnMessage, onmessage), hwnd))) { pSBC->_pLayout = NULL; return; } // set timer for repeating actions if(pSBC->_partPressed != SBP_THUMB) { // perform first action pLayout->OnScroll( pSBC->_direction, TranslateSBAction(pSBC->_partPressed), 0, FALSE, lScrollTime); CSize scrollOffset; pSBC->_pDispScroller->GetScrollOffset(&scrollOffset); scrollAmount = scrollOffset[pSBC->_direction]; // set timer for subsequent action FormsSetTimer( pSBC, ONTICK_METHOD(CScrollbarController, OnTick, ontick), SB_REPEAT_TIMER, GetRepeatDelay()); } // invalidate the part we hit, if necessary pLayout->OpenView(); InvalidatePart( pSBC->_partPressed, pSBC->_direction, pSBC->_rcScrollbar, contentSize, containerSize, scrollAmount, buttonWidth, pDispScroller, pSBC->GetDrawInfo()); }