Export: Use of $put/$get across nested loops?

Hello,

I found some slightly dated entries in the forums that stated the use of user variables created by $put could not be referenced within a "nested" (or "sub") loop. Can someone please tell me if this restriction is still correct?

I was hoping to be able to $put the %_counter% value from one loop so that I could build a concise ID for each %albumartist%/%album% combination. Something like this:

$filename(loopcheck.txt,utf-8)
$loop(%albumartist%)$puts(aanum,%_counter%)
$loop(%_album%)$get(aanum)

    .
. 
$loopend()

$loopend()

Thank you!

-Mike-

E.g. such a script:

$filename(csv,utf-16)
$loop(%_path%)
$loop(%_filename%)
$puts(fs,$add($get(fs),%_file_size%))
$loopend()
$loopend()
$get(fs)

outputs fs at the end, outside the loops.

Find some useful links there ...
In einer Aktion die Größe eines Verzeichnis ermitteln?

DD.20170219.1857.CET

Thanks for the response and suggestion.

Should I infer from the responses that the restriction mentioned in the forum is still in place?

Unfortunately, I cannot use your suggestion of accessing the user variable after the loop is closed as I am not trying to obtain a sum or total information. Instead, I was hoping to use "current" counter information from both loops within the nested %album% loop.

What I was hoping to do was to capture the current %_counter% value during an active loop on %albumartist%. Then in the active nested loop on %album% capture the current %_counter% value again - this time for the current %album% %_counter%. Then, in this nested/open loop, combined the two counters to make a unique Album Artist/Album identifier in the form of AAnnnnnALnnn that could be used for the ID=value in generated HTML. This solution would be cleaner than simply concatenating the (very long) %albumartist% and %album% fields and more precise trying to hash the %albumartist% field to come up with a unique identifier.

Thanks again,

Mike

Can't you just create a little prototype with your loop-construction and then see if you get the right values?
This is all very theoretical.

Of course.

The following files are attached.
(1) loopcheck.mte is a test export script that illustrates the problem I encountered with $put/$get across nested loops.
(2) loopcheck_output.txt is the output file. Please open this as as a .csv file so that the output is a little easier to read.
(3) sample_library.txt is a brief listing of the sample library used to describe the problem. For illustration purposes this library contains only a very few AlbumArtists, Albums and tracks.

The sample export script is shown here:

$filename(loopcheck.txt,utf-8)
Begin End,Loop,Current %%_counter%%,Saved AAnum,Saved ALnum,Album Artist,Album Name,Title
$loop(%albumartist%)$puts(aanum,%_counter%)Begin,AlbumArtist,%_counter%,AA$num($get(aanum),5),,%albumartist%
$loop(%album%)$puts(alnum,%_counter%)Begin,Album,%_counter%,AA$num($get(aanum),5),AL$num($get(alnum),3),%albumartist%,%album% 
$loop(%track%)Begin,Track,%_counter%,AA$num($get(aanum),5),AL$num($get(alnum),3),%albumartist%,%album%,%title%
$loopend()End,Track
$loopend()End,Album
$loopend()End,Albumartist

This test case reveals that the current value of the stored ($put) variables are not available to a nested $loop. Instead, the value returned via $get in the nested loop appear to be from the prior iteration of the parent loop.

In the loopcheck_output.txt this is what I am seeing:

  1. In the first time through parent loop - $loop(%albumartist%) – the %_counter% value is 1 and is stored into a variable.
a. Then in a child loop -$loop(%album%) – the stored value is $get’d but a zero is returned. This value is incorrect. b. Next, the current value of %_counter% from the child loop is stored into a different variable. This value is again 1 (and is correct for the first time through the album loop. c. Then within the active loop on %album% a third loop on %track% is started. This loop $get’s both values. Both values are returned as 0 which is incorrect.
2. In the second time through the parent %albumartist% loop, the values returned in both child loops are still incorrect, but have been incremented by 1. 3. This pattern continues for each iteration of the parent loop.

Hopefully this makes it clear.

sample_library.txt (1023 Bytes)

loopcheck.mte (540 Bytes)

loopcheck_output.txt (2.79 KB)

Ohrenkino,

It certainly looks like an error to me. Do you have any suggestions?

Thanks,

Mike

I think that the basic misunderstanding is the initialization of the %_counter%

Your originial code showed
$loop(%albumartist%)$puts(aanum,%_counter%)Begin,AlbumArtist,%_counter%,AA$num($get(aanum),5),,%albumartist%

but when you $puts %_counter% into aanum the %_counter% has not counted anything yet.

The first count happens later in ...Begin,AlbumArtist,%_counter%,

So it would be better to shift $puts(aanum,%_counter%) behind %_counter:
$loop(%albumartist%)Begin,AlbumArtist,%_counter%,$puts(aanum,%_counter%)AA$num($get(aanum),5),,%albumartist%

The same applies to the other loops.
See if this makes it better.

Ohrenkino,

A copy of the second test case loopcheck2.mte and output are attached. Unfortunately, the results are still incorrect.

Please note that within each $loop there is a $get following the $puts. This verifies that within the same loop, the value returned by the $get is identical to what was stored by the $puts.

The problem remains that within the nested loop, the value returned by $get is not correct: If it’s the first time through, null values are returned instead of the correct values stored in the parent loop. If it’s not the first time through, then the values that are returned are from the prior iteration of the parent loop.

This is neither intuitive nor crystal clear, but I believe this is what is occuring.

In order to eliminate %_counter% as a contributing factor, I created a third test case. In this case I created two additional user variables and stored (via $puts) the %albumartist% within the $loop(%albumartist%) and also stored %album% within the nested $loop(%album%).

This test case illustrates the identical problem. Namely, when the %albumartist% is $puts’d within the $loop(%albumartist%) and then $get’d within the nested $loop(%album), the first time through null values are returned. On subsequent iterations the values returned by $get within the nested loop are what had been stored in the prior iteration of the parent loop and is not the expected current value.

This is illustrated by loopcheck3.mte and it’s associated output. If you rename the output .txt files to .csv and open them with excel they are a little easier to read.

Hopefully this is as clear as it can be.

Thanks again for helping to investigate this situation. I await your review and suggestions.

Thanks,

Mike

loopcheck2.mte (541 Bytes)

loopcheck3.mte (689 Bytes)

loopcheck2.txt (2.71 KB)

loopcheck3.txt (4.05 KB)

OK, got it:
each set of variables is local to a loop.
The aanum you set in the artist loop is a different aanum that you set in the album loop.
What you see is the value in the current loop.

So you have to think of a clever loop and text design that uses $if() constructions to notice the change in artist and album and then increment the user-variable on that trigger.
But all these changes have to be within the same loop like
$loop(artist)
$loop(album)
$loop(title) $if(oldartist<>artist then set oldartist=artist, $add(aanum,1)...
output: aanum alnum title
$loopend()
$loopend()
$loopend()

I think I have all said and written about the visibility of $put/$puts some time ago.
There you can find a mte script, which demonstrates the behaviour ...
Check if field value is identical for all selected tracks

Maybe I'm blind to this thread problem because I've been taking such a long break with Mp3tag export scripting, but a further test on Mp3tag v2.81 makes me fear that something is wrong.

Run this export script and check the result ...

$filename($getEnv('USERPROFILE')'\Desktop\LoopCheck.txt',UTF-8) '20170225.Mp3tag.LoopCheck' $loop(1,1)'aanum='$put(aanum,0)$loopend() 'aanum='$get(aanum)' ???' '---' '#loop albumartist'$loop(%ALBUMARTIST%) 'aaname='%ALBUMARTIST% 'aanum='$put(aanum,$add(1,$get(aanum))) '#loop album'$loop(%ALBUM%) 'aaname='%ALBUMARTIST% 'aanum='$get(aanum) 'album='%ALBUM% $loopend()'#loopend album' $loopend()'#loopend albumartist'

I did the test on 3 files, having fields and values ...
ALBUMARTIST=AlbumArtist_1; ALBUM=Album_1_1
ALBUMARTIST=AlbumArtist_2; ALBUM=Album_2_1
ALBUMARTIST=AlbumArtist_2; ALBUM=Album_2_2

... and got this output ...

20170225.Mp3tag.LoopCheck aanum=0 aanum=2 ??? --- #loop albumartist aaname=AlbumArtist_1 aanum=1 #loop album aaname=AlbumArtist_1 aanum=0 album=Album_1_1 #loopend album aaname=AlbumArtist_2 aanum=2 #loop album aaname=AlbumArtist_2 aanum=1 album=Album_2_1 aaname=AlbumArtist_2 aanum=1 album=Album_2_2 #loopend album #loopend albumartist

Have a look at the values of variable aanum, ...
there might be different failures, ...
especially a calculation failure of -1 when the variable is read within another loop construct.

DD.20170225.1028.CET

I did another test with a modified export script ...
... which creates a better result ...

$filename($getEnv('USERPROFILE')'\Desktop\LoopCheck.2.txt',UTF-8) '20170225.Mp3tag.LoopCheck.2' $loop(0)'aanum='$put(aanum,0) 'aanum='$get(aanum)' '$if($eql(0,$get(aanum)),'','') '---' '#loop albumartist'$loop(%ALBUMARTIST%) 'aaname='%ALBUMARTIST% 'aanum='$put(aanum,$add(1,$get(aanum))) '#loop album'$loop(%ALBUM%) 'aaname='%ALBUMARTIST% 'aanum='$add(1,$get(aanum)) 'album='%ALBUM% $loopend()'#loopend album' $loopend()'#loopend albumartist' $loopend()

... and got this output ...

20170225.Mp3tag.LoopCheck.2 aanum=0 aanum=0 --- #loop albumartist aaname=AlbumArtist_1 aanum=1 #loop album aaname=AlbumArtist_1 aanum=1 album=Album_1_1 #loopend album aaname=AlbumArtist_2 aanum=2 #loop album aaname=AlbumArtist_2 aanum=2 album=Album_2_1 aaname=AlbumArtist_2 aanum=2 album=Album_2_2 #loopend album #loopend albumartist

DD.20170225.1655.CET

I was able to recreate your results with both scripts. The first script clearly identifies the problem and the second "adjusts" the values returned to match what was expected. This method, along with some brilliant (yet messy) $if(...) logic suggested by ohrenkino provide a viable way to circumvent the problem in this particular case.

This logic satisfies my particular need where the values being passed between $loops(...) are numeric and increment with each iteration. If others have a need to pass data which was not numeric or followed a different pattern this circumvention may not work for them.

What is the proper procedure to request that this problem be corrected in some future release of Mp3tag?

Thanks very much for your help!

-Mike-