Skip to main content

Notice

Please note that most of the software linked on this forum is likely to be safe to use. If you are unsure, feel free to ask in the relevant topics, or send a private message to an administrator or moderator. To help curb the problems of false positives, or in the event that you do find actual malware, you can contribute through the article linked here.
Topic: foo_playlist_tree (Read 713976 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

foo_playlist_tree

Reply #1625
Is there a way to send different queries to different playlists? I see that Scheme has:

Code: [Select]
(add-to-playlist handle [playlist-index] [item-index]) => if no playlist-index is specified, active playlist is assumed.


But I am not sure how I would implement that with a mouse or keyboard action.


It's possible in scheme.  And once you've gotten the scheme query written, you can assign the query refresh to a keystroke or button using the Main Menu refresh options (under libarary->Playlist Tree->Refresh).
There used to be a link to my website here.

foo_playlist_tree

Reply #1626
Starting to have some success with scheme queries now - it is a very subtle but powerful language!

Is it possible to access the value of a tag (e.g. artist, track, or my user-defined tag "opus")  in a scheme query to use elsewhere in scheme code?

foo_playlist_tree

Reply #1627
Starting to have some success with scheme queries now - it is a very subtle but powerful language!

Is it possible to access the value of a tag (e.g. artist, track, or my user-defined tag "opus")  in a scheme query to use elsewhere in scheme code?


absolutely.  What are you trying to do?
There used to be a link to my website here.

foo_playlist_tree

Reply #1628

Starting to have some success with scheme queries now - it is a very subtle but powerful language!

Is it possible to access the value of a tag (e.g. artist, track, or my user-defined tag "opus")  in a scheme query to use elsewhere in scheme code?


absolutely.  What are you trying to do?



I'm trying to query the database to find any other tracks with the same composer and title as that playing but which has an "opus" tag.

I'm (currently) stuck on building the filter string for the query and then building the name for the playlist. (I've hard-coded them into the code for the present). I'm not sure how to build get tag values (meta-tag()? ) and build strings?

In any case, although I can run the db query with a filter of form e.g. "composer is schubert" it does not run with a filter of a longer form e.g. "composer is schubert AND title is die forelle AND NOT opus MISSING" (even when hard-coded.)

I want to make and activate a playlist with the composer, title and opus number as its name. Then I'll pick up the name of the active playlist in panels_ui and make a button to set the opus of the playing track (after checking the composer and title match)!

Here's my code ( such as it is):

Code: [Select]
(let (        (playlistname '"OPUS3")  
               (filter "(composer HAS schubert AND title has forelle)")
       )  
      (let (
            (handle (now-playing))
            )
           (let (  
                  (title (format-title handle "%composer% %title%" ) )
                 )  
            (add-to-playlist handle playlist-index)
            (add-node handle (list title)
           )
      )

    (for-each-db-entry
           (lambda (handle)
                        (begin
                              (add-node handle (list (format-title handle "DB: %title% %opus%"  )))
                        )
             )
   filter
      )

  (let (
               (playlist-index (find-or-create-playlist playlistname))
        )
        (clear-playlist playlist-index)
        (activate-playlist playlist-index)
  )



I'm learning by doing ... and enjoying it as the power of the list processing languages is amazing, but I'd be grateful for any help you can give.

foo_playlist_tree

Reply #1629
It's possible in scheme.  And once you've gotten the scheme query written, you can assign the query refresh to a keystroke or button using the Main Menu refresh options (under libarary->Playlist Tree->Refresh).


Would you mind showing me the code to do this?

My current code not using scheme is:

Criteria:
%last_played% HAS 20

Format:
$cwb_datediff(%last_played%,%cwb_systemdate%) days ago|[%artist% - ]%title%

Population Order:
$num($cwb_datediff(%last_played%,%cwb_systemdate%),3)$sub(100,$substr(%last_played%,12,13))

 

foo_playlist_tree

Reply #1630
I'm trying to query the database to find any other tracks with the same composer and title as that playing but which has an "opus" tag.

I'm (currently) stuck on building the filter string for the query and then building the name for the playlist. (I've hard-coded them into the code for the present). I'm not sure how to build get tag values (meta-tag()? ) and build strings?

In any case, although I can run the db query with a filter of form e.g. "composer is schubert" it does not run with a filter of a longer form e.g. "composer is schubert AND title is die forelle AND NOT opus MISSING" (even when hard-coded.)

I want to make and activate a playlist with the composer, title and opus number as its name. Then I'll pick up the name of the active playlist in panels_ui and make a button to set the opus of the playing track (after checking the composer and title match)!

This should get you close.  I couldnt test it myself because I dont have the same tags, so there could be some errors.

BTW, I think part of the problem with your original filter string is that case is important.  all the keywords such as IS, HAS, MISSING, NOT, AND must be uppercase.

Code: [Select]
(let ((playing (now-playing)))
  (let ((composer (format-title playing "%composer%"))
(title (format-title playing "%title%")))
    (let ((filter
  (string-append "composer IS " composer
  " AND title IS " title
  " AND NOT opus MISSING"))
  (item-found #f))
      (for-each-db-entry
      (lambda (handle)
(let* ((opus (format-title handle "%opus%"))
(playlist-name
(string-append composer " - " title " - " opus)))
  (add-to-playlist handle
    (find-or-create-playlist playlist-name))))
      filter))))
There used to be a link to my website here.

foo_playlist_tree

Reply #1631
It's possible in scheme.  And once you've gotten the scheme query written, you can assign the query refresh to a keystroke or button using the Main Menu refresh options (under libarary->Playlist Tree->Refresh).

Would you mind showing me the code to do this?

<snip>

Here's the original query converted into scheme:

Code: [Select]
(for-each-db-entry
 (lambda (handle)
  (let ((days (format-title
handle
"$cwb_datediff(%last_played%,%cwb_systemdate%) days ago"))
(leaf
  (format-title
  handle
  "[%artist% - ]%title%")))
    (add-node handle (list days leaf))))
 "%last_played% HAS 20"
 "$num($cwb_datediff(%last_played%,%cwb_systemdate%),3)$sub(100,$substr(%last_played%,12,13)")

Here's a version that puts the tracks into separate playlists based on when they were last played.  It only uses tracks that have been played within 2 weeks.

Code: [Select]
(let ((cleared-list ()))
  (for-each-db-entry
  (lambda (handle)
    (let ((days (format-title
  handle
  "$cwb_datediff(%last_played%,%cwb_systemdate%) days ago"))
  (leaf
    (format-title
    handle
    "[%artist% - ]%title%")))
      (let ((p-index (find-or-create-playlist days)))
(when (not (member days cleared-list))
      (clear-playlist p-index)
      (set! cleared-list (cons days cleared-list)))
(add-to-playlist handle p-index))))
  "%last_played% HAS 20 AND \"$cwb_datediff(%last_played%,%cwb_systemdate%)\" LESS 14"
  "%last_played%"))
There used to be a link to my website here.

foo_playlist_tree

Reply #1632
Excellent , time to play.

Is there any reason this doesn't work:

Code: [Select]
$ifgreater(2,@quote<@format<%_itemcount%>>,,VA|)


Hmm, seems this would produce some sort of recursive error

foo_playlist_tree

Reply #1633
Excellent , time to play.

Is there any reason this doesn't work:

Code: [Select]
$ifgreater(2,@quote<@format<%_itemcount%>>,,VA|)


Hmm, seems this would produce some sort of recursive error


Where are you trying to put that?
There used to be a link to my website here.

foo_playlist_tree

Reply #1634
I'm trying to query the database to find any other tracks with the same composer and title as that playing but which has an "opus" tag.

I'm (currently) stuck on building the filter string for the query and then building the name for the playlist. (I've hard-coded them into the code for the present). I'm not sure how to build get tag values (meta-tag()? ) and build strings?

In any case, although I can run the db query with a filter of form e.g. "composer is schubert" it does not run with a filter of a longer form e.g. "composer is schubert AND title is die forelle AND NOT opus MISSING" (even when hard-coded.)

I want to make and activate a playlist with the composer, title and opus number as its name. Then I'll pick up the name of the active playlist in panels_ui and make a button to set the opus of the playing track (after checking the composer and title match)!

This should get you close.  I couldnt test it myself because I dont have the same tags, so there could be some errors.

BTW, I think part of the problem with your original filter string is that case is important.  all the keywords such as IS, HAS, MISSING, NOT, AND must be uppercase.

Code: [Select]
(let ((playing (now-playing)))
  (let ((composer (format-title playing "%composer%"))
(title (format-title playing "%title%")))
    (let ((filter
  (string-append "composer IS " composer
  " AND title IS " title
  " AND NOT opus MISSING"))
  (item-found #f))
      (for-each-db-entry
      (lambda (handle)
(let* ((opus (format-title handle "%opus%"))
(playlist-name
(string-append composer " - " title " - " opus)))
  (add-to-playlist handle
    (find-or-create-playlist playlist-name))))
      filter))))


Thanks very much - it works well, first time!

I didn't realise about needing upper-case for the query keywords - (I realised last night that I had had the full filters working OK and couldn't figure why they didn't work now. I guess I changed their case when retyping etc.) It might be useful if the wiki states that tyeh keywords must be in capitals (or maybe it does and I didn't notice).

(Looking forward to doing more with scheme: I've already built a master index - single list with artists, albums, composer in alphabetical order - I'm going to add the entries "last, first" as well as "first last" (using your strchr function) and group under initial letters!

Looking at the primitives - should there be one to delete a playlist? delete a playlist entry? etc..

foo_playlist_tree

Reply #1635
There's a built in Scheme interpreter in Playlist Tree these days for really advanced quieries.

I don't know that your problem can be solved using regular titleformatting, but I know that it can using scheme, as I did something similar for a user on the playlist tree forum.

Thanks, but I don't quite get where the code snippets should be entered. Criteria? Or Format? I've tried both, and nothing happens. (I did of course add a tag called "credits" with the same syntax to a few test tracks.)

I don't quite get the Scheme language. I've tried looking at the Scheme code snippets here and comparing them to their TAGZ counterpart, but I don't get it. Is there a place where I can learn it in this context, a place with examples and descriptions? I especially need some syntax reference, I mean, I don't even have any idea what the "let" thing does.

foo_playlist_tree

Reply #1636
Nevermind, I made it! Originally, I had the same problem as described here. However, I made some changes and tried using variables. It worked perfectly!

Here's my code (I'm using the %involved people list% tag).

Criteria:
Code: [Select]
NOT involved people list MISSING


Format:
Code: [Select]
$puts(ip,%<involved people list>%)
$substr($get(ip),1,$add($strchr($get(ip),'('),-2))|$substr($get(ip),$add($strchr($get(ip),'('),1),$add($strrchr($get(ip),')'),-1))|%title%

This way, I will firstly get the involved people, then their roles as "subfolders". I've not done anything more interesting, I just wanted to get it working. Now it works, and I'll get to polish it and make it the way I want (basically adding more subfolders, like album).

The syntax I use when entering information into INVOLVED PEOPLE LIST is
Code: [Select]
name1 (role1); name2 (role2); name3 (role3)


For anyone struggling with the same problem, here's details:

First, I created this:
Code: [Select]
$substr(%<involved people list>%,1,$strchr(%<involved people list>%,''))|%title%

This was the one that didn't work. It was supposed to take all the involved persons and include the tag value up to the first parenthesis (where the role part begins). However, I just ran into the problem I mentioned earlier.

So, I went on to defining a variable:
Code: [Select]
$puts(ip,%<involved people list>%)

I didn't know what this would actually do - would it parse the whole tag and put every matching value into the variable, or would it parse the first part of the tag (the first person), finish the subfolders here and then move on to the next part (person)? Turns out it was the latter, and thank God for that. (Sorry if that was a messy description, I'm not that good with this stuff.)

So, the rest was easy. I added another line, the complete script now looked like this:
Code: [Select]
$puts(ip,%<involved people list>%)
$substr($get(ip),1,$strchr($get(ip),'('))|%title%

This would give names such as Todd Wilson (, Mark Smith ( etc. So, I just fooled around a bit with the $add() function to remove the two latter characters (the opening parenthesis and the space before that). Now it looked like this:
Code: [Select]
$puts(ip,%<involved people list>%)
$substr($get(ip),1,$add($strchr($get(ip),'('),-2))


So, for the last part, I wanted to have roles as subfolders. I did pretty much the same here - I used $strchr() and $strrchr() to get the character position for the opening and closing parentheses, used the $add() function to remove the parentheses themselves and ended up with the result at the top of this post. Hope this helps people.

Edit: The only drawback with my INVOLVED PEOPLE LIST formatting used in conjunction with my script, is that I can not have parentheses in names or in the roles themselves, parentheses can only be used for denoting a role. For example: If I enter
Code: [Select]
Mike (Michael) Smith (guitar)

it will show up as the name "Mike" and the role "Michael) Smith (guitar". This can be fixed in two ways - either by changing the whole syntax used for entering information (which might be an idea), or by making the script find the last occurence of the opening parenthesis, and not the first occurence like I have done here (however, the latter does still not allow parentheses inside the role string).

foo_playlist_tree

Reply #1637
I'm trying to query the database to find any other tracks with the same composer and title as that playing but which has an "opus" tag.

I'm (currently) stuck on building the filter string for the query and then building the name for the playlist. (I've hard-coded them into the code for the present). I'm not sure how to build get tag values (meta-tag()? ) and build strings?

In any case, although I can run the db query with a filter of form e.g. "composer is schubert" it does not run with a filter of a longer form e.g. "composer is schubert AND title is die forelle AND NOT opus MISSING" (even when hard-coded.)

I want to make and activate a playlist with the composer, title and opus number as its name. Then I'll pick up the name of the active playlist in panels_ui and make a button to set the opus of the playing track (after checking the composer and title match)!

This should get you close.  I couldnt test it myself because I dont have the same tags, so there could be some errors.

BTW, I think part of the problem with your original filter string is that case is important.  all the keywords such as IS, HAS, MISSING, NOT, AND must be uppercase.

Code: [Select]
(let ((playing (now-playing)))
  (let ((composer (format-title playing "%composer%"))
(title (format-title playing "%title%")))
    (let ((filter
  (string-append "composer IS " composer
  " AND title IS " title
  " AND NOT opus MISSING"))
  (item-found #f))
      (for-each-db-entry
      (lambda (handle)
(let* ((opus (format-title handle "%opus%"))
(playlist-name
(string-append composer " - " title " - " opus)))
  (add-to-playlist handle
    (find-or-create-playlist playlist-name))))
      filter))))


This is working well - but I haven't been able to get it to activate one of the generated playlists just before it exits! I'd really appreciate your showing me what to do...

I've got it activating the playlist!  - using a BEGIN to group the commands. I'd be interested to see how you would have done it, if you have some time some time.

foo_playlist_tree

Reply #1638
This looks like it i sgoing to be a very powerful component - once the scheme language is understood.


Meanwhile, I'm trying to build an index of artists which includes them twice - once as

      John Smith

and once as

        Smith, John


No problem getting either way (using ordinary PTP queries) but I can't seem to combine them in a single query. Any ideas?


I've done this now - I can put up my code if anyone is interested .

foo_playlist_tree

Reply #1639
Upload it please, I'm interested too.

foo_playlist_tree

Reply #1640
Upload it please, I'm interested too.


This is my scheme preferences code:

(remove-whitespace, strchr & split came from CWBowron's PLT forum; strip came from the web but flip and initial-and-string are my first scheme procedures - or whatever they are called in scheme!)


Code: [Select]

(define (remove-whitespace str)
  (let ((len (string-length str)))
(do ((start 0 (+ 1 start)))
((or (>= start len)
(not (char=? #\space (string-ref str start))))
(do ((end (- len 1) (- end 1)))
((or (<= end start)
  (not (char=? #\space (string-ref str end))))
  (substring str start (+ 1 end))))))))

(define (strchr str chr start)
  (cond
((>= start (string-length str)) #f)
((char=? (string-ref str start) chr) start)
(else (strchr str chr (+ 1 start)))))

(define (split str chr)
  (let ((mid (strchr str chr 0)))
(if mid
(list (remove-whitespace (substring str 0 (- mid 1)))
  (split (substring str (+ mid 1) (string-length str) chr))
)
#f)))
; strip : string -> string
;  remove white space from the beginning and end of a string
(define strip
  (let ([r-strip (regexp "^[ \t\r]*(.*?)[ \t\r]*$")])
(lambda (s)
  (cadr (regexp-match r-strip s)))))

(define (flip str chr sep )
  (let ((mid (strchr str chr 0)))
(if mid
  (strip (string-append (strip (substring str (+ mid 1) (string-length str)))
  (if  (string? sep) sep (make-string 1 sep) )  (strip (substring str 0  mid  ))))
#f)))

(define (initial-and-string str)
  (if (> (string-length str) 2)
(list (substring str  0 1) str)
(list str)
))


and in the query:

Code: [Select]

(define (proc-tag hp tag album title)

(if (> (string-length tag) 1)
(add-node hp (append (initial-and-string tag) (list album title)) )
(if (flip tag #\, " ")
  (add-node hp  (append (initial-and-string (flip tag #\, " " )) (list album title) ))
  (if (flip tag #\space "," )
(add-node hp (append (initial-and-string (flip tag #\  ", " )) (list album title) ))
)
)
)
)
;----------------------------------------------------------------------------------------------------------------------------------------
(for-each-db-entry
(lambda (handle)
  (let (
  (album   (format-title handle "[%album%]"))
  (albumartist (format-title handle "$if3($trim($meta(album artist)), )"))
  (title   (format-title handle "%track%  %title%"))
  (artistfull (format-title handle "$meta_sep(artist,', ',' & ')"))
  )
  (add-node handle (append (initial-and-string album) (list artistfull title)))
 
(for-each
(lambda (composer)
(let (
(album   (format-title handle "[%album%]"))
(title   (format-title handle "%track%  %title%"))
)
  (proc-tag handle composer   album title)
))
(meta-list handle "composer") )

(for-each
(lambda (artist)
  (let (
  (album   (format-title handle "[%album%]"))
  (title   (format-title handle "%track%  %title%"))
  )
  (proc-tag handle artist   album title)  
  ) )
  (meta-list handle "artist"))

(for-each
(lambda (artist)
  (let (
  (album   (format-title handle "[%album%]"))
  (albumartist   (format-title handle "[%album artist%]")) 
  (title   (format-title handle "%track%  %title%"))
  )
  (proc-tag handle albumartist   album title)  
  ) )
  (meta-list handle "artist"))
)
))


The code makes a single alphabetical index (i.e. A B C etc. ) with all artists, album artists, composers and albums in it. It handles ordinary names e.g. : "John Smith" and creates "Smith, John". It respects tags the other way around e.g. "te Kanawa, Kiri" and generates "Kiri te Kanawa" as the reversal. (If the tag was "Kiri te Kanawa", the normal process would generate "Kanawa, Kiri te".) e.g. "Mozart, Wolfgang Amadeus" and generates "Wolfgang Amadeus Mozart" as the reversal. (If the tag was "Wolfgang Amadeus Mozart", the normal process would generate "Amadeus Mozart, Wolfgang".) If the tag value ends with a comma, e.g. "Dresden Orchestra," then no reversal is meant to be entered. I was relying on the fact the original name and the flipped name would be the same so that there would only be one entry in the index. This works but the entry has each track twice. I'll fix this up tomorrow and repost.

Also, I have found that selecting items from Playlist Tree sends them directly to my active playlist as well as the  playlist PLT is set up to send to. Not sure what is causing this. I intend to explore further tomorrow. I'd be grateful to hear if you do or don't experience this!

Good luck.

foo_playlist_tree

Reply #1641
Upload it please, I'm interested too.


This is my scheme preferences code:

(remove-whitespace, strchr & split came from CWBowron's PLT forum; strip came from the web but flip and initial-and-string are my first scheme procedures - or whatever they are called in scheme!)


Code: [Select]

(define (remove-whitespace str)
  (let ((len (string-length str)))
(do ((start 0 (+ 1 start)))
((or (>= start len)
(not (char=? #\space (string-ref str start))))
(do ((end (- len 1) (- end 1)))
((or (<= end start)
  (not (char=? #\space (string-ref str end))))
  (substring str start (+ 1 end))))))))

(define (strchr str chr start)
  (cond
((>= start (string-length str)) #f)
((char=? (string-ref str start) chr) start)
(else (strchr str chr (+ 1 start)))))

(define (split str chr)
  (let ((mid (strchr str chr 0)))
(if mid
(list (remove-whitespace (substring str 0 (- mid 1)))
  (split (substring str (+ mid 1) (string-length str) chr))
)
#f)))
; strip : string -> string
;  remove white space from the beginning and end of a string
(define strip
  (let ([r-strip (regexp "^[ \t\r]*(.*?)[ \t\r]*$")])
(lambda (s)
  (cadr (regexp-match r-strip s)))))

(define (flip str chr sep )
  (let ((mid (strchr str chr 0)))
(if mid
  (strip (string-append (strip (substring str (+ mid 1) (string-length str)))
  (if  (string? sep) sep (make-string 1 sep) )  (strip (substring str 0  mid  ))))
#f)))

(define (initial-and-string str)
  (if (> (string-length str) 2)
(list (substring str  0 1) str)
(list str)
))


and in the query:

Code: [Select]

(define (proc-tag hp tag album title)

(if (> (string-length tag) 1)
(add-node hp (append (initial-and-string tag) (list album title)) )
(if (flip tag #\, " ")
  (add-node hp  (append (initial-and-string (flip tag #\, " " )) (list album title) ))
  (if (flip tag #\space "," )
(add-node hp (append (initial-and-string (flip tag #\  ", " )) (list album title) ))
)
)
)
)
;----------------------------------------------------------------------------------------------------------------------------------------
(for-each-db-entry
(lambda (handle)
  (let (
  (album   (format-title handle "[%album%]"))
  (albumartist (format-title handle "$if3($trim($meta(album artist)), )"))
  (title   (format-title handle "%track%  %title%"))
  (artistfull (format-title handle "$meta_sep(artist,', ',' & ')"))
  )
  (add-node handle (append (initial-and-string album) (list artistfull title)))
 
(for-each
(lambda (composer)
(let (
(album   (format-title handle "[%album%]"))
(title   (format-title handle "%track%  %title%"))
)
  (proc-tag handle composer   album title)
))
(meta-list handle "composer") )

(for-each
(lambda (artist)
  (let (
  (album   (format-title handle "[%album%]"))
  (title   (format-title handle "%track%  %title%"))
  )
  (proc-tag handle artist   album title)  
  ) )
  (meta-list handle "artist"))

(for-each
(lambda (artist)
  (let (
  (album   (format-title handle "[%album%]"))
  (albumartist   (format-title handle "[%album artist%]")) 
  (title   (format-title handle "%track%  %title%"))
  )
  (proc-tag handle albumartist   album title)  
  ) )
  (meta-list handle "artist"))
)
))


The code makes a single alphabetical index (i.e. A B C etc. ) with all artists, album artists, composers and albums in it. It handles ordinary names e.g. : "John Smith" and creates "Smith, John". It respects tags the other way around e.g. "te Kanawa, Kiri" and generates "Kiri te Kanawa" as the reversal. (If the tag was "Kiri te Kanawa", the normal process would generate "Kanawa, Kiri te".) e.g. "Mozart, Wolfgang Amadeus" and generates "Wolfgang Amadeus Mozart" as the reversal. (If the tag was "Wolfgang Amadeus Mozart", the normal process would generate "Amadeus Mozart, Wolfgang".) If the tag value ends with a comma, e.g. "Dresden Orchestra," then no reversal is meant to be entered. I was relying on the fact the original name and the flipped name would be the same so that there would only be one entry in the index. This works but the entry has each track twice. I'll fix this up tomorrow and repost.

Also, I have found that selecting items from Playlist Tree sends them directly to my active playlist as well as the  playlist PLT is set up to send to. Not sure what is causing this. I intend to explore further tomorrow. I'd be grateful to hear if you do or don't experience this!

Good luck.

foo_playlist_tree

Reply #1642
Upload it please, I'm interested too.


This is my scheme preferences code:

(remove-whitespace, strchr & split came from CWBowron's PLT forum; strip came from the web but flip and initial-and-string are my first scheme procedures - or whatever they are called in scheme!)


Code: [Select]

(define (remove-whitespace str)
  (let ((len (string-length str)))
(do ((start 0 (+ 1 start)))
((or (>= start len)
(not (char=? #\space (string-ref str start))))
(do ((end (- len 1) (- end 1)))
((or (<= end start)
  (not (char=? #\space (string-ref str end))))
  (substring str start (+ 1 end))))))))

(define (strchr str chr start)
  (cond
((>= start (string-length str)) #f)
((char=? (string-ref str start) chr) start)
(else (strchr str chr (+ 1 start)))))

(define (split str chr)
  (let ((mid (strchr str chr 0)))
(if mid
(list (remove-whitespace (substring str 0 (- mid 1)))
  (split (substring str (+ mid 1) (string-length str) chr))
)
#f)))
; strip : string -> string
;  remove white space from the beginning and end of a string
(define strip
  (let ([r-strip (regexp "^[ \t\r]*(.*?)[ \t\r]*$")])
(lambda (s)
  (cadr (regexp-match r-strip s)))))

(define (flip str chr sep )
  (let ((mid (strchr str chr 0)))
(if mid
  (strip (string-append (strip (substring str (+ mid 1) (string-length str)))
  (if  (string? sep) sep (make-string 1 sep) )  (strip (substring str 0  mid  ))))
#f)))

(define (initial-and-string str)
  (if (> (string-length str) 2)
(list (substring str  0 1) str)
(list str)
))


and in the query:

Code: [Select]

(define (proc-tag hp tag album title)

(if (> (string-length tag) 1)
(add-node hp (append (initial-and-string tag) (list album title)) )
(if (flip tag #\, " ")
  (add-node hp  (append (initial-and-string (flip tag #\, " " )) (list album title) ))
  (if (flip tag #\space "," )
(add-node hp (append (initial-and-string (flip tag #\  ", " )) (list album title) ))
)
)
)
)
;----------------------------------------------------------------------------------------------------------------------------------------
(for-each-db-entry
(lambda (handle)
  (let (
  (album   (format-title handle "[%album%]"))
  (albumartist (format-title handle "$if3($trim($meta(album artist)), )"))
  (title   (format-title handle "%track%  %title%"))
  (artistfull (format-title handle "$meta_sep(artist,', ',' & ')"))
  )
  (add-node handle (append (initial-and-string album) (list artistfull title)))
 
(for-each
(lambda (composer)
(let (
(album   (format-title handle "[%album%]"))
(title   (format-title handle "%track%  %title%"))
)
  (proc-tag handle composer   album title)
))
(meta-list handle "composer") )

(for-each
(lambda (artist)
  (let (
  (album   (format-title handle "[%album%]"))
  (title   (format-title handle "%track%  %title%"))
  )
  (proc-tag handle artist   album title)  
  ) )
  (meta-list handle "artist"))

(for-each
(lambda (artist)
  (let (
  (album   (format-title handle "[%album%]"))
  (albumartist   (format-title handle "[%album artist%]")) 
  (title   (format-title handle "%track%  %title%"))
  )
  (proc-tag handle albumartist   album title)  
  ) )
  (meta-list handle "artist"))
)
))


The code makes a single alphabetical index (i.e. A B C etc. ) with all artists, album artists, composers and albums in it. It handles ordinary names e.g. : "John Smith" and creates "Smith, John". It respects tags the other way around e.g. "te Kanawa, Kiri" and generates "Kiri te Kanawa" as the reversal. (If the tag was "Kiri te Kanawa", the normal process would generate "Kanawa, Kiri te".) e.g. "Mozart, Wolfgang Amadeus" and generates "Wolfgang Amadeus Mozart" as the reversal. (If the tag was "Wolfgang Amadeus Mozart", the normal process would generate "Amadeus Mozart, Wolfgang".) If the tag value ends with a comma, e.g. "Dresden Orchestra," then no reversal is meant to be entered. I was relying on the fact the original name and the flipped name would be the same so that there would only be one entry in the index. This works but the entry has each track twice. I'll fix this up tomorrow and repost.

Also, I have found that selecting items from Playlist Tree sends them directly to my active playlist as well as the  playlist PLT is set up to send to. Not sure what is causing this. I intend to explore further tomorrow. I'd be grateful to hear if you do or don't experience this!

Good luck.


This is the latest, for me final, version - somewhat more Scheme-like (I think). I've added a loop to handle the values  (divided by "\") in multi-value tags separately as some multi-value tags were not being separated by the primitive.

In the scheme preferences code box:

Code: [Select]
(define (remove-whitespace str)
  (let ((len (string-length str)))
    (do ((start 0 (+ 1 start)))
((or (>= start len)
    (not (char=? #\space (string-ref str start))))
(do ((end (- len 1) (- end 1)))
    ((or (<= end start)
  (not (char=? #\space (string-ref str end))))
  (substring str start (+ 1 end))))))))

(define (strchr str chr start)
  (cond
    ((>= start (string-length str)) #f)
    ((char=? (string-ref str start) chr) start)
    (else (strchr str chr (+ 1 start)))))

(define (split str chr)
  (let ((mid (strchr str chr 0)))
    (if mid
(list (remove-whitespace (substring str 0 (- mid 1)))
      (split (substring str (+ mid 1) (string-length str) chr))
)
#f)))

;;; str-split : Apr 2006 Doug Hoyte, hcsw.org.
;;; ----
;;; Splits a string 'str into a list of strings
;;; that were separated by the delimiter character 'ch
;;; ----
;;; Efficient as possible given that we can't count on
;;; 'str being an immutable string.

(define (str-split str ch)
  (let ((len (string-length str)))
    (letrec
      ((split
        (lambda (a b)
          (cond
            ((>= b len) (if (= a b) '() (cons (substring str a b) '())))
            ((char=? ch (string-ref str b)) (if (= a b)
                                              (split (+ 1 a) (+ 1 b))
                                              (cons (substring str a b) (split b b))))
            (else (split a (+ 1 b)))))))
      (split 0 0))))

; strip : string -> string
;  remove white space from the beginning and end of a string
(define strip
  (let ([r-strip (regexp "^[ \t\r]*(.*?)[ \t\r]*$")])
    (lambda (s)
      (cadr (regexp-match r-strip s)))))

(define (flip str chr sep )
  (let ((mid (strchr str chr 0)))
    (if mid
              (strip (string-append (strip (substring str (+ mid 1) (string-length str) ))
                                                (if  (string? sep) sep (string sep) )
                                                (strip (substring str 0  mid  )) ))
#f )))

(define (initial-and-string str)
  (cond (  (not str) '() )
            (  (> (string-length str) 1) (list (substring str  0 1) str ) )
            (  #t    (list str) )
    ))

In the scheme code box:

Code: [Select]
(define (proc-tag hp multivaluetag album title)
  (for-each
  (lambda (multivaluetag)
        (for-each
        (lambda (tag) 
                  (if (not (equal? (substring tag (- (string-length tag) 1)  (string-length tag)  ) ",") )
                              (add-node hp (append (initial-and-string tag) (list album title) ))  )
                  (cond   
                            (  (strchr tag #\, 0)
                              (add-node hp  (append (initial-and-string (flip tag #\,            " " )) (list album title) )) )
                          (  (strchr tag #\space 0)
            (add-node hp (append (initial-and-string (flip tag #\space  ", " )) (list album title) )) )
              )
        )
        (str-split multivaluetag #\\) )
    )
    (meta-list hp multivaluetag) )
)
;----------------------------------------------------------------------------------------------------------------------------------------
(for-each-db-entry
(lambda (handle)
      (let (
                  (album          (format-title handle "[%album%]"))
                  (title              (format-title handle "%track%  %title%"))
                  (artistfull        (format-title handle "$meta_sep(artist,', ',' & ')"))
                )
; add album
                (add-node handle (append (initial-and-string album) (list artistfull title) ))
         
              (proc-tag handle "composer"          album title)
              (proc-tag handle "artist"                album title)         
              (proc-tag handle "albumartist"        album title)   
              (proc-tag handle "album artist"        album title)
      )
))


foo_playlist_tree

Reply #1643
Hi - I am running the latest version of everything...

Playlist Tree 3.03
Panels UI 11.0
Foobar 0.9.4.3
Columns UI 0.1.3 b1.7

Win XP SP2

Every time I try to run Playlist Tree in either Columns or Panels it stops responding and crashes - people keep telling me to launch Playlist Tree in columns ui and then get a dialogue box popup and click ok - and then from there it will work... I simply do not get this option - I have tried adding/removing all of the versions and components and I still do not get the option...

I really want to try and use this component but it aint working

I have just tried removing panels completly and using the default ui and using dockable panels to add playlist tree and it wont show either.. I have those other dll's in my main foobar folder as instructed.. any suggestions.. it seems not to be panels ui related any more...


----

finally got it to load left the application in default ui running the panel for about 5-10 minutes and eventually the dialogue box shows up - i hit ok and now it works inside panels...

I am guessing it takes so long to load because I have a large music collection 50,000 songs and its scanning them?

either way I am happy its working now..

foo_playlist_tree

Reply #1644
Hey guys, having a little problem with this. I installed it once and didn't like it so deleted it. Thought I'd give it another shot again today and now it just doesn't want to work. I'm not used to it so I guess I could be using it incorrectly but I don't think so. In short it won't allow me to change playlists via the tree. If I right-click on my SCPL and change via the context menu it works but no-go otherwise. It worked the other day but not now. I even deleted any other components I've installed since but it still doesn't work. Any help would be appreciated.

foo_playlist_tree

Reply #1645
you can only "change playlists via the tree" if the active playlist is *Browser*
(or whatever you may have changed it to)
elevatorladylevitateme

foo_playlist_tree

Reply #1646
Thanks but that still doesn't seem to have worked . I just noticed my 'Refresh Browser' option in the Library menu is missing too.

EDIT:Seems it's not just the Playlist Tree. I can't change playlists via the Playlist Switcher either. Argh. Lol

Looks like my CFG or Columns UI got corrupted or something. Had to do a fresh install and reconfigure everything. Luckily I'd saved all my code as text files. Now that I think about it after I installed the playlist tree I did have a crash so that may be what caused it. Don't know. Either way, just thought I'd let you know. Remember to back up all your code not just your cfg!

I'll get round to trying this again once I take a suitable rest. Lol.

foo_playlist_tree

Reply #1647
I'm in the process of moving my foobar2000 components and documentations to a new server.  It should forward links from the old wiki.bowron.us site to the new host at bazquux.com, but I wanted users to know that the new bazquux.com site is legitimate.
There used to be a link to my website here.

foo_playlist_tree

Reply #1648
Greetings all!

I was wondering how I can enable this plugin?=/

I put those dll's in right directions, and I saw the playlist_tree in preferences-> components, but I have no clue how to enable it?

foo_playlist_tree

Reply #1649
Greetings all!

I was wondering how I can enable this plugin?=/

I put those dll's in right directions, and I saw the playlist_tree in preferences-> components, but I have no clue how to enable it?



Try main menu: Library/ Playlist Tree/ Root/ New Query