View Full Version : Parse control info tag
been searching for it, but could not find a solution for it yet, should be easy to implement.
the info tag from the the label control now only takes one infoitem, e.g. musicplayer.artist. it would be nice to be able to supply more than one item and fixed characters.
something like <info>[musicplayer.artist] - *[musicplayer.title]</info>
this would be easily achieved using a regularexpression which matches some trigger sequence (like [<something>]) and replaces it with the prober value.
another solution to achieve the same (but probably more difficult to implement) is to be able to attach a control to the side of another control (so when the size of the 1st control changes, the attached control will reposition).
last but not least multiple info tags (like in the fadelabel) could be rendered behind eachother (so the above example would become <info>musicplayer.artist</info><info> - </info><info>musicplayer.title</info>). this would probably be the easiest to implement (no regex stuff).
jmarshall
2005-05-10, 18:19
i've been thinking on this for quite a while, but have yet to come up with an ideal solution (both simple from the skinners point of view and the code point of view).
remember that we need localisation, so any additional strings must be localizable (ie can be references into strings.xml). this tends to complicate things somewhat.
i guess the easiest to implement would be the one where it's all in one tag, with pieces of information that xbmc should replace being contained in some predefined delimiters (eg square brackets as you indicate). i don't think using <blah> is valid, as the xml parser will screw up with that. either that, or we use something like + between each expression that requires concating together.
i think it's essential to have some form of delimiter as it makes it so much easier (and quicker) to produce the format string needed in the end.
comments/opinions are most welcome :)
cheers,
jonathan
you could just treat anything between the delimeters as parsable, either an info string (musicplayer.foo) or a string id that can be localised (localize.155 or something).
so you could make something like:
<info>[localize.654321] [queue.currenttrack] [localize.1234567] [queue.totaltracks]</info>
which would render into:
track 6 of 18
my c++ is a bit rusty.. but in c# it would be something like
public string parseinfotag(string infotag)
{
system.text.stringbuilder newline = new system.text.stringbuilder(infotag);
if (expression.indexof('[') > -1)
{
system.text.regularexpressions.regex r = new system.text.regularexpressions.regex(@"\[([\w\d\./]*(\(\))?(\([\d]+\))?(\(""[^""]*""\))?)*(\[[^\[\]] *\])*\]", system.text.regularexpressions.regexoptions.ignore case | system.text.regularexpressions.regexoptions.compil ed );
system.text.regularexpressions.match m;
string field;
for ( m = r.match( expression ); m.success; m = m.nextmatch() )
{
if (m.groups[0].length > 0)
{
field = m.groups[0].tostring().substring(1,m.groups[0].len gth-2);
string result = "";
if (field.tolower().startswith("localize.")
{
//localize whats behind localize.
result = "foo";
}
else
{
//try to parse e.g. musicplayer.album
result = "foo";
}
newline.replace(m.groups[0].tostring(),result);
}
}
}
return newline.tostring();
}
never mind the regex.. i copied some code from a project i work on.. it matches with 'most' stuff between [].. *and some other criteria.. but reading back a regex i created like a year ago is too much work for now:)
we use it for similar purposes, where the parsable parts are executed using reflection on an object, so you only have to define properties or methods on a 'scripting' object that you want to expose, and execute them using reflection. no need to manually parse items anymore. instead of [localize.1234] you could use [localize(1234)], where you have a function localize(string id) exposed as public on the scripting object. nyway.. i have enough c# code for that around here:)
maybe if i'm in the mood for it i'll try to install vs2003 and get some xbmc code... and look at it.. but since i'm already programming all day.. i can't promise nything
-edit-
i forgot.. unmanaged c++ doesn't support reflection.. nyway.. solutions enough i think
i made a very small patch for my own use by copying some code from the fadelabel (for handling multiple info tags).
then while rendering i loop over the info id's and concat a string using a default seperator (' - ') in this case...
in cguilabelcontrol:
void cguilabelcontrol::render()
{
*if (m_vecinfo.size())
*{
*// check if we need to update our info
*wstring strlabel ( l"" );
*for (unsigned int i = 0; i < m_vecinfo.size(); i++)
*{
*int m_info = m_vecinfo[i];
*wstring labelpart = g_infomanager.getlabel(m_info);
*if (strlabel.length())
*{
*strlabel.append(l" - ");
*}
*strlabel.append(labelpart);
*}
* *if (strlabel != m_strlabel)
setlabel(strlabel);
*}
if anyone is interested in the other neccessary code changes let me know.. i think it's all a bit too small to be really benificial.. but i like that i now have: musicplayer.year - musicplayer.album on one row, and musicplayer.time - musicplayer.duration on another...
i'll now see if i can implement a localize.<stringid> info tag in order for me to use any seperator (or localized text) i like..
but i have to admit... damn.. unmanaged c++ sucks big time.. i'm glad i program c# during the day
why not extend the label tag to accept more than one info and/or label tag? the system should concatenate them in the order they are found.
<type>label</type>
<info>musicplayer.artist</info>
<label> - </label>
<info>musicplayer.album</info>
and as dantm says, this is already very similar to how the fadelabel works.
alternatively, the xml could be something like this:
<type>label</type>
<concat>
<info>musicplayer.artist</info>
<label> - </label>
<info>musicplayer.album</info>
</concat>
to denote which pieces to concatenate. then this could even be ported into a fadelabel too.
<type>fadelabel</type>
<concat>
<info>musicplayer.artist</info>
<label> - </label>
<info>musicplayer.album</info>
</concat>
<concat>
<info>musicplayer.time</info>
<label>/</label>
<info>musicplayer.duration</info>
</concat>
i now have it working like this:
* *<control>
* * *<description>time</description>
* * *<type>label</type>
* * *<id>1</id>
* * *<visible>player.hasaudio</visible>
* * *<posx>640</posx>
* * *<posy>436</posy>
* * *<info>musicplayer.time</info>
* * *<info>15215</info>
* * *<info>musicplayer.duration</info>
* * *<align>right</align>
* * *<font>font10</font>
* *</control> *
where 15214 is an id in the string db so localisation works..
it shows something like 2:13 / 14:18
but any string could be put in the concatenation.. there are still a few problems.. leading and trailing spaces are removed from the localization strings, so i hardcoded a space inbetween all concatenations.
the other problem is that it always shows the localized strings, even if no music is playing. gonna look into that now, probably the visible tag is not getting parsed properly (or not used at all, who knows).
jmarshall
2005-05-12, 00:55
i kinda like the second idea - much more xml-ish, though order is still important.
replace <concat> with <combinedinfo> and we're all rosy i think.
cheers,
jonathan
pictures:
http://www.inden.demon.nl/screenshot000.jpg
and
http://www.inden.demon.nl/screenshot002.jpg
after some checking i noticed that conditional visibility is not present in the labelcontrol (only in image and edit?).. so i copied it from image to labelcontrol..
but shouldn't it be in the base control class so all controls automagically benefit from it?
i put a patch up on sourceforge for those interested:
patch 1200420 (http://sourceforge.net/tracker/index.php?func=detail&aid=1200420&group_id=87054&atid=581840)
great, lets hope a dev agress and adds it to cvs if it's a cool patch ;)
great, lets hope a dev agress and adds it to cvs if it's a cool ™ patch ;)
i think it needs some more working to be cool :)
it works as it is, but it's not a perfect solution.. it's more the idea...
but i'm pretty sure a dev can do it a lot quicker than that i have to look to pages of unfamiliar coding using unfamiliar libraries.
ok.. i'm busy making some changes, the old patch will be discarded, the new format will be as following:
use a <label> tag to specify what you want to see and put the infotags numbered into the label (or the localized string).
an example will be better:)
* *<control>
* * *<description>time</description>
* * *<type>label</type>
* * *<id>1</id>
* * *<visible>player.hasaudio</visible>
* * *<label>[1] / [2]</label>
* * *<posx>640</posx>
* * *<posy>446</posy>
* * *<info>musicplayer.time</info>
* * *<info>musicplayer.duration</info>
* * *<align>right</align>
* * *<font>font10</font>
* *</control> * *
it will parse the info tags into the label. i still have to test it, but when its working i will put up a new (updated) patch.
something similar could be done for the fadelabel, using multiple <label> tags, where the fadelabel will loop over the labels (instead of looping over the info items) and parse them with info tags e.g.:
* * *<label>time: [1]</label>
* * *<label>remaining: [3]</label>
* * *<label>duration[2] & genre [4]</label>
* * *<info>musicplayer.time</info>
* * *<info>musicplayer.duration</info>
* * *<info>musicplayer.remaining</info>
* * *<info>musicplayer.genre</info>
ofcourse localized string could be used too.
if devs r interested i'll look at that.. though i don't need it myself...
gr.
dan
jmarshall
2005-05-13, 16:02
sounds like a nice solution, but how do you handle localization strings? is it in the <label> tags, or in the <info> tags, or???
also, do you have a solution to cope with backward compatibility?
cheers,
jonathan
localization will be both in info as in label tags.
so u can use both <label>stringid</label> to get a parsable string (e.g. '[1] of [2]'), or you can use <info>stringid</info> to get a localized string, e.g.:
<label>[1] [2] [3]</label>
<info>musicplayer.album</info>
<info>stringid</info>
<info>musicplayer.genre</info>
fadelabel will be working the same, and both will be backwards compatible. i'll probably release a patch later this evening.
gr
dan
i like the idea of referencing something else, but make it more "xmlish" (to quote jmarshall's earlier comment.) *i'm thinking of a new construct to hold these referenced info items. here's a quick example:
<window>
...
<controls>
..
*<control>
* * <id>1</id>
* * <type>fadelabel</type>
* * <visible>player.hasaudio</visible>
* * ....
* * <label>$ref(1)$ref(2)</label>
* * <label>$ref(3)$ref(4)</label>
* * <label>$ref(5)$ref(6) & $ref(7)$ref(8)</label>
*</control>
*...
</controls>
<referencelist>
*<items>
* *<item>
* * *<id>1</id>
* * *<label>12345</info>
* * *<!--time: --!>
* *</item>
* *<item>
* * *<id>2</id>
* * *<info>musicplayer.time</info>
* *</item>
* *<item>
* * *<id>3</id>
* * *<label>12346</info>
* * *<!--remaining: --!>
* *</item>
* *<item>
* * *<id>4</id>
* * *<info>musicplayer.duration</info>
* *</item>
* *<item>
* * *<id>5</id>
* * *<label>12347</info>
* * *<!--duration: --!>
* *</item>
* *<item>
* * *<id>6</id>
* * *<info>musicplayer.remaining</info>
* *</item>
* *<item>
* * *<id>7</id>
* * *<label>12348</info>
* * *<!--genre: --!>
* *</item>
* *<item>
* * *<id>8</id>
* * *<info>musicplayer.genre</info>
* *</item>
*</referencelist>
</window>
well the way i implemented it now (new working patch up at sourceforge, id 1200420)
is kinda similar to the way u suggest it, but requires less changes to existing skins, the only differance is that you suggest a global (to the window) sort of reference list, while i've implemented a reference list for each control, which is like it worked before basically, and therefore backwards compatible.
i don't think working with a long list of references makes it easier for the skinner, you have to resort to the list all the time for the id's to use. now they are defined within visible range.
nyway, as i said, i uploaded a tested and working patch which uses my latest suggested format, using localization both in info and in label and dynamic visibility for both label and fadelabel (fadelabel now uses multiple label tags to support this). for as far as i've tested everything is backwards compatible.
feel free to use it in the main cvs... or use those bits u like.. or don't use it at all:)
the [1][2][3] solution just doesnt seem "right". its still order dependant, and its a little clumsy. *i tried to xml-ize it but it didnt really help. *it just made it more confusing.
if its going to be order dependant anyway, why not just make it as simple as possible by*expand label to accept special tokens. *eventually, the use the info tag could be deprecated (but it could continue to be supported for just a single info manager item.)
example:
<label>$localize(12345) $info(musicplayer.time)/$info(musicplayer.duration)</label>
would output something like this:
time: 00:01/05:00
this is somewhat similar to something you proposed earlier. *i just made it more xbmc-like by combining the syntax of the xbmc-dot-commands with the id3 label formatting string.
this should not be difficult to allow backward compatibilty. the plain info tag would still function as it does today. *a label with just a number would function as it does today. *
if label is not a number, then parse it looking for tokens in the form of "$type(parameter)". *i used caps in my example so its easy to see, but the parser should ignore case.
type = localize, means lookup the parameter in strings.xml
type = info, means lookup the parameter from the infomanager
any other characters are just concatenated into the output, like the space and slash in the example.
i'd say if the type or parameter make no sense, then ignore the entire $type(parameter) block, but output a parse error in the log. *or maybe putting some indicator on the screen would be a good idea... maybe the bad $type(parameter) block as is, as if it was just a normal string?
and for completeness, $$ should means its not a token, so just copy the characters until the next $ is encountered.
it's indeed quite similar to my earliest feature request :)
i think using a regex to find matches would be easiest.. just have to figure out the regex parser used by xbmc.
i'll look into it.. when i have time :)
the parse function could also be used for all other controls which have a label (button etc)
ok patch is up on sourceforge... works as mentioned in kraqh3d's last post.
if it gets into csv, use the label = parselabel(label) for all controls containing a label.
njoy!
d.
cool. i'll take a look at it later today... and speaking of regexp engines, i stumbled upon this last night: http://www.pcre.org/
its a open source regexp library thats used by many other popular open source software such as python, apache, php, exim, and nmap. there's links to win32 compiled binaries in both .dll and .lib format. i downloaded them last night, along with the source, but i didnt get a chance to play with it yet.
i didn't use a regex in the end.. using some simple string parsing was enough..
firstly cause the format is quite simple.. secondly.. cause i wasn't in the mood to figure out the regex engine currently used:)
i don't think a regex is faster in this case nyway (mm.. i'll use that as my excuse ;) )
but drop me a line if u got ny questions 'bout it, or i might be on irc.
d.
@dantm
nice work! i like it. i just modified my musicviz skin file to concatenate some items in a single line.
oh.. when (or if) u put it into cvs.. don't forget to take out the debug line in parselabel, its was for my own purposes.. and writes a bit too often (for each render) to the log :)
i didnt commit it yet. *i was playing with some error conditions and noticed something wierd. *it's not a problem with your code, just atoi returns zero for a string thats doesnt match the pattern criteria. *so for example, $localize(foo) prints "my programs".
this is because string 0 = "my programs" in strings.xml. i added a test condition to see if the item in parens is an integer greater or equal to zero. *but, really, i think we need to remove string zero from strings.xml as i'm sure this issue exists elsewhere. (i'm betting all the "ato", "strto", and "wto" functions work similarly.)
yeah.. i already noticed the atoi behaviour.. but as it does not much harm in this case. it will only place a burden on the skinners to change the use of string id 0 if you remove that one.
for sake of correctness we can check for a valid number using cutil::isnaturalnumber(string).
nyway, lets see if there are more interesting things i can patch:)
that's exactly what i did. as i said, it's not a fault with your patch. there's really no harm in it. you just get "my programs" :)
but, it would probably be a good idea to stop using string 0 to avoid unwanted conversion. this way you'll get a null string returned from the global string translator. changing the use of string zero isnt too much of a problem. a simple sed script should be able to replace them all.
and i can't get it to work...
added:
<control>
<description>time</description>
<type>label</type>
<id>1</id>
<visible>player.hasaudio</visible>
<posx>145</posx>
<posy>530</posy>
<info>15400</info>
<info>musicplayer.time</info>
<info>15401</info>
<info>musicplayer.duration</info>
<align>left</align>
<font>font10</font>
</control>
to musicvisualisation.xml
in my strings.xml:
15400: time:
15401: /
it will only show the first "old" tag (in this case): musicplayer.time
it behaves just like one would assume if it only grabbed the first <info> item it understands and ignores the rest, but i'm pretty sure i uploaded a fresh xbe (yep, just doublechecked).
ideas ???
Nuka1195
2005-05-17, 08:12
ok patch is up on sourceforge... works as mentioned in kraqh3d's last post.
if it gets into csv, use the label = parselabel(label) for all controls containing a label.
njoy!
d.
kraqh3d's last post is:
<label>$localize(12345) $info(musicplayer.time)/$info(musicplayer.duration)</label>
haven't tried it though.
indeed that was the problem.. (i used the instructions from sf patch page) (silly me) hehe
oh and btw, maybe a small suggestion. it's mighty annoying when there's no albumart or ie album tag in the media you listen to, would it be possible for a doesexist "thingy"?
similar to player.hasaudio just more general
maybe <visible>$doesexist(musicplayer.album)</visible>
oh and btw, maybe a small suggestion. it's mighty annoying when there's no albumart or ie album tag in the media you listen to, would it be possible for a doesexist "thingy"?
similar to player.hasaudio just more general
maybe <visible>$doesexist(musicplayer.album)</visible>
there is never an excuse for lousy tagging! :)
it is possible, but since we can have more than one info item on a line it should be able to check for more than 1 tag to be present..
maybe i'll look into it ;)
alternatively, if a tag is not present i could skip all text untill the next info item, since it will probably be a delimiter that will look a bit off if there is nothing before it which it can 'delimit'
@dantm
i dont think the visible tag is the right way to handle this. it only controls if the label itself is visible, not a "piece" of the label. besides, it can only handle a single condition.
if the intention is to have "musicplayer.artist - musicplayer.album" only show "album" (and not "- album") if the artist is missing, then check out the setlabel function in guiwindowmusicbase. i *think* it handles these conditions by checking if the previous block returned a value or not.
@dantm
i dont think the visible tag is the right way to handle this. *it only controls if the label itself is visible, not a "piece" of the label. *besides, it can only handle a single condition.
if the intention is to have "musicplayer.artist - musicplayer.album" only show "album" (and not "- album") if the artist is missing, then check out the setlabel function in guiwindowmusicbase. *i *think* it handles these conditions by checking if the previous block returned a value or not.
i agree.. though i think it should check for both the value before as the value after the text, since it's often a delimiter that only needs to be present if _both_ values are present.
i'll look into it.. and dream up some valid solution :)
jmarshall
2005-05-17, 16:17
see spiff's modification to the formatitemlabel (or whatever the function is) in guiwindowmusicbase.cpp
that does pretty much exactly what you want, ignoring delimiters as necessary.
ok.. i made it like this now, it only shows text:
1. if it's between string start and a info item that is not empty
2. if it's between 2 info items that are not empty
3. if it's between an info item that is not empty and string end.
and with text i also mean localized strings.
so you can safely use '$info(musicplayer.artist) $localize(123) and $localize(345) $info(musicplayer.album)' and it will only display everything between the $info tags if both return a valid string (not empty).
things get a bit messy if you would use something like:
'now playing track $info(musicplayer.title) of the album $info(musicplayer.album)'
if the title would be missing only the album name would be rendered, missing the 'now playing' part. as i don't think this will be an issue (yet) i won't put more time in it. i'll rather encourage ppl to tag their files properly :)
i'll test things when i get home, and put up a patch (only guicontrol.cpp).
SuReSHoT
2005-05-17, 19:10
i have to say this is an awesome addition from the skiiner's point of view. :kickass:
i'm still a little new to skinning, so these may may, or may not, be a little noobish, hope ya don't mind. :blush:
1. can this setup use multiple <type>rss</type> tags? i was looking to create one bar for the rss feed, but i would like to add multiple feeds to the same bar, instead of having a bar per feed.
2. if the above is possible, would this setup know to wait for the first rss feed to finish before it would load the next tag?
soryy if the q's are a little noobie, but i've been trying to find a way to reuse the rss bar for multiple feeds, it would be nice to keep them all in one bar, and one .xml for as many feeds as you want.
if none of this is possible, would it be much to request this feature when you have a chance? :bowdown:
thanks for the help, and great job with this setup!
it's currently not possible to do something like that with the parsed label tag.
maybe in the future someone will add it, i never use rss at all myself.. so it probably won't be me :) shouldn't be too difficult i guess.
SuReSHoT
2005-05-17, 21:35
it's currently not possible to do something like that with the parsed label tag.
maybe in the future someone will add it, i never use rss at all myself.. so it probably won't be me :) shouldn't be too difficult i guess.
well, this might sound even nobbier then before but...
(can i even pass "noobbier" off as a word?)
like i mentioned before, i'm still new to playing with the source code, but i'd like to give it a shot anyhow . would you mind giving me a helping hand to locate the proper files i'll need to work with to add this feature? i don't mind making a feeble attempt at it myself, :lookaround: but i kind of need a hand to know what files i'll need to play with, instead of guessing at it.
thanks in advance for any help!
well u'll figure it out soon enough.. i also only started a few days back:)
but as a hand out, look in the guilib for files guirsscontrol (which renders the rss control) and guicontrolfactory which handles control loading.
and if u want it to end up in cvs, communicate with the devs about what u want and what they think of it.. or u might end up building something nobody wants, or in a way nobody wants it :)
SuReSHoT
2005-05-17, 22:21
well u'll figure it out soon enough.. i also only started a few days back:)
but as a hand out, look in the guilib for files guirsscontrol (which renders the rss control) and guicontrolfactory which handles control loading.
and if u want it to end up in cvs, communicate with the devs about what u want and what they think of it.. or u might end up building something nobody wants, or in a way nobody wants it :)
thanks for the pointers, it is greatly appreciated. i don't think i'll bother the dev's just yet about this, i'd rather see if i can pull it off myself. if they decide to use it after it is completed, well, that's all up to them, they are more then welcome to it. i honestly couldn't see why they wouldnt want it if it's already made, but hey that's their call. :)
to be perfectly honest, i want this feature more for myself then anything else. :d i already have a decent list of rss feeds that i use, but so far, i've had to load them in the yarssr script. it would be nice to just have one .xml where you can add as many feeds as you like, and have them just list one after another in a loop, in the same location. it would save the skin from being all cluttered up for those who already have multiple feeds, and it would allow you to really make use of the rss feature. i guess i'm just getting sick of reading the same info over and over. :rolleyes:
thanks again for the qiuck response, i'm going to take a look in the files right now and see how little i really know. (btw, i have no coding skills, but i tend to pick up on it quick, no promises i'll finish this patch anytime this year.. :lol: )
i put up an updated guicontrol.cpp on sourceforge, which implements discussed behaviour (hidding text inbetween items if one of them is not returning anything)..
feel free to patch up.
gr.
dan
cool... i'll check it out later.
Nuka1195
2005-05-18, 02:12
put up an updated guicontrol.cpp on sourceforge, which implements discussed behaviour (hidding text inbetween items if one of them is not returning anything)..
i downloaded the patch after you mentioned this.
i put the following in the home.xml.
<control>
<description>time label</description>
<type>label</type>
<id>1</id>
<posx>525</posx>
<posy>415</posy>
<label>$localize(142) $info(musicplayer.time)/$info(musicplayer.duration)</label>
<align>right</align>
<font>font10</font>
</control>
with no audio playing time:/ shows up. maybe your file didn't update yet??? i noticed the date was may 14.
it works fine when music is playing.
guess it's my time to lecture you :o
<visible>player.hasaudio</visible>
Nuka1195
2005-05-18, 02:29
thank you :bowdown:
Nuka1195
2005-05-19, 09:38
i can not get any $localize(12345) strings to work with the updated guicontrol.cpp.
did the format change?
also, might i suggest a new format.
this is extreme, but say you wanted a line like this.
<label>playing track $info(musicplayer.track) on $info(musicplayer.album) cd</label>
how does your code know what text goes with what $info(). could another seperator be added?
<label>{playing track $info(musicplayer.track) on }{$info(musicplayer.album) cd}</label>
i can not get any $localize(12345) strings to work with the updated guicontrol.cpp.
did the format change?
also, might i suggest a new format.
this is extreme, but say you wanted a line like this.
<label>playing track $info(musicplayer.track) on $info(musicplayer.album) cd</label>
how does your code know what text goes with what $info(). could another seperator be added?
<label>{playing track $info(musicplayer.track) on }{$info(musicplayer.album) cd}</label>
i'll see what happened with the localize strings.
d.
ok i removed the guicontrol.cpp patch since i am not content with the conditional functionality it supplies (not to mention it contained a bug :) ).
i'll be thinking about how to do it properly in the meantime.. probably will be introducing something like $if(condition,value) to support conditions.
i'll let u guys know when i have something else.
ok, the idea i'm implementing now is using $if(condition,value), value can be a literal and in case of a number it will be localized.
the condition will be an additive condition, the first info item will set the state of the bool, any additional info items do or an and or an or on the current state, not is also implemented. ok, i know it sounds vague, but i know what it does :) lol
it basically means that something like:
a or b or c and d or e
is treated as:
((((a or b) or c) and d) or e)
so you could have something like:
now playing $info(musicplayer.title) $if(musicplayer.album,', from the album ') $info(musicplayer.album). [$info(musicplayer.year)$if(musicplayer.year and musicplayer.genre,', ')$info(musicplayer.genre)$if(musicplayer.year or musicplayer.genre and musicplayer.artist,', ')$info(musicplayer.artist), $info(musicplayer.bitrate)$if(not musicplayer.bitrate,'no bitrate available)]
my recommendation however is to make simple conditions, because it will become rather unreadable for those who are not used to boolean logic :)
will test this when i get home.. unless someone has any better ideas :)
i already committed it. *what bug? *it seemed to work fine for me with simple things like:
"$info(musicplayer.artist) - $info(musicplayer.album)" where i intentionally had the artist missing from the tag.
i donno about these conditionals. *its getting way too complicated now. *i dont think it needs to be any "better" than how the track formatter works.
i already committed it. *what bug? *it seemed to work fine for me with simple things like:
"$info(musicplayer.artist) - $info(musicplayer.album)" where i intentionally had the artist missing from the tage.
i donno about these conditionals. *its getting way to complicated now.
yeah info worked, localize didn't.
i agree these conditionals look a bit more complicated, but are also a lot more flexible.
your example would become:
"$info(musicplayer.artist)$if(musicplayer.artis t and musicplayer.album,' - ')$info(musicplayer.album)"
not too complicated yet. as i said, i suggest keeping it simple. but at least u can make it as complex as u like now.
what do you mean localize didnt? something like this:
"$info(musicplayer.artist)$localize(12345)$info(mus icplayer.album)" would still show the localized string?
u were replying while i was editting... this is key line:
i dont think it needs to be any "better" than how the track formatter works.
*edit*
ah, forget it, i dont care as long as the simple way continues to work where missing tags remove adjoining text blocks.
what do you mean localize didnt? *something like this:
"$info(musicplayer.artist)$localize(12345)$info(mus icplayer.album)" would still show the localized string?
no $localize didn't /doesn't work at all, it will never write the localized string... somehow i never tested that:)
i disagree about not getting better.
a string like "now playing (artist) with track (track)" would also remove the "now playing" part if the artist is not available. the solution only worked well for simple, non textual delimiters. my new suggestion works for (almost) anything.
lol...
well.. i can't really have both solutions... cause the new idea always renders literal texts, while they old idea renders literal texts conditionally... :)
i'll check out why the localized strings arent added to the output string. an append is probably missing someplace :)
i dont understand why cant you have both. the $if is a new control type. anything without an $if should be subjected to the old rules.
anyway, i think this is overkill and unwarranted.
jmarshall
2005-05-19, 16:49
another thing to keep in mind is that this has to be performed every frame, for every label control or fadelabel control, so any solution that is finalized must be as optimal as possible.
i agree that less complexity is better, and can't really think of any useful scenarios in which the more complicated one is necessary that can't be overcome with using 2 or more label controls.
cheers,
jonathan
i'll check out why the localized strings arent added to the output string. an append is probably missing someplace :)
i dont understand why cant you have both. *the $if is a new control type. *anything without an $if should be subjected to the old rules. *
anyway, i think this is overkill and unwarranted.
no, it's not a missing append, the code just sucks a little:)
i'll see if i can find a way to incoorporate both rules.
d.
-edit-
oh well .. nm.. see if u can fix the localize.. i hate to swap solutions back nd forth.. nd i don't use conditional stuff myself nyway.. since i just have everything tagged properly:)
i _think_ this should fix the localize issue:
cstdstring cguicontrol::parselabel(cstdstring &strlabel)
{
*cstdstring tostring = l"";
*cstdstring queuestring = l"";
*int lastpos = 0;
*bool lastvalid = true;
*//look for parsable item
*int t = strlabel.find('$');
*//while a parsable item is found
*while ( t>=0 )
*{
* *int skip = 0;
* *cstdstring checkescape = l"";
* *//read next char
* *if (t+1 < (int)strlabel.length())
* *{
* * *checkescape = strlabel.substr(t+1,1);
* *}
* *bool emptyinfo = false;
* *//check if it's not a $, if it is then escape
* *if (!checkescape.equals("$"))
* *{
* * *//write all text since the last parsable item till this one to the literal text queue
* * *if (t > lastpos)
* * *{
* * * *cstdstring tempstring = strlabel.substr(lastpos,t-lastpos);
* * * *//replace escaped char
* * * *tempstring.replace("$$","$");
* * * *queuestring.append(tempstring.c_str());
* * *}
* * *cstdstring replacestring = l"";
* * *int startdata = strlabel.find('(',t);
* * *int enddata = strlabel.find(')',t);
* * *//look for value delimiters
* * *if (startdata > t && enddata > startdata)
* * *{
* * * *cstdstring strtype = strlabel.substr(t+1,(startdata - t)-1);
* * * *cstdstring strvalue = strlabel.substr(startdata+1,(enddata - startdata)-1);
* * * *//if valid delimiters are found try to parse them
* * * *strtype = strtype.tolower();
* * * *if (strtype.equals("info"))
* * * *{
* * * * *int info = g_infomanager.translatestring(strvalue);
* * * * *if (info)
* * * * *{
* * * * * *replacestring = g_infomanager.getlabel(info);
* * * * * *emptyinfo = (replacestring.length() == 0);
* * * * *}
* * * * *lastpos = enddata +1;
* * * * *skip = (enddata - t);
* * * *}
* * * *else if (strtype.equals("localize"))
* * * *{
* * * * *//check if it's a valid number
* * * * *if (cutil::isnaturalnumber(strvalue))
* * * * *{
* * * * * *int localize = atoi(strvalue);
* * * * * *if (localize)
* * * * * *{
* * * * * * *//if a localized string is found add it to the literal text queue
* * * * * * *cstdstring localizestring = g_localizestrings.get(localize);
* * * * * * *queuestring.append(localizestring.c_str());
* * * * * *}
* * * * * *lastpos = enddata +1;
* * * * * *skip = (enddata - t);
* * * * *}
* * * *}
* * *}
* * *// we have a valid infoitem
* * *if (replacestring.length() > 0)
* * *{
* * * *//if there is text in the queue write it
* * * *if (queuestring.length() > 0)
* * * *{
* * * * *tostring.append(queuestring.c_str());
* * * *}
* * * *//empty literal text queue string
* * * *queuestring = l"";
* * * *//now write info string
* * * *tostring.append(replacestring.c_str());
* * * *lastvalid = true;
* * *}
* * *else if (emptyinfo)
* * *{
* * * *//clear the queue
* * * *queuestring = l"";
* * * *lastvalid = false;
* * *}
* *}
* *else
* *{
* * *skip = 1;
* *}
* *if (t+skip < (int)strlabel.length())
* *{
* * *//try to find the next one
* * *t = strlabel.find('$',t+skip + 1);
* *}
* *else
* *{
* * *//past end of line, stop searching
* * *t = -1;
* *}
*}
*//if any text was leftover after the last parsable tag, add it to the literal text queue
*if (lastpos < (int)strlabel.length())
*{
* *cstdstring tempstring = strlabel.substr(lastpos,(int)strlabel.length()-lastpos);
* *tempstring.replace("$$","$");
* *queuestring.append(tempstring.c_str());
*}
*//if the last info item was valid, append the literal text queue to the result string
*if (lastvalid && queuestring.length() > 0)
*{
* *tostring.append(queuestring.c_str());
*}
*return tostring;
}
Nuka1195
2005-05-19, 23:48
does you code allow for prefix and suffix text to be conditionally shown?
i redid the parselabel so it works like this.
you must have everything you want parsed in curly brackets. if there is not a matching pair of brackets, it doesn't parse it. if there is a least one pair, it will ignore anything outside of a pair. i did this to streamline the code. it forces more strict skinning, but it's probably better.
example: {it is }{$info(weather.conditions)outside and }{$info(weather.temperature)}
if weather.conditions was blank for example, it would return:
it is 55f (with the degree sign)
the conditional values control everything in there block. i just need to clean it up and do some more testing. if you think you might use this then i'll finish it. i could see a real benefit for the fadelabel.
but if weather.temperature would be blank it would still write 'outside and ' at the end... which would be rather meaningless.
for a perfect solution you _will_ have to incorporate conditional expressions... but as the devs consider it getting too complex and i don't use it myelf i will not continue on that path.
Nuka1195
2005-05-20, 00:06
you're right.
Nuka1195
2005-05-20, 07:08
ok, i have it working like the following:
all info must be enclosed in {}. any text in with an $info() tag, will be dependent on there being info.
<label>{album: $info(musicplayer.album)}{ by }{$info(musicplayer.artist)}</label>
you notice the { by }, if there are no $info() tags then that block relies on both sides having info.
i'll clean it up and test more with $localize().
if you would have:
<label>{album: $info(musicplayer.album)}{, by }{$info(musicplayer.artist)}{, in the year }{$info(musicplayer.year)}</label>
and artist is not available, it will concat album and year info without delimiters
thanks. that fix worked. the localized strings now are visible when appropiate.
Nuka1195
2005-05-20, 15:51
:nuts: why can't people tag things correctly.
well it isn't perfect, but it does give some control to the skinner and would work for simple strings. probablt isn't worth it though.
oh well.
:nuts: *why can't people tag things correctly.
well it isn't perfect, but it does give some control to the skinner and would work for simple strings. probablt isn't worth it though.
oh well.
it's not always a matter of tagging... if you play shoutcast streams or for example a wav file a lot of info is missing. i usually only play fully tagged mp3's so for me there is no need for conditionality at all.
was this ever finalized ???
if so, could a dev tell me what we got in cvs at the moment and how it works ? this whole thread is very confusing
sorry, ive been away for a few weeks. this has been in cvs for a while without the fancy conditionals. to concatentate infotags and localized strings you need to use control words which are parsed by the label control -- $localize() and $info(). anything else is assumed to be text.
the example from the changelog is:
<label>$localize(171) $info(musicplayer.artist)</label>
this will produce (in english):
artist: u2
missing fields in the middle will result in text seperators getting removed similar to how the tag formatting works in my music.
jmarshall
2005-07-12, 01:08
just squashed another bug in this, and have just realized this is being called for every label, every frame.
this seems a little wasteful.
perhaps a way around it would be to have it setup in the <info> tag, and if the <info> tag is not parsed (in guicontrolfactory::create()) to a number, have it as an additional string variable.
the label control then just needs to check this variable at render time, and only processes the parselabel() code (which mayaswell go in the infomanager) when it needs it.
thoughts?
edit: not really wasteful at all, as only labels with $ in them actually get parsed!
cheers,
jonathan
so you've fixed it so that only labels using the special tags are parsed? i can add this information to the new skinning page about label controls:
http://manual.xboxmediacenter.de/wakka.p....&v=13st (http://manual.xboxmediacenter.de/wakka.php?wakka=labelcontrol&v=13st)