PDA

View Full Version : Overlay idea



Moser, Robert L. II
2003-12-05, 13:05
I've been kicking this around in my head for a while, and thought I'd open
it up to some discussion.

Current state: the lines() function returns $line1, $line2, $overlay1,
$overlay2. $overlay1 and $overlay2 replace the ends of $line1 and $line2,
with their ends coinciding with the end of the display.

What I'd like to see:
Specify each overlay as an array consisting of the string to display over
the base text, which line to put the string on, and where the string should
be displayed. The position of the string would be given as a number from
-40 to 39, interpreted as with arrays, but with positive numbers indicating
that the string should begin there, and negative indicating that the string
should end there.

For example, the right arrow overlay so commonly used would be
['vfD_rightarrow_Vfd',1,-1]. All current overlays would have -1 as their
position indicator.

Possibly that string bit could be a code ref (to which would be passed the
$client object).

Then have a list of these overlay arrays which all get applied over the base
$line[12].

So far so good, but then we get into the tricky bits. How do you build that
list of arrays? You will most likely be applying them in order, so
determining that order is very important.

If the array of overlays was limited to coming from the lines() function,
there wouldn't be much of a problem, each lines() function would determine
the order on its own. But, once you have a good overlay system set up, you
can use it to do animations, and things like the much requested put a
message up on a particular line.

Assuming you have your list built up (and neglecting the code ref
possibility for now), the overlay rendering would go something like this:

#overlayref is [0 => overlay string, 1 => line, 2 => overlay position]
foreach my $overlayref (@overlays) {
my $overlayLength =
Slim::Hardware::VFD::lineLength($$overlayref[0]);
Slim::Hardware::VFD::subString($$overlayref[1] ? $line2 : $line1
,$$overlayref[2] < 0 ? 41 + $$overlayref[2] - $overlaylength
: $$overlayref[2]
,$overlayLength
,$$overlayref[0]);
}


One possibility is to have a hash of overlays in the client object which
could be added by whatever module. The module would be responsible for
getting rid of the overlay entry when it was no longer needed. The entries
in the hash would be a priority, and a list of overlays. The overlay list
would be built in order of priority. One of the entries in the hash could
be for the current mode, and would be set in the setMode function.

Anyway, there's the idea, let the bashing begin.

dean
2003-12-05, 13:52
I'd prefer passing the overlay information as part of the string, like
we do for cursor position, etc.

Imagine a now playing screen expressed as this string:

Now Playing__overlay_right__00:34\n
03. Mama's Got A Squeezebox__overlay_right____vfD_notesymbol_Vfd__

Also note that rather than having an array of lines, we just include a
line break character (\n) and send the whole screen as a single string.

Or even better:

<screen>Now Playing<rightalign>00:34</rightalign><br>
03. Mama's Got a Squeezebox<rightalign>&note;</rightalign></screen>

Whatever system we come up with, I'd like to make sure that it can
handle:

- Non-fixed width characters
- Displays with less or more than 2 lines
- Displays with less or more than 40 characters

Doing overlays that use character positions, probably won't cut it.





On Dec 5, 2003, at 12:05 PM, Moser, Robert L. II wrote:

> I've been kicking this around in my head for a while, and thought I'd
> open
> it up to some discussion.
>
> Current state: the lines() function returns $line1, $line2, $overlay1,
> $overlay2. $overlay1 and $overlay2 replace the ends of $line1 and
> $line2,
> with their ends coinciding with the end of the display.
>
> What I'd like to see:
> Specify each overlay as an array consisting of the string to display
> over
> the base text, which line to put the string on, and where the string
> should
> be displayed. The position of the string would be given as a number
> from
> -40 to 39, interpreted as with arrays, but with positive numbers
> indicating
> that the string should begin there, and negative indicating that the
> string
> should end there.
>
> For example, the right arrow overlay so commonly used would be
> ['vfD_rightarrow_Vfd',1,-1]. All current overlays would have -1 as
> their
> position indicator.
>
> Possibly that string bit could be a code ref (to which would be passed
> the
> $client object).
>
> Then have a list of these overlay arrays which all get applied over
> the base
> $line[12].
>
> So far so good, but then we get into the tricky bits. How do you
> build that
> list of arrays? You will most likely be applying them in order, so
> determining that order is very important.
>
> If the array of overlays was limited to coming from the lines()
> function,
> there wouldn't be much of a problem, each lines() function would
> determine
> the order on its own. But, once you have a good overlay system set
> up, you
> can use it to do animations, and things like the much requested put a
> message up on a particular line.
>
> Assuming you have your list built up (and neglecting the code ref
> possibility for now), the overlay rendering would go something like
> this:
>
> #overlayref is [0 => overlay string, 1 => line, 2 => overlay position]
> foreach my $overlayref (@overlays) {
> my $overlayLength =
> Slim::Hardware::VFD::lineLength($$overlayref[0]);
> Slim::Hardware::VFD::subString($$overlayref[1] ? $line2 : $line1
> ,$$overlayref[2] < 0 ? 41 + $$overlayref[2] - $overlaylength
> : $$overlayref[2]
> ,$overlayLength
> ,$$overlayref[0]);
> }
>
>
> One possibility is to have a hash of overlays in the client object
> which
> could be added by whatever module. The module would be responsible for
> getting rid of the overlay entry when it was no longer needed. The
> entries
> in the hash would be a priority, and a list of overlays. The overlay
> list
> would be built in order of priority. One of the entries in the hash
> could
> be for the current mode, and would be set in the setMode function.
>
> Anyway, there's the idea, let the bashing begin.
>

Kevin Deane-Freeman
2003-12-05, 23:39
A central array seems a good start to me. I dont think that parsing XML or some
other markup is a step forward overall. Id like to see something that reduces
the number of times the code is passing $line1, $line2, etc. I am, of course,
assuming that references are smaller than the actual data. Pointing to a memory
location, and passing that around has to reduce the overhead that is currently
in the server. I am not a programmer, and probably never will be, no matter how
much code I do write. I rely on the expertise of those with the proper training :)

if I am correct in my perception that we can reduce memory usage by using a hash
array, then I'm all for it, even at the cost of backward compatiblity. I'm
currently at 62M for 10k songs, and while I have plenty of memory to spare...it
still looks like a bigger number than it has to be.

Splitting the lines so that users can insert one line of data without killing
the other, I'm all for it. I'm not sure if access to exact character position
is so important. If there is a good example, then I'm interested (I'm hoping
its more than just bouncing ball ;)

-kdf

Richard Purdie
2003-12-06, 02:46
Can I just try an idea I've had in the back of my mind out on you? This sort
of relates to what you're talking about and sort of doesn't.

How about forming a FILO stack of what should be on the display? For
example, the date and clock could be on layer one. When the player is turned
on, the menus come onto layer 2. Say someone then wants a message displayed
via an http request - this would go onto layer three. As the user confirms
that they've seen the message, it would be popped off to reveal the menu.
The player is turned off and the original layer is revealed again. By
passing some special character you can make part of the display "see
through" so the mode behind can be seen.

The advantage of this is that the animation becomes something attached to a
layer. It also means user messages can interrupt the display and not cause
as many problems so plugins could become simpler. Each layer can have an
attached update function which is called x number of times whilst the layer
is displayed which would update the clock for example. This would allow
scrolling updated data. (Think of the clock bouncing around whilst changing
time).

Rather than have the fun with XML I've make each data routine responsible
for sorting the layout and just pass a set of lines to the display code. You
could create a set of functions that user code could use to format the data
(how many lines do we have? how many columns?). For non fixed width
characters, some you'd have to declare the number of pixels and then have a
function that would calculate the number of pixels a certain piece of text
would need.

Thinking about it, there is no reason you can't have some functions like

centreText("9:39:39 AM") which would return something like

"||||||||||||||||||||9:39:39 AM||||||||||||||||||||"

where "|" is a special character denoting empty space.

rightText("27oC") would return
"||||||||||||||||||||||||||||||||||||||||27oC"

and then you could have a merge function which returns the text to be
displayed (or failure as the display isn't big enough)...

These are just some ideas and I'm by no means saying do it this way -
they're just worth thinking about...

I am concerned about server memory use and I think something does need to be
done about that. I'm not sure which bit of the server hogs memory however...

RP

dean
2003-12-06, 07:52
On Dec 5, 2003, at 10:39 PM, Kevin Deane-Freeman wrote:
> A central array seems a good start to me. I dont think that parsing
> XML or some
> other markup is a step forward overall. Id like to see something that
> reduces
> the number of times the code is passing $line1, $line2, etc. I am, of
> course,
> assuming that references are smaller than the actual data. Pointing
> to a memory
> location, and passing that around has to reduce the overhead that is
> currently
> in the server. I am not a programmer, and probably never will be, no
> matter how
> much code I do write. I rely on the expertise of those with the
> proper training :)
A single reference to a string is about as small as it gets in perl.

> if I am correct in my perception that we can reduce memory usage by
> using a hash
> array, then I'm all for it, even at the cost of backward compatiblity.
> I'm
> currently at 62M for 10k songs, and while I have plenty of memory to
> spare...it
> still looks like a bigger number than it has to be.
That would almost certainly be larger than a single string representing
the state of the display.

dean
2003-12-06, 07:59
On Dec 6, 2003, at 1:46 AM, Richard Purdie wrote:
> Can I just try an idea I've had in the back of my mind out on you?
> This sort
> of relates to what you're talking about and sort of doesn't.
>
> How about forming a FILO stack of what should be on the display? For
> example, the date and clock could be on layer one. When the player is
> turned
> on, the menus come onto layer 2. Say someone then wants a message
> displayed
> via an http request - this would go onto layer three. As the user
> confirms
> that they've seen the message, it would be popped off to reveal the
> menu.
> The player is turned off and the original layer is revealed again. By
> passing some special character you can make part of the display "see
> through" so the mode behind can be seen.
Sounds like you are describing a windowing system.

> Rather than have the fun with XML I've make each data routine
> responsible
> for sorting the layout and just pass a set of lines to the display
> code.
Right. So I'm suggesting that we have a single string that defines the
state of the display. I don't care much if it's XML or more like the
__vfD_code_Vfd__ style syntax we have now. I don't want to pass around
arrays or hashes.

> You
> could create a set of functions that user code could use to format the
> data
> (how many lines do we have? how many columns?). For non fixed width
> characters, some you'd have to declare the number of pixels and then
> have a
> function that would calculate the number of pixels a certain piece of
> text
> would need.
We already have this in the lines() function that each display mode
has. They currently return either 2 or 4 scalars (line1, line2,
overlay1, overlay2). Let's return a single scalar that combines all of
these through some simple markup syntax, then convert this to raw
display characters right before it goes to the player.

> Thinking about it, there is no reason you can't have some functions
> like
>
> centreText("9:39:39 AM") which would return something like
>
> "||||||||||||||||||||9:39:39 AM||||||||||||||||||||"
>
> where "|" is a special character denoting empty space.
How about " "? :)

> I am concerned about server memory use and I think something does need
> to be
> done about that. I'm not sure which bit of the server hogs memory
> however...
The Info library hogs a tremendous amount of space, but there's fixed
overhead that we need to reduce too. The transient display usage I'm
sure is tiny.

-dean

Phil Barrett
2003-12-06, 08:41
On 6 Dec 2003, at 14:59, dean blackketter wrote:
> On Dec 6, 2003, at 1:46 AM, Richard Purdie wrote:
>> Thinking about it, there is no reason you can't have some functions
>> like
>>
>> centreText("9:39:39 AM") which would return something like
>>
>> "||||||||||||||||||||9:39:39 AM||||||||||||||||||||"
>>
>> where "|" is a special character denoting empty space.
> How about " "? :)

Not quite - I think Richard means transparent space, as opposed to the
" " in the time string, which is opaque space. The transparency allows
the string to be "composited" over lower layers.

Phil

Richard Purdie
2003-12-06, 11:11
> Sounds like you are describing a windowing system.

Effectively yes. If you want the plugin system to be truely useable, this is
what will be needed. It'll be painful to implement now but not as much as it
will be a year down the road...

> Right. So I'm suggesting that we have a single string that defines the
> state of the display. I don't care much if it's XML or more like the
> __vfD_code_Vfd__ style syntax we have now. I don't want to pass around
> arrays or hashes.

I agree with that. The more I think about it, the more it makes sense.
Getting the markup right is going to be the key thing. Simple but powerful
is what is needed.

> > Thinking about it, there is no reason you can't have some functions
> > like
> >
> > centreText("9:39:39 AM") which would return something like
> >
> > "||||||||||||||||||||9:39:39 AM||||||||||||||||||||"
> >
> > where "|" is a special character denoting empty space.
> How about " "? :)

The idea was that " " would display nothing where as "|" was transparent.
You could then have a ten character area to the right of your clock
scrolling the lastest share prices whilst leaving the clock visble. Or
whatever - it would just a be neat feature to work in with a windowing
system :)

> The Info library hogs a tremendous amount of space, but there's fixed
> overhead that we need to reduce too. The transient display usage I'm
> sure is tiny.

The info library is what I suspected hogs space (although the fixed overhead
is also high now I think about it). I'll have a think about how to improve
info handling... :-/

RP

Robert Moser II
2003-12-06, 13:23
dean blackketter blurted out:

> Whatever system we come up with, I'd like to make sure that it can handle:
>
> - Non-fixed width characters
> - Displays with less or more than 2 lines
> - Displays with less or more than 40 characters
>
> Doing overlays that use character positions, probably won't cut it.
>

For the second two points, both can be handled in the framework I
mentioned, with slight modification. Instead of the current state of
two $line scalars, make it a @lines array (passed by ref), that covers
displays with any number of lines. For the second, each player object
would have a linewidth attribute which would be used in calculating
position. If you go off the ends, then the text won't be displayed.

With those modifications that previous code would look like this:

#overlayref is [0 => overlay string, 1 => line, 2 => overlay position]
foreach my $overlayref (@overlays) {
my $overlayLength =
Slim::Hardware::VFD::lineLength($$overlayref[0]);
my $width = $client->displaywidth;
Slim::Hardware::VFD::subString($$lineref[$$overlayref[1]]
,$$overlayref[2] < 0
? $width + 1 + $$overlayref[2] - $overlaylength
: $$overlayref[2]
,$overlayLength
,$$overlayref[0]);
}


I really don't see the advantage of passing one scalar (or scalar ref)
which has to be broken down for processing, over passing two array refs
(or one if it consists of [$lineref,$overlayref]), which are in the
state needed for processing. If we were passing the string outside of
our program, I could see doing it. But this is all internal, so there
is no need to have it be human readable.

As I see it, all you do by making everything one string is complicate
the string handling functions. Witness the VFD string functions, the
zero length strings (like __cursorpos__) are a pain to properly account
for. I don't even want to think about writing a VFD::subString function
which can handle markup.

As for non-fixed width characters, that's a tough problem, but it could
be handled by a separate function which knows things like how to
calculate the length of a string in pixels. For positioning from the
sides of the display, use a standard character to pixel conversion, so
that things don't jump around.

Robert Moser II
2003-12-06, 14:25
Richard Purdie blurted out:

> Can I just try an idea I've had in the back of my mind out on you? This sort
> of relates to what you're talking about and sort of doesn't.
>
> How about forming a FILO stack of what should be on the display? For
> example, the date and clock could be on layer one. When the player is turned
> on, the menus come onto layer 2. Say someone then wants a message displayed
> via an http request - this would go onto layer three. As the user confirms
> that they've seen the message, it would be popped off to reveal the menu.
> The player is turned off and the original layer is revealed again. By
> passing some special character you can make part of the display "see
> through" so the mode behind can be seen.

This is very close to what I was thinking. The problem is one of
ownership. As a module, you can't just pop off a layer, because you
can't be sure that you were the last one to add a layer. There needs to
be some way of knowing which layer is yours, so that you can modify the
correct one. That's why I was thinking of a hash plus a priority, the
hash to determine ownership, and the priority to determine layer.

> Rather than have the fun with XML I've make each data routine responsible
> for sorting the layout and just pass a set of lines to the display code. You
> could create a set of functions that user code could use to format the data
> (how many lines do we have? how many columns?). For non fixed width
> characters, some you'd have to declare the number of pixels and then have a
> function that would calculate the number of pixels a certain piece of text
> would need.

You could also have it return something like [String to
draw,[coordinates of where to draw it]]. For character based displays
those coordinates would be row/column and for graphics displays they
would be pixel coordinates (of some corner of the box containing the
string).

> Thinking about it, there is no reason you can't have some functions like
> centreText("9:39:39 AM") which would return something like
> "||||||||||||||||||||9:39:39 AM||||||||||||||||||||"
> where "|" is a special character denoting empty space.
> rightText("27oC") would return
> "||||||||||||||||||||||||||||||||||||||||27oC"
> and then you could have a merge function which returns the text to be
> displayed (or failure as the display isn't big enough)...

Again, pretty close to my thinking. The main difference that I see here
was that I was thinking of doing it from the bottom layer up, whereas
you are going from the top down. In the end, it would come down to
trying it both ways and seeing which one ends up being simpler to code.
As for the transparent character, it would probably best to use some
kind of vfD_symbol_Vfd rather than an actual character, since you never
know when you might actually want to use that particular character.

> These are just some ideas and I'm by no means saying do it this way -
> they're just worth thinking about...

Definitely keep 'em coming, you've got some good ideas here. Plus, the
more ideas we have on the table, the higher the likelihood of us finding
a great one.

Robert Moser II
2003-12-07, 10:17
I'm not sure where this would fit into the flow of conversation, so I'm
just sticking it at the top.

How about an object to represent the screen? Some base object like
Slim::Display::Screen, with extensions like Slim::Display::Screen::Char
(further extended to Slim::Display::Screen::Char_Double). Then the
lines function would return an object, which it would initially get by
doing Slim::Display::Screen->new($client);

The screen object would have all the screen formatting functions and
screen attributes built into it. So, for example it would supply a
center() method, and a length method, and have attributes like height,
width, measurementtype (char|pixel|char_elem).

Methods definitely to have would be toString (spits out strings like
Dean likes), and toDisplay (spits out string ready to be sent to display).

For layering, have an addLayer method which takes another screen object
(of the same type) and composites it in (under or over the existing,
possibly controlled by a parameter).

Doublesize in this scheme would be that
Slim::Display::Screen::Char_Double class, which would have a
measurementtype of char_elem (since it isn't pixels, and it isn't
characters). Another method would be stringHeight, which would return
the height in measurementtype of the given string (which for the most
part would be 2 in doublesize mode).

The primary method would be something like addText, which would take
parameters of the text to add, where to add it, and anything special
about the text (think fonts here). For a screen of type Char_Double,
that special bit could be to use small chars (which could provide an
interesting mix of doublesize and single size chars on the same display).

Another attribute could be numLines, which would return the number of
lines of displayable text when using the default font.

Sorry for the rambling nature of this post, it is pretty much just a
brain dump.

Robert

Robert Moser II
2003-12-07, 10:27
Robert Moser II blurted out:
> The primary method would be something like addText, which would take
> parameters of the text to add, where to add it, and anything special
> about the text (think fonts here). For a screen of type Char_Double,
> that special bit could be to use small chars (which could provide an
> interesting mix of doublesize and single size chars on the same display).

As an addendum here, there could also be methods like addXML, or
addFormattedText, which would understand things like the XML options
previously discussed, or the __cursorpos__, __overlay_right__, etc.

another (settable) attribute: centerpos.

Robert Moser II
2003-12-07, 10:50
> another (settable) attribute: centerpos.

I don't know why, but I keep writing centerpos when I mean cursorpos,
sorry about that.

dean
2003-12-08, 10:03
My concern about this would be about performance.
On Dec 7, 2003, at 9:17 AM, Robert Moser II wrote:

> I'm not sure where this would fit into the flow of conversation, so
> I'm just sticking it at the top.
>
> How about an object to represent the screen? Some base object like
> Slim::Display::Screen, with extensions like
> Slim::Display::Screen::Char (further extended to
> Slim::Display::Screen::Char_Double). Then the lines function would
> return an object, which it would initially get by doing
> Slim::Display::Screen->new($client);
>
> The screen object would have all the screen formatting functions and
> screen attributes built into it. So, for example it would supply a
> center() method, and a length method, and have attributes like height,
> width, measurementtype (char|pixel|char_elem).
>
> Methods definitely to have would be toString (spits out strings like
> Dean likes), and toDisplay (spits out string ready to be sent to
> display).
>
> For layering, have an addLayer method which takes another screen
> object (of the same type) and composites it in (under or over the
> existing, possibly controlled by a parameter).
>
> Doublesize in this scheme would be that
> Slim::Display::Screen::Char_Double class, which would have a
> measurementtype of char_elem (since it isn't pixels, and it isn't
> characters). Another method would be stringHeight, which would return
> the height in measurementtype of the given string (which for the most
> part would be 2 in doublesize mode).
>
> The primary method would be something like addText, which would take
> parameters of the text to add, where to add it, and anything special
> about the text (think fonts here). For a screen of type Char_Double,
> that special bit could be to use small chars (which could provide an
> interesting mix of doublesize and single size chars on the same
> display).
>
> Another attribute could be numLines, which would return the number of
> lines of displayable text when using the default font.
>
> Sorry for the rambling nature of this post, it is pretty much just a
> brain dump.
>
> Robert
>
>