//--------------------------------------------------------------------------- #include #pragma hdrstop #include // for : malloc & free #include "Main.h" /****************************************************************************} {* For conditions of distribution and use, *} {* see copyright notice in libmng.pas *} {****************************************************************************} {* *} {* project : libmng *} {* file : main.pas copyright (c) 2000 G.Juyn *} {* version : 1.0.1 *} {* *} {* purpose : Main form for mngview application *} {* *} {* author : G.Juyn *} {* web : http://www.3-t.com *} {* email : mailto:info@3-t.com *} {* *} {* comment : this is the heart of the mngview applciation *} {* *} {* changes : This project is a converted version of "mngview" - AP *} {* - AP - 15/9/2000 - revisions ... *} {* - made the callbacks calling convention explicit *} (* - Moved the defines from "project options" to "main.h" *} {* - Added Readme.txt to the project - Please READ IT ! *} (* *} {* 0.5.1 - 05/02/2000 - G.Juyn *} {* - added this version block *} {* - made the initialization part more robust *} {* eg. program aborts on initialization errors *} {* - B002(105797) - added check for existence of default sRGB *} {* profile (now included in distribution) *} {* - added mng_cleanup to program exit *} {* 0.5.1 - 05/08/2000 - G.Juyn *} {* - changed to stdcall convention *} {* 0.5.1 - 05/11/2000 - G.Juyn *} {* - changed callback function declarations *} {* *} {* 0.5.3 - 06/16/2000 - G.Juyn *} {* - removed processmessages call from refresh callback *} {* 0.5.3 - 06/17/2000 - G.Juyn *} {* - switched "storechunks" off *} {* 0.5.3 - 06/26/2000 - G.Juyn *} {* - changed definition of userdata to mng_ptr *} {* 0.5.3 - 06/28/2000 - G.Juyn *} {* - changed the default icon to something more appropriate *} {* - changed definition of memory alloc size to mng_size_t *} {* 0.5.3 - 06/29/2000 - G.Juyn *} {* - changed order of refresh parameters *} {* *} {* 0.9.0 - 06/30/2000 - G.Juyn *} {* - changed refresh parameters to 'x,y,width,height' *} {* *} {* 0.9.1 - 07/08/2000 - G.Juyn *} {* - fixed to use returncode constants *} {* - changed to accomodate MNG_NEEDTIMERWAIT returncode *} {* 0.9.1 - 07/10/2000 - G.Juyn *} {* - changed to use suspension-mode *} {* *} {* 1.0.1 - 05/02/2000 - G.Juyn *} {* - removed loading of default sRGB profile (auto in libmng) *} {* *} {****************************************************************************/ //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TMainForm *MainForm; # define _OR_ | # define _AND_ & # define _DIV_ / # define _NOT_ ! # define _NIL_ 0 # define _SHR_ >> # define _SHL_ << // Prototypes for static functions - the LibMng Callbacks. static mng_ptr __stdcall Memalloc( mng_uint32 iLen ); static void __stdcall Memfree( mng_ptr iPtr, mng_size_t iLen ); static mng_bool __stdcall Openstream( mng_handle hHandle ); static mng_bool __stdcall Closestream( mng_handle hHandle ); static mng_bool __stdcall Readdata ( mng_handle hHandle, mng_ptr pBuf, mng_uint32 iBuflen, mng_uint32 *pRead ); static mng_bool __stdcall ProcessHeader ( mng_handle hHandle, mng_uint32 iWidth, mng_uint32 iHeight ); static mng_ptr __stdcall GetCanvasLine ( mng_handle hHandle, mng_uint32 iLinenr ); static mng_ptr __stdcall GetAlphaLine( mng_handle hHandle, mng_uint32 iLinenr ); static mng_bool __stdcall ImageRefresh ( mng_handle hHandle, mng_uint32 iX, mng_uint32 iY, mng_uint32 iWidth, mng_uint32 iHeight ); static mng_uint32 __stdcall GetTickCount( mng_handle hHandle ); static mng_bool __stdcall SetTimer( mng_handle hHandle, mng_uint32 iMsecs ); //--------------------------------------------------------------------------- __fastcall TMainForm::TMainForm(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- static mng_ptr __stdcall Memalloc( mng_uint32 iLen ) { mng_ptr pResult = malloc( iLen ); /* get memory from the heap */ if( pResult ) /* Added - condition */ memset( pResult, 0, iLen ); return pResult; } //--------------------------------------------------------------------------- static void __stdcall Memfree( mng_ptr iPtr, mng_size_t iLen ) { free( iPtr ); /* free the memory */ (void)iLen; // Kill compiler warning } //--------------------------------------------------------------------------- static mng_bool __stdcall Openstream( mng_handle hHandle ) { TMainForm *OHForm; /* get a fix on our form */ OHForm = (TMainForm *)mng_get_userdata( hHandle ); if( OHForm->OFFile != _NIL_ ) /* free previous stream (if any) */ OHForm->OFFile->Free(); /* open a new stream */ OHForm->OFFile = new TFileStream( OHForm->SFFileName, fmOpenRead _OR_ fmShareDenyWrite); OHForm->ProgressBar1->Position = 0; /* Added */ OHForm->ProgressBar1->Min =0; /* Added */ OHForm->ProgressBar1->Max = OHForm->OFFile->Size; /* Added */ return MNG_TRUE; } //--------------------------------------------------------------------------- static mng_bool __stdcall Closestream( mng_handle hHandle ) { TMainForm *OHForm; /* get a fix on our form */ OHForm = (TMainForm *)mng_get_userdata( hHandle ); OHForm->OFFile->Free(); /* cleanup the stream */ OHForm->OFFile = 0; /* don't use it again ! */ OHForm->ProgressBar1->Position = 0; /* Added */ return MNG_TRUE; } //--------------------------------------------------------------------------- static mng_bool __stdcall Readdata ( mng_handle hHandle, mng_ptr pBuf, mng_uint32 iBuflen, mng_uint32 *pRead ) { TMainForm *OHForm; unsigned int IHTicks; unsigned int IHByte1; unsigned int IHByte2; unsigned int IHBytesPerSec ; /* get a fix on our form */ OHForm = (TMainForm *)mng_get_userdata( hHandle ); /* are we at EOF ? */ if( OHForm->OFFile->Position >= OHForm->OFFile->Size ) { *pRead = 0; /* indicate so */ } else { IHBytesPerSec = OHForm->IFBytesPerSec; /* fake a slow connection */ if( IHBytesPerSec > 0 ) { IHTicks = (unsigned int)GetTickCount(); IHByte1 = (IHTicks - OHForm->IFTicks) * IHBytesPerSec; IHByte2 = (OHForm->IFBytes + iBuflen) * 1000; if( IHByte2 > IHByte1 ) /* Added - condition */ if( ((IHByte2 - IHByte1) _DIV_ IHBytesPerSec) > 10 ) { Sleep( (DWORD)((IHByte2 - IHByte1) _DIV_ IHBytesPerSec) ); } }; /* read the requested data */ *pRead = OHForm->OFFile->Read( pBuf, iBuflen); OHForm->IFBytes = OHForm->IFBytes + *pRead; OHForm->ProgressBar1->Position = (int)OHForm->IFBytes; /* Added */ } // end else; return MNG_TRUE; } //--------------------------------------------------------------------------- static mng_bool __stdcall ProcessHeader ( mng_handle hHandle, mng_uint32 iWidth, mng_uint32 iHeight ) { TMainForm *OHForm; /* get a fix on our form */ OHForm = (TMainForm *)mng_get_userdata( hHandle ); /* Added */ OHForm->Caption = ExtractFileName( OHForm->SFFileName ) + " [" + String( iWidth ) + "x" + String( iHeight ) + "]"; OHForm->OFBitmap->Width = iWidth; /* store the new dimensions */ OHForm->OFBitmap->Height = iHeight; OHForm->OFImage->Left = 0; /* adjust the visible component */ OHForm->OFImage->Top = 0; OHForm->OFImage->Width = iWidth; OHForm->OFImage->Height = iHeight; OHForm->FormResize (OHForm); /* force re-centering the image*/ /* clear the canvas & draw an outline */ OHForm->OFBitmap->Canvas->Brush->Color = clGray; OHForm->OFBitmap->Canvas->Brush->Style = bsSolid; OHForm->OFBitmap->Canvas->FillRect( OHForm->OFBitmap->Canvas->ClipRect ); OHForm->OFBitmap->Canvas->Brush->Color = clRed; OHForm->OFBitmap->Canvas->Brush->Style = bsSolid; OHForm->OFBitmap->Canvas->Pen->Color = clRed; OHForm->OFBitmap->Canvas->Pen->Style = psSolid; OHForm->OFBitmap->Canvas->FrameRect( OHForm->OFBitmap->Canvas->ClipRect); /* make sure it gets out there */ OHForm->OFImage->Picture->Assign( OHForm->OFBitmap ); /* tell the library we want funny windows-bgr*/ if( mng_set_canvasstyle( hHandle, MNG_CANVAS_BGR8 ) ) OHForm->MNGerror( "libmng reported an error setting the canvas style" ); return MNG_TRUE; } //--------------------------------------------------------------------------- static mng_ptr __stdcall GetCanvasLine ( mng_handle hHandle, mng_uint32 iLinenr ) { TMainForm *OHForm; /* get a fix on our form */ OHForm = (TMainForm *)mng_get_userdata( hHandle ); /* easy with these bitmap objects ! */ return OHForm->OFBitmap->ScanLine[ iLinenr ]; } //--------------------------------------------------------------------------- static mng_bool __stdcall ImageRefresh ( mng_handle hHandle, mng_uint32 iX, mng_uint32 iY, mng_uint32 iWidth, mng_uint32 iHeight ) { TMainForm *OHForm; /* get a fix on our form */ OHForm = (TMainForm *)mng_get_userdata( hHandle ); /* force redraw */ OHForm->OFImage->Picture->Assign( OHForm->OFBitmap ); return MNG_TRUE; } //--------------------------------------------------------------------------- static mng_uint32 __stdcall GetTickCount( mng_handle hHandle ) { return GetTickCount(); /* windows knows that */ } //--------------------------------------------------------------------------- static mng_bool __stdcall SetTimer( mng_handle hHandle, mng_uint32 iMsecs ) { TMainForm *OHForm; /* get a fix on our form */ OHForm = (TMainForm *)mng_get_userdata( hHandle ); OHForm->OFTimer->Interval = iMsecs; /* and set the timer */ OHForm->OFTimer->Enabled = true; return MNG_TRUE; } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- void __fastcall TMainForm::FormCreate(TObject *Sender) { String SHProfileName; mng_uint16 IHRed, IHGreen, IHBlue; /* word */ OFBitmap = new Graphics::TBitmap(); /* initialize */ IFBytesPerSec = 10000000; OFFile = 0; OFOpenDialog->InitialDir = ""; OFBitmap->HandleType = bmDIB; /* make it a 24-bit DIB */ OFBitmap->PixelFormat = pf24bit; /* now initialize the library */ IFHandle = mng_initialize( mng_ptr(this), Memalloc, Memfree, _NIL_ ); if( IFHandle == _NIL_ ) { MNGerror ("libmng initializiation error"\ "\n"\ "Program aborted" ); PostMessage( Handle, WM_CLOSE, 0, 0); return; // was Exit }; /* no need to store chunk-info ! */ mng_set_storechunks( IFHandle, MNG_FALSE ); /* use suspension-buffer */ mng_set_suspensionmode( IFHandle, MNG_TRUE ); /* set all the callbacks */ if( (mng_setcb_openstream (IFHandle, Openstream ) != MNG_NOERROR) _OR_ (mng_setcb_closestream (IFHandle, Closestream ) != MNG_NOERROR) _OR_ (mng_setcb_readdata (IFHandle, Readdata ) != MNG_NOERROR) _OR_ (mng_setcb_processheader(IFHandle, ProcessHeader) != MNG_NOERROR) _OR_ (mng_setcb_getcanvasline(IFHandle, GetCanvasLine) != MNG_NOERROR) _OR_ (mng_setcb_refresh (IFHandle, ImageRefresh ) != MNG_NOERROR) _OR_ (mng_setcb_gettickcount (IFHandle, GetTickCount ) != MNG_NOERROR) _OR_ (mng_setcb_settimer (IFHandle, SetTimer ) != MNG_NOERROR) ) { MNGerror ("libmng reported an error setting a callback function!"\ "\n"\ "Program aborted" ); PostMessage( Handle, WM_CLOSE, 0, 0 ); return; // was Exit }; /* supply our own bg-color */ IHRed = (mng_uint16)((Color ) _AND_ 0xFF); IHGreen = (mng_uint16)((Color _SHR_ 8) _AND_ 0xFF); IHBlue = (mng_uint16)((Color _SHR_ 16) _AND_ 0xFF); IHRed = (mng_uint16)((IHRed _SHL_ 8) + IHRed); IHGreen = (mng_uint16)((IHGreen _SHL_ 8) + IHGreen); IHBlue = (mng_uint16)((IHBlue _SHL_ 8) + IHBlue); if( mng_set_bgcolor (IFHandle, IHRed, IHGreen, IHBlue) != MNG_NOERROR ) MNGerror( "libmng reported an error setting the background color!"); } //--------------------------------------------------------------------------- void __fastcall TMainForm::FormCloseQuery(TObject *Sender, bool &CanClose) { BFCancelled = true; /* if we're still animating then stop it */ if( OFTimer->Enabled ) { if( mng_display_freeze (IFHandle) != MNG_NOERROR ) MNGerror ("libmng reported an error during display_freeze!" ); } OFTimer->Enabled = false; mng_cleanup( &IFHandle ); } //--------------------------------------------------------------------------- void __fastcall TMainForm::FormShow(TObject *Sender) { FormResize( this ); } //--------------------------------------------------------------------------- void __fastcall TMainForm::FormResize(TObject *Sender) { /* center the image in the window */ if( ClientWidth < OFImage->Width ) OFImage->Left = 0; else OFImage->Left = (ClientWidth - OFImage->Width ) _DIV_ 2; if( ClientHeight < OFImage->Height ) OFImage->Top = 0; else OFImage->Top = (ClientHeight - OFImage->Height) _DIV_ 2; ProgressBar1->Width = Panel1->Width - 8; /* Added */ } //--------------------------------------------------------------------------- void __fastcall TMainForm::FormKeyDown(TObject *Sender, WORD &Key, TShiftState Shift) { /* pressing will freeze an animation */ if( Key == VK_ESCAPE ) { if( OFTimer->Enabled ) { if( mng_display_freeze( IFHandle) != MNG_NOERROR ) MNGerror( "libmng reported an error during display_freeze!" ); } OFTimer->Enabled = false; /* don't let that timer go off then ! */ BFCancelled = true; } } //--------------------------------------------------------------------------- void __fastcall TMainForm::OFTimerTimer(TObject *Sender) { mng_retcode IHRslt; OFTimer->Enabled = false; /* only once ! */ if( _NOT_ BFCancelled ) { /* and inform the library */ IHRslt = mng_display_resume( IFHandle ); if( (IHRslt != MNG_NOERROR) _AND_ (IHRslt != MNG_NEEDTIMERWAIT) ) MNGerror( "libmng reported an error during display_resume!" ); }; } //--------------------------------------------------------------------------- void __fastcall TMainForm::OFMenuFileOpenClick(TObject *Sender) { mng_retcode IHRslt; OFOpenDialog->InitialDir = ""; OFOpenDialog->InitialDir = GetCurrentDir(); //@@ OFOpenDialog->FileName = SFFileName; if( OFOpenDialog->Execute() ) /* get the filename */ { if( OFTimer->Enabled ) /* if the lib was active; stop it */ { OFTimer->Enabled = false; Application->ProcessMessages(); /* process any timer requests (for safety) */ /* now freeze the animation */ if( mng_display_freeze( IFHandle ) != MNG_NOERROR ) MNGerror( "libmng reported an error during display_freeze!" ); }; /* save interesting fields */ SFFileName = OFOpenDialog->FileName; IFTicks = GetTickCount(); IFBytes = 0; BFCancelled = false; /* always reset (just in case) */ if( mng_reset( IFHandle ) != MNG_NOERROR ) { MNGerror( "libmng reported an error during reset!" ); } else { /* and let the lib do it's job ! */ IHRslt = mng_readdisplay (IFHandle); if( (IHRslt != MNG_NOERROR) _AND_ (IHRslt != MNG_NEEDTIMERWAIT) ) MNGerror( "libmng reported an error reading the input file!" ); }; }; } //--------------------------------------------------------------------------- void __fastcall TMainForm::OFMenuFileProfileClick(TObject *Sender) { char SHProfileDir[ MAX_PATH ]; GetSystemDirectory( SHProfileDir, MAX_PATH ); strcat( SHProfileDir, "\\Color" ); OFOpenDialogProfile->InitialDir = String( SHProfileDir ); if( OFOpenDialogProfile->Execute() ) { if( mng_set_outputprofile( IFHandle, OFOpenDialogProfile->FileName.c_str()) != 0 ) MNGerror( "libmng reported an error setting the output-profile!" ); } } //--------------------------------------------------------------------------- void __fastcall TMainForm::OFMenuFileExitClick(TObject *Sender) { if( mng_cleanup( &IFHandle ) != MNG_NOERROR ) MNGerror( "libmng cleanup error" ); Close(); } //--------------------------------------------------------------------------- void __fastcall TMainForm::OFMenuOptionsModemSpeedClick(TObject *Sender) { OFMenuOptionsModem28k8->Checked = false; OFMenuOptionsModem33k6->Checked = false; OFMenuOptionsModem56k->Checked = false; OFMenuOptionsModemISDN64->Checked = false; OFMenuOptionsModemISDN128->Checked = false; OFMenuOptionsModemCable512->Checked = false; OFMenuOptionsModemUnlimited->Checked = false; if( IFBytesPerSec == (unsigned int)OFMenuOptionsModem28k8->Tag _DIV_ 10 ) OFMenuOptionsModem28k8->Checked = true; else if( IFBytesPerSec == (unsigned int)OFMenuOptionsModem33k6->Tag _DIV_ 10 ) OFMenuOptionsModem33k6->Checked = true; else if( IFBytesPerSec == (unsigned int)OFMenuOptionsModem56k->Tag _DIV_ 10 ) OFMenuOptionsModem56k->Checked = true; else if( IFBytesPerSec == (unsigned int)OFMenuOptionsModemISDN64->Tag _DIV_ 10 ) OFMenuOptionsModemISDN64->Checked = true; else if( IFBytesPerSec == (unsigned int)OFMenuOptionsModemISDN128->Tag _DIV_ 10 ) OFMenuOptionsModemISDN128->Checked = true; else /* Added - changedit was the line below ! */ // if( IFBytesPerSec == (unsigned int)OFMenuOptionsModemUnlimited->Tag _DIV_ 10 ) if( IFBytesPerSec == (unsigned int)OFMenuOptionsModemCable512->Tag _DIV_ 10 ) OFMenuOptionsModemCable512->Checked = true; else OFMenuOptionsModemUnlimited->Checked = true; } //--------------------------------------------------------------------------- void __fastcall TMainForm::OFMenuOptionsModemXClick(TObject *Sender) { IFBytesPerSec = ((TMenuItem*)Sender)->Tag _DIV_ 10; } //--------------------------------------------------------------------------- void TMainForm::MNGerror( String SHMsg ) { /* get extended info */ mng_uint32 iErrorcode; mng_uint8 iSeverity; mng_chunkid iChunkname; mng_uint32 iChunkseq; mng_int32 iExtra1; mng_int32 iExtra2; mng_pchar zErrortext; char szFormatStr[ 256 ]; iErrorcode = mng_getlasterror (IFHandle, &iSeverity, &iChunkname, &iChunkseq, &iExtra1, &iExtra2, (mng_pchar*)&zErrortext); wsprintf( szFormatStr, "Error = %d; Severity = %d; Chunknr = %d; Extra1 = %d", (int)iErrorcode, (int)iSeverity, (int)iChunkseq, (int)iExtra1 ); MessageDlg( SHMsg + "\n\n" + String(zErrortext) + "\n\n" + szFormatStr, /* see wsprintf above */ mtError, TMsgDlgButtons() << mbOK, 0 ); } //---------------------------------------------------------------------------