summaryrefslogtreecommitdiffstats
path: root/noatun/modules/kjofol-skin/kjseeker.cpp
blob: 41e4db13b7e11ad44f68f48d5e9fbebafb5ca0f4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
/***************************************************************************
	kjseeker.cpp
	---------------------------------------------
	slider that lets the user jump inside the currently played file
	---------------------------------------------
	Maintainer: Stefan Gehn <sgehn@gmx.net>

 ***************************************************************************/

#include "kjseeker.h"
#include "kjloader.h"

#include "helpers.cpp"
#include <noatun/player.h>

#include <kdebug.h>

KJSeeker::KJSeeker(const QStringList &i, KJLoader *l) : KJWidget(l), g(0)
{
	QString activeBg = backgroundPressed("bmp1");
	if(activeBg.isEmpty())
	{
		kdDebug(66666) << k_funcinfo << "No pressed background found for seeker," <<
			" using default background!" << endl;
		parent()->image(parser()["backgroundimage"][1]);
	}
	else
		mActive = parent()->image(activeBg);

	mScale = parent()->image(parser()["seekimage"][1]);
	QImage pixmapNoPress = parent()->image(parser()["backgroundimage"][1]);

	// generate transparent mask
	int x, y, xs, ys;
	x=i[1].toInt();
	y=i[2].toInt();
	xs=i[3].toInt()-x;
	ys=i[4].toInt()-y;
	setRect(x,y,xs,ys);
	QImage transmask(xs, ys, 1, 2, QImage::LittleEndian);
#if QT_VERSION < 0x030300
	transmask.setColor(0, qRgb(0,0,0));
	transmask.setColor(1, qRgb(255,255,255));
#else
	transmask.setColor(1, qRgb(0,0,0));
	transmask.setColor(0, qRgb(255,255,255));
#endif

	// clear the pointers
	memset(barmodeImages, 0, 256*sizeof(QImage*));
	memset(barmode, 0, 256*sizeof(QPixmap*));

	// Now do the pixel føking
//	kdDebug(66666) << "creating Pixmaps for Seeker" << endl;
	for (int iy=y;iy<y+ys; iy++)
	{
		for (int ix=x;ix<x+xs; ix++)
		{
			QRgb checkmScale = mScale.pixel(ix, iy);
			// am I transparent?
			if (!isGray(checkmScale))
			{
				setPixel1BPP(transmask, ix-x, iy-y, 0);
				continue;
			}
			setPixel1BPP(transmask, ix-x, iy-y, 1);

			// what is the level
			int level=grayRgb(checkmScale)+1;
			if (level>255) level=255;
			// allocate the pixmap of the level proper
			// copy the color to the surface proper
			QRgb activeColor=mActive.pixel(ix,iy);
			QRgb inactiveColor=pixmapNoPress.pixel(ix,iy);
			// set this pixel and everything before it
			for(int i=0; i<level; i++)
			{
				if (!barmodeImages[i])
					barmodeImages[i]=new QImage(xs,ys, 32);
				QRgb *l=(QRgb*)barmodeImages[i]->scanLine(iy-y);
				l[ix-x]=inactiveColor;
			}

			do
			{
				if (!barmodeImages[level])
					barmodeImages[level]=new QImage(xs,ys, 32);
				QRgb *l=(QRgb*)barmodeImages[level]->scanLine(iy-y);
				l[ix-x]=activeColor;
			} while (level++<255);
		}
	}
//	kdDebug(66666) << "finished creating Pixmaps" << endl;

	// create the blank one
	barmode[0]=new QPixmap(xs, ys);
	QPixmap px=parent()->pixmap(parser()["backgroundimage"][1]);
	bitBlt(barmode[0], 0, 0, &px, x, y, xs, ys, Qt::CopyROP);
	px.convertFromImage(transmask);
	barModeMask=px;

//	kdDebug(66666) << "END KJSeeker constructor" << endl;
}

QPixmap *KJSeeker::toPixmap(int n)
{
	if (!barmodeImages[n]) return barmode[n];

	barmode[n]=new QPixmap(
			barmodeImages[n]->width(),
			barmodeImages[n]->height()
		);
	barmode[n]->convertFromImage(*barmodeImages[n]);

	delete barmodeImages[n];
	barmodeImages[n]=0;
	return barmode[n];
}


KJSeeker::~KJSeeker()
{
	for (uint i=0; i<256; i++)
	{
		if (barmode[i])
			delete barmode[i];
		if (barmodeImages[i])
			delete barmodeImages[i];
	}
}

void KJSeeker::paint(QPainter *p, const QRect &)
{
	closest();
	QPixmap *pixmap = toPixmap(g);
	pixmap->setMask(barModeMask);
	bitBlt(p->device(), rect().topLeft().x(), rect().topLeft().y(),
		pixmap, 0, 0, rect().width(), rect().height(), Qt::CopyROP);
}

bool KJSeeker::mousePress(const QPoint &pos)
{
	return (isGray(mScale.pixel(rect().topLeft().x()+pos.x(), rect().topLeft().y()+pos.y())));
}

void KJSeeker::mouseRelease(const QPoint &pos, bool in)
{
	int x = rect().topLeft().x()+pos.x();
	int y = rect().topLeft().y()+pos.y();

	if(napp->player()->isStopped())
		return;

	if(!mScale.valid(x, y))
	   return;

	QRgb color=mScale.pixel(x, y);

	// user released mousebutton outside of the seeker-area (which is gray)
	if ( (!isGray(color)) || (!in) )
		return;

	g = grayRgb(color);
	repaint();

//	kdDebug(66666) << "length : " << napp->player()->getLength() << endl;
//	kdDebug(66666) << "skip to: " << ((long long)g*(long long)napp->player()->getLength())/255 << endl;

	// g * titlelength can get REALLY HUGE, that's why I used (long long)
	napp->player()->skipTo( ((long long)g*(long long)napp->player()->getLength())/255 );

	return;
}

void KJSeeker::timeUpdate(int sec)
{
	int length = napp->player()->getLength() / 1000;
	if (length<1)
		length=1;

	if (sec > length)
		sec = length;
	else if ( sec < 0 )
		sec=0;

	g = sec * 255 / length;
	//kdDebug(66666) << "sec: " << sec << " len: " << length << " g: " << g << endl;
	QPainter p(parent());
	paint(&p, rect());
}

void KJSeeker::closest()
{
	int south=g, north=g;
	bool southtried=false, northtried=false;
	while (
			!barmode[south] && !barmodeImages[south]
			&& !barmode[north] && !barmodeImages[north])
	{
		if (southtried && northtried) { g=0; return; }
		south--;
		north++;
		if (north>255) {northtried=true; north=g;}
		if (south<0) {southtried=true; south=g;}
	}
	if (barmode[south] || barmodeImages[south])
		g=south;
	else if (barmode[north] || barmodeImages[north])
		g=north;
}