home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga MA Magazine 1998 #6
/
amigamamagazinepolishissue1998.iso
/
cdrom
/
compactplayer
/
source
/
cdpanel.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-12-28
|
18KB
|
764 lines
/****** cdpanel_gc/--datasheet-- ******************************************
NAME
cdpanel.gadget -- CD front panel
SUPERCLASS
gadgetclass
DESCRIPTION
METHODS
GM_DOMAIN
GM_RENDER
GM_HITTEST
GM_GOACTIVE
GM_GOINACTIVE
OM_SET
OM_UPDATE
OM_GET
OM_NEW
OM_DISPOSE
All other methods are passed to the superclass.
ATTRIBUTES
NOTES
SEE ALSO
******************************************************************************
*/
#include "sysheaders.h"
#include "classdata.h"
#include "cdpanel.h"
static ULONG new_method( Class *cl, Object *o, struct opSet *ops);
static ULONG dispose_method( Class *cl, Object *o, Msg msg);
static ULONG set_method( Class *cl, Object *o, struct opSet *ops);
static ULONG get_method( Class *cl, Object *o, struct opGet *opg);
static ULONG render_method( Class *cl, Object *o, struct gpRender *gpr);
static ULONG domain_method( Class *cl, Object *o, struct gpDomain *gpd);
/* handy macro for handling tag data */
#define SETTAGARG(tag, id, data) { tag.ti_Tag = (ULONG)(id);\
tag.ti_Data = (ULONG)(data); }
/* prototype for external function from 'gadgetbox.asm' */
extern __stdargs void SetupGadgetIBox(
struct Gadget *gadget,
struct IBox *domain,
struct IBox *box);
/* prototype for LayoutClass */
static ULONG __saveds __asm CDPanelDispatch(
register __a0 Class * class,
register __a2 Object * object,
register __a1 Msg message);
void Sprintf(char *, const char *, ...);
#ifdef __SASC
#pragma msg 181 ign push
static struct ClassLibrary *BevelBase;
#pragma msg 181 pop
#else
static struct ClassLibrary *BevelBase;
#endif
ULONG
SendNotify(Object * o, struct GadgetInfo *gi, ULONG flags, Tag t,...)
{
return DoMethod(o, OM_NOTIFY, &t, gi, flags);
}
static ULONG __asm /* no __saveds necessary, this is called through the dispatcher anyway */
tagset(
register __a0 Class * cl,
register __a2 Object * o,
register __a1 struct opSet *ops)
{
struct CDPanelData *sd = INST_DATA(cl, o);
register ULONG tidata;
register BOOL ours;
BOOL refresh = FALSE;
struct TagItem *tag;
struct TagItem *tstate = ops->ops_AttrList;
if (sd)
{
while (tag = NextTagItem(&tstate))
{
tidata = tag->ti_Data;
ours = TRUE;
switch (tag->ti_Tag)
{
case CDPANEL_Artist:
sd->gad_Data[Artist] = tidata;
sd->gad_Old[Artist] = ~0;
break;
case CDPANEL_Title:
sd->gad_Data[Title] = tidata;
sd->gad_Old[Title] = ~0;
break;
case CDPANEL_TrackTitles:
sd->gad_TrackTitles = (STRPTR *)tidata;
break;
case CDPANEL_TotalTime:
sd->gad_Data[TotalTime] = tidata;
sd->gad_Old[TotalTime] = ~0;
break;
case CDPANEL_Time:
sd->gad_Data[Time] = tidata;
sd->gad_Old[Time] = ~0;
break;
case CDPANEL_Tracks:
sd->gad_Data[Tracks] = tidata;
sd->gad_Old[Tracks] = ~0;
break;
case CDPANEL_TrackTimes:
sd->gad_TrackTimes = (ULONG *)tidata;
break;
case CDPANEL_Track:
sd->gad_Old[Track] = sd->gad_Data[Track];
sd->gad_Data[Track] = tidata;
break;
case CDPANEL_TrackTime:
sd->gad_Data[TrackTime] = tidata;
sd->gad_Old[TrackTime] = ~0;
break;
case CDPANEL_Status:
if (tidata == CDP_EMPTY || tidata == CDP_EJECTED)
{
memset(sd->gad_Data, 0, sizeof(sd->gad_Data));
memset(sd->gad_Graph, sd->gad_BgPen, 320);
}
else
if (tidata == CDP_STOPPED && sd->gad_Data[Status] != tidata)
{
sd->gad_Data[Track] = 0;
sd->gad_Data[TrackTime] = 0;
sd->gad_Data[Time] = 0;
memset(sd->gad_Graph, sd->gad_BgPen, 320);
}
sd->gad_Data[Status] = tidata;
// sd->gad_Old[Status] = ~0;
break;
case CDPANEL_BgPen:
sd->gad_BgPen = (WORD)tidata;
break;
case CDPANEL_FgPen:
sd->gad_FgPen = (WORD)tidata;
break;
case CDPANEL_NoBorder:
sd->gad_NoBorder = (BOOL)tidata;
SetAttrs( sd->gad_BevelFrame, BEVEL_Style, sd->gad_NoBorder ? BVS_NONE : BVS_BUTTON, TAG_END );
break;
case GA_TextAttr:
if (sd->gad_Font)
CloseFont(sd->gad_Font);
sd->gad_Font = OpenFont((struct TextAttr *)tidata);
break;
default:
ours = FALSE;
break;
}
if (ours)
refresh = TRUE;
}
if (ops->ops_GInfo && refresh && AttemptLockLayerRom( ops->ops_GInfo->gi_Window->WLayer ) )
{
struct RastPort *rp;
UnlockLayerRom( ops->ops_GInfo->gi_Window->WLayer );
if (rp = ObtainGIRPort(ops->ops_GInfo))
{
DoMethod(o, GM_RENDER, ops->ops_GInfo, rp, GREDRAW_UPDATE);
ReleaseGIRPort(rp);
refresh = FALSE;
}
}
}
return refresh;
}
static void MyFreeBitMap( struct BitMap *bm )
{
if (!bm)
return;
if (GfxBase->LibNode.lib_Version >= 39)
{
FreeBitMap( bm );
}
else
{
if (bm->Planes[0])
FreeRaster( bm->Planes[0], bm->BytesPerRow<<3, bm->Rows * bm->Depth );
FreeMem( bm, sizeof(struct BitMap) );
}
}
static struct BitMap *MyAllocBitMap( UWORD w, UWORD h, UBYTE d, ULONG f, struct BitMap *fr )
{
if (GfxBase->LibNode.lib_Version >= 39)
{
return AllocBitMap( w, h, d, f, fr );
}
else
{
ULONG s = (((w+15)>>4)<<4);
UBYTE *r;
struct BitMap *bm = AllocMem( sizeof(struct BitMap), MEMF_PUBLIC );
if (!bm)
return NULL;
if (r = AllocRaster(s, h*d))
{
UBYTE p;
bm->BytesPerRow = s>>3;
bm->Rows = h;
bm->Depth = d;
bm->Flags = f;
if (!(f & BMF_INTERLEAVED))
s *= h;
for (p = 0; p < d; p++)
{
bm->Planes[p] = r;
r += s;
}
return bm;
}
bm->Planes[0] = NULL;
MyFreeBitMap(bm);
return NULL;
}
}
static ULONG
new_method(
Class * cl,
Object * o,
struct opSet *ops)
{
struct CDPanelData *sd;
Object *object;
object = (Object *) DoSuperMethodA(cl, o, (Msg) ops);
if (object)
{
sd = INST_DATA(cl, object);
if (sd->gad_Graph = AllocVec( 640, MEMF_CHIP ))
{
sd->gad_BgPen = 1;
sd->gad_FgPen = ~0;
memset(sd->gad_Graph, sd->gad_BgPen, 320);
tagset(cl, object, ops);
if (!sd->gad_Font)
sd->gad_Font = GfxBase->DefaultFont;
if (sd->gad_BevelFrame = NewObject( BEVEL_GetClass(), NULL, BEVEL_Style, sd->gad_NoBorder ? BVS_NONE : BVS_BUTTON, TAG_END ))
{
return ((ULONG)object);
}
}
CoerceMethod(cl, object, OM_DISPOSE);
}
return (0L);
}
static ULONG
dispose_method(
Class * cl,
Object * o,
Msg message)
{
struct CDPanelData *sd = INST_DATA(cl, o);
if (sd->gad_Font != GfxBase->DefaultFont)
CloseFont( sd->gad_Font );
DisposeObject(sd->gad_BevelFrame);
if (sd->gad_Graph)
FreeVec(sd->gad_Graph);
MyFreeBitMap(sd->gad_TempBitMap);
return DoSuperMethodA(cl, o, message);
}
static ULONG
set_method(
Class * cl,
Object * o,
struct opSet *ops)
{
register struct TagItem *tstate = ops->ops_AttrList;
if (tstate)
tagset(cl, o, ops);
DoSuperMethodA(cl, o, (Msg) ops);
return 0;
}
static ULONG
get_method(
Class * cl,
Object * o,
struct opGet *opg)
{
ULONG retval = TRUE;
struct CDPanelData *sd = INST_DATA(cl, o);
switch (opg->opg_AttrID)
{
case CDPANEL_Status:
*opg->opg_Storage = sd->gad_Data[Status];
break;
case CDPANEL_Track:
*opg->opg_Storage = sd->gad_Data[Track];
break;
default:
retval = DoSuperMethodA(cl, o, (Msg) opg);
break;
}
return (retval);
}
static ULONG
domain_method(
Class * cl,
Object * o,
struct gpDomain *gpd)
{
struct CDPanelData *sd = INST_DATA(cl, o);
ULONG t;
/* GM_DOMAIN is a V42 method for asking a gadget how much space it
* needs/prefers.
* This is a fixed size gadget, so we'll always return the same thing.
*/
gpd->gpd_Domain.Left = gpd->gpd_Domain.Top = 0;
gpd->gpd_Domain.Width = 26 * (sd->gad_Font->tf_XSize) + 2*(2 + 1);
gpd->gpd_Domain.Height = 3 * (sd->gad_Font->tf_YSize + 1) + 8 + 2*(2 + 1);
// if (!sd->gad_NoBorder)
// {
SetAttrs( sd->gad_BevelFrame,
IA_Width, gpd->gpd_Domain.Width,
IA_Height, gpd->gpd_Domain.Height,
TAG_END );
GetAttr( BEVEL_InnerWidth, sd->gad_BevelFrame, &t );
gpd->gpd_Domain.Width += gpd->gpd_Domain.Width - t;
GetAttr( BEVEL_InnerHeight, sd->gad_BevelFrame, &t );
gpd->gpd_Domain.Height += gpd->gpd_Domain.Height - t;
// }
return (0);
}
UBYTE IconPlaying[8] = { 0x40, 0x70, 0x7c, 0x7f, 0x7c, 0x70, 0x40, 0x00 };
UBYTE IconStopped[8] = { 0x00, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00 };
UBYTE IconEjected[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
UBYTE IconPaused[8] = { 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00 };
UBYTE IconEmpty[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
UBYTE IconSeeking[8] = { 0x38, 0x38, 0x38, 0xfe, 0x7c, 0x38, 0x10, 0x00 };
static void
DrawStatusIcon( struct RastPort *rp, UBYTE *icon, UWORD x, UWORD y )
{
UWORD i,j;
for (j = 0 ; j < 8 ; j++)
{
for (i = 0 ; i < 8 ; i++)
{
if (icon[j] & (1 << i))
WritePixel( rp, x+7-i, y+j);
}
}
}
static ULONG
render_method(
Class * cl,
Object * o,
struct gpRender *gpr)
{
struct CDPanelData *sd = INST_DATA(cl, o);
struct RastPort rpfg = *gpr->gpr_RPort, rpbg = *gpr->gpr_RPort;
UBYTE line[6];
ULONG X, Y;
ULONG *data = sd->gad_Data, *old = sd->gad_Old;
ULONG baseline = sd->gad_Font->tf_Baseline;
SetAPen( &rpbg, sd->gad_BgPen );
SetDrMd( &rpbg, JAM2 );
if (gpr->gpr_Redraw == GREDRAW_REDRAW)
{
ULONG W, H;
// struct impDraw id;
SetupGadgetIBox((struct Gadget *) o, &gpr->gpr_GInfo->gi_Domain, &sd->gad_Container);
if (!sd->gad_NoBorder)
{
#if 0
id.MethodID = IM_DRAWFRAME;
id.imp_RPort = &rpfg;
id.imp_Offset.X = sd->gad_Container.Left;
id.imp_Offset.Y = sd->gad_Container.Top;
id.imp_State = IDS_SELECTED;
id.imp_DrInfo = gpr->gpr_GInfo->gi_DrInfo;
id.imp_Dimensions.Width = sd->gad_Container.Width;
id.imp_Dimensions.Height = sd->gad_Container.Height;
DoMethodA( sd->gad_BevelFrame, (Msg)&id );
#else
SetAttrs( sd->gad_BevelFrame,
IA_Left, 0, IA_Top, 0,
IA_Width, sd->gad_Container.Width, IA_Height, sd->gad_Container.Height,
TAG_END );
DrawImageState( &rpfg, (struct Image *)sd->gad_BevelFrame, sd->gad_Container.Left, sd->gad_Container.Top, IDS_SELECTED, gpr->gpr_GInfo->gi_DrInfo );
#endif
GetAttr( BEVEL_InnerLeft, sd->gad_BevelFrame, &X );
GetAttr( BEVEL_InnerTop, sd->gad_BevelFrame, &Y );
GetAttr( BEVEL_InnerWidth, sd->gad_BevelFrame, &W );
GetAttr( BEVEL_InnerHeight, sd->gad_BevelFrame, &H );
}
else
{
X = 0;
Y = 0;
W = sd->gad_Container.Width;
H = sd->gad_Container.Height;
}
X += sd->gad_Container.Left + 1;
Y += sd->gad_Container.Top + 1;
W -= 2;
H -= 2;
RectFill( &rpbg, X, Y, X + W - 1, Y + H - 1 );
sd->gad_GraphLen = W - 13;
if (sd->gad_GraphLen > 320)
sd->gad_GraphLen = 320;
MyFreeBitMap( sd->gad_TempBitMap );
sd->gad_TempBitMap = MyAllocBitMap( sd->gad_GraphLen, 1, 8, 0, NULL );
memset(old, ~0, DATA_MAX * sizeof(ULONG));
}
else
{
// if (sd->gad_NoBorder)
// {
// X = Y = 0;
// }
// else
// {
GetAttr( BEVEL_InnerLeft, sd->gad_BevelFrame, &X );
GetAttr( BEVEL_InnerTop, sd->gad_BevelFrame, &Y );
// }
X += sd->gad_Container.Left + 1;
Y += sd->gad_Container.Top + 1;
}
SetAPen( &rpfg, sd->gad_FgPen );
SetBPen( &rpfg, sd->gad_BgPen );
SetDrMd( &rpfg, JAM2 );
SetFont( &rpfg, sd->gad_Font );
X += 2;
Y += 2;
if (data[Track] != old[Track] || data[Tracks] != old[Tracks])
{
/* track count */
Sprintf( line, "%02.2ld", data[Status] == CDP_STOPPED ? data[Tracks] : data[Track] );
Move( &rpfg, X, Y + baseline );
RectFill( &rpbg, X, Y, X + 2 * (sd->gad_Font->tf_XSize), Y + sd->gad_Font->tf_YSize );
Text( &rpfg, line, 2 /* constant length string */ );
}
if (data[TrackTime] != old[TrackTime])
{
/* playing time on this track */
Sprintf( line, "%02.2ld:%02.2ld", data[TrackTime]/60, data[TrackTime]%60 );
Move( &rpfg, X + 3 * (sd->gad_Font->tf_XSize), Y + baseline );
RectFill( &rpbg, X + 3 * (sd->gad_Font->tf_XSize), Y, X + 8 * (sd->gad_Font->tf_XSize), Y + sd->gad_Font->tf_YSize );
Text( &rpfg, line, 5 /* constant length string */ );
}
if (data[Time] != old[Time])
{
ULONG time = data[TrackTime];
if (sd->gad_TrackTimes && data[Track])
time = sd->gad_TrackTimes[data[Track]] - data[Time];
/* remaining time on this track */
Sprintf( line, "%02.2ld:%02.2ld", time/60, time%60 );
Move( &rpfg, X + 9 * (sd->gad_Font->tf_XSize), Y + baseline );
RectFill( &rpbg, X + 9 * (sd->gad_Font->tf_XSize), Y, X + 14 * (sd->gad_Font->tf_XSize), Y + sd->gad_Font->tf_YSize );
Text( &rpfg, line, 5 /* constant length string */ );
/* playing time from the start of the CD */
Sprintf( line, "%02.2ld:%02.2ld", data[Time]/60, data[Time]%60 );
Move( &rpfg, X + 15 * (sd->gad_Font->tf_XSize), Y + baseline );
RectFill( &rpbg, X + 15 * (sd->gad_Font->tf_XSize), Y, X + 20 * (sd->gad_Font->tf_XSize), Y + sd->gad_Font->tf_YSize );
Text( &rpfg, line, 5 /* constant length string */ );
}
if (data[TotalTime] != old[TotalTime])
{
/* total length of the CD */
Sprintf( line, "%02.2ld:%02.2ld", data[TotalTime]/60, data[TotalTime]%60 );
Move( &rpfg, X + 21 * (sd->gad_Font->tf_XSize), Y + baseline );
RectFill( &rpbg, X + 21 * (sd->gad_Font->tf_XSize), Y, X + 26 * (sd->gad_Font->tf_XSize), Y + sd->gad_Font->tf_YSize );
Text( &rpfg, line, 5 /* constant length string */ );
}
Y += sd->gad_Font->tf_YSize + 1;
if (data[Artist] != old[Artist])
{
/* show artist name */
ULONG len;
if (!data[Artist])
data[Artist] = (ULONG)"CompactPlayer";
len = strlen((STRPTR)data[Artist]);
Move( &rpfg, X, Y + baseline );
RectFill( &rpbg, X, Y, X + 26 * (sd->gad_Font->tf_XSize), Y + sd->gad_Font->tf_YSize );
Text( &rpfg, (STRPTR)data[Artist], len > 26 ? 26 : len );
}
/* title */
Y += sd->gad_Font->tf_YSize + 1;
if (sd->gad_TrackTitles && data[Track] && data[Track] != old[Track])
{
/* show track title */
ULONG len = strlen(sd->gad_TrackTitles[data[Track]-1]);
Move( &rpfg, X, Y + baseline );
RectFill( &rpbg, X, Y, X + 26 * (sd->gad_Font->tf_XSize), Y + sd->gad_Font->tf_YSize );
Text( &rpfg, sd->gad_TrackTitles[data[Track]-1], len > 26 ? 26 : len );
}
else
if (data[Title] != old[Title] || data[Track] != old[Track])
{
/* show disc title */
ULONG len;
if (!data[Title])
data[Title] = (ULONG)"By Osma Ahvenlampi";
len = strlen((STRPTR)data[Title]);
Move( &rpfg, X, Y + baseline );
RectFill( &rpbg, X, Y, X + 26 * (sd->gad_Font->tf_XSize), Y + sd->gad_Font->tf_YSize );
Text( &rpfg, (STRPTR)data[Title], len > 26 ? 26 : len );
}
/* track graph */
Y += sd->gad_Font->tf_YSize + 1;
if (data[Tracks] != old[Tracks])
{
ULONG x = X + /*sd->gad_GraphLen*/ data[TotalTime] * sd->gad_GraphLen / (80*60);
/* draw the disc time line */
RectFill( &rpbg, X, Y, X + sd->gad_GraphLen, Y + 6 );
Move( &rpfg, X, Y + 3 );
Draw( &rpfg, X, Y + 6 );
Move( &rpfg, X, Y + 5 );
Draw( &rpfg, x, Y + 5 );
Move( &rpfg, x, Y + 3 );
Draw( &rpfg, x, Y + 6 );
if (sd->gad_TrackTimes)
{
/* mark the track limits */
ULONG i = 0;
while (i < data[Tracks])
{
x = X + sd->gad_TrackTimes[i++] * sd->gad_GraphLen / (80*60) /*data[TotalTime]*/;
Move( &rpfg, x, Y + 4 );
Draw( &rpfg, x, Y + 6 );
}
}
}
if (data[Status] != old[Status])
{
/* draw the icon */
ULONG x = X + sd->gad_GraphLen + 1;
UBYTE *i;
RectFill( &rpbg, x, Y, x + 7, Y + 7 );
switch (data[Status])
{
case CDP_EMPTY:
i = IconEmpty;
break;
case CDP_PLAYING:
i = IconPlaying;
break;
case CDP_PAUSED:
i = IconPaused;
break;
case CDP_STOPPED:
i = IconStopped;
break;
case CDP_SEEKING:
i = IconSeeking;
break;
case CDP_EJECTED:
i = IconEjected;
break;
}
DrawStatusIcon( &rpfg, i, x, Y );
}
if (data[Time] != old[Time] && sd->gad_TempBitMap)
{
/* draw the line at current track position */
ULONG x = data[Time] * sd->gad_GraphLen / (80*60)/*data[TotalTime]*/;
struct RastPort rp = rpfg;
rp.Layer = NULL;
rp.BitMap = sd->gad_TempBitMap;
if (data[Status] == CDP_PLAYING || data[Status] == CDP_SEEKING)
{
if (data[Track] != old[Track] || data[Time] < old[Time])
memset(sd->gad_Graph + x, sd->gad_BgPen, sd->gad_TrackTimes[data[Track]] * sd->gad_GraphLen / (80*60) - x);
sd->gad_Graph[x&0xfffe] = sd->gad_FgPen;
}
memcpy(sd->gad_Graph + 320, sd->gad_Graph, 320);
WritePixelLine8(&rpfg, X, Y+2, sd->gad_GraphLen, sd->gad_Graph, &rp);
memcpy(sd->gad_Graph, sd->gad_Graph + 320, 320);
}
memcpy(old, data, DATA_MAX * sizeof(ULONG));
return (0);
}
static ULONG __saveds __asm
CDPanelDispatch(
register __a0 Class * cl,
register __a2 Object * o,
register __a1 Msg message)
{
ULONG retval;
switch (message->MethodID)
{
case GM_DOMAIN:
retval = domain_method(cl, o, (struct gpDomain *) message);
break;
case GM_RENDER:
retval = render_method(cl, o, (struct gpRender *) message);
break;
case GM_HITTEST:
retval = 0;
break;
case GM_HANDLEINPUT:
case GM_GOINACTIVE:
case GM_GOACTIVE:
retval = GMR_NOREUSE;
break;
case OM_SET:
case OM_UPDATE:
retval = set_method(cl, o, (struct opSet *) message);
break;
case OM_NEW:
retval = new_method(cl, o, (struct opSet *) message);
break;
case OM_DISPOSE:
retval = dispose_method(cl, o, message);
break;
case OM_GET:
retval = get_method(cl, o, (struct opGet *) message);
break;
default:
retval = DoSuperMethodA(cl, o, message);
break;
}
return (retval);
}
/* function to create/initialize our CLASS */
Class *
CreateCDPanelClass(void)
{
Class *cl;
if (cl = MakeClass( NULL, "gadgetclass", NULL, sizeof(struct CDPanelData), 0))
{
cl->cl_Dispatcher.h_Entry = (unsigned long (*)())CDPanelDispatch;
cl->cl_Dispatcher.h_SubEntry = NULL;
BevelBase = (struct ClassLibrary *) OpenLibrary("images/bevel.image", 0L);
if (BevelBase)
{
return (cl);
}
FreeClass( cl );
}
return (0);
}
void
DestroyCDPanelClass(struct Class * cl)
{
if (BevelBase)
{
CloseLibrary((struct Library *)BevelBase);
BevelBase = NULL;
}
if (cl)
{
FreeClass((struct IClass *)cl);
}
}