Page 1 of 1

Custom Navigation Trees: Different Structures per Share

Posted: Tue Aug 25, 2009 4:51 pm
by ldh2002
There is one detail in my tree structure I want to share.

Goal: Apply different tree structures to subsets of the music collection shared with TwonkyMedia Server 5.0.x.

Reason: I usually browse my music tree by AlbumArtist/Year/Album. For Best-of compilations, however, I never remember (and hardly care) when they were issued. Thirdly, for soundtracks the Artist is irrelevant, I only care for the Album(-title); furthermore I do not want the list cluttered with all the regular albums (not all soundtracks are compilations, btw.).
Thus I need a disjoint tree structure. As there is no filter mechanism (yet?), I found another way which allowed me to reach this goal.

Means: <include>-node

Approach:
  • Put the music data for each subset into a different folder shared in Twonky.
  • Create separate .view.xml files for each subset.
  • In the <view>-node assign each file the same path
  • In the <include>-node replace the * <tree path='*' /> with the number of the different shares, starting with 15
Helpful but not required:
  • In the <view>-node use a subview other than the ones in default.view.xml. This way there is no irritating overlap with default.view. Copy the stuff you need from default.view and assign it to your subview(s)
  • In case you want to have albums in more than one subset (e.g. best-of compilations in your usual artists collections), use symbolic links or junctions on hour hard drive structure.
Example Code:

First file ist mostly copied from default.view.xml

Code: Select all

<view name='artists' path='mypersonal.view' subviews="advanced,ipod,simple,folder">
	<include>
		<tree path='15' />
	</include>
	<navtree sortcriteria='+upnp:originalTrackNumber'>
		<container name='music' id='music' multiview='1' sortcriteria='+dc:title' upnp:originalTrackNumber='1' createClass='object.item.audioItem.musicTrack'>
			<container name='alltracks' visibility="advanced,ipod,simple" id='music/all' sortcriteria='+dc:title' createClass='object.item.audioItem.musicTrack' class='object.container'/>	
			<container name='artistindex' visibility="advanced" id='music/artistindex' sortcriteria='+dc:title' class='object.container' createClass='object.item.audioItem.musicTrack'>
				<container buildon='upnp:artist[3]' sortcriteria='+dc:title' class='object.container' createClass='object.item.audioItem.musicTrack'>
					<container buildon='upnp:artist' sortcriteria='+dc:title' class='object.container.person.musicArtist' createClass='object.item.audioItem.musicTrack'>
						<container name='allname' sortcriteria='+dc:title' createClass='object.item.audioItem.musicTrack' class='object.container' />
						<container buildon='upnp:album' albumart='1' sortcriteria='+upnp:originalTrackNumber' createClass='object.item.audioItem.musicTrack' class='object.container.album.musicAlbum' />
					</container>
				</container>
			</container>
			<container name='artistalbum' visibility="simple" id='music/artistalbum' sortcriteria='+dc:title' class='object.container' createClass='object.item.audioItem.musicTrack'>				
				<container name='allname'  buildon='upnp:album' sortcriteria='+upnp:originalTrackNumber' createClass='object.item.audioItem.musicTrack' class='object.container.album.musicAlbum' />
				<container buildon='upnp:albumArtist[5]' sortcriteria='+dc:title' class='object.container' createClass='object.item.audioItem.musicTrack'>
					<container buildon='upnp:albumArtist[1]' sortcriteria='+dc:title' class='object.container.person.albumartist' createClass='object.item.audioItem.musicTrack'>
						<container buildon='upnp:albumArtist' sortcriteria='+upnp:originalTrackNumber' class='object.container.person.albumartist' createClass='object.item.audioItem.musicTrack'>
							<container buildon='upnp:album' albumart='1' sortcriteria='+upnp:originalTrackNumber' class='object.container.album.musicAlbum' createClass='object.item.audioItem.musicTrack'/>
						</container>
					</container>
				</container>
			</container>
			<container name='Interpret/Jahr/Album' visibility="simple" id='music/albumartists' sortcriteria='+dc:title' class='object.container' createClass='object.item.audioItem.musicTrack'>				
				<container name='allname'  buildon='upnp:album' sortcriteria='+upnp:originalTrackNumber' createClass='object.item.audioItem.musicTrack' class='object.container.album.musicAlbum' />
				<container buildon='upnp:albumArtist[5]' sortcriteria='+dc:title' class='object.container' createClass='object.item.audioItem.musicTrack'>
					<container buildon='upnp:albumArtist[1]' sortcriteria='+dc:title' class='object.container.person.albumartist' createClass='object.item.audioItem.musicTrack'>
						<container buildon='upnp:albumArtist' sortcriteria='+dc:title' class='object.container.person.albumartist' createClass='object.item.audioItem.musicTrack'>
							<container name='albums'buildon='upnp:album' sortcriteria='+upnp:originalTrackNumber' upnp:originalTrackNumber='1' class='object.container.person.albumartist' createClass='object.item.audioItem.musicTrack'>								
								<container buildon='upnp:album' albumart='1' sortcriteria='+upnp:originalTrackNumber' class='object.container.album.musicAlbum' createClass='object.item.audioItem.musicTrack'/>
							</container>
							<container buildon='dc:date[1:4]' albumart='1' sortcriteria='+dc:date' upnp:originalTrackNumber='2' class='object.container' createClass='object.item.audioItem.musicTrack'>
								<container buildon='upnp:album' albumart='1' sortcriteria='+upnp:originalTrackNumber' class='object.container.album.musicAlbum' createClass='object.item.audioItem.musicTrack'/>							
							</container>								
						</container>
					</container>
				</container>
			</container>
			<container name='genre' visibility="advanced,ipod" id='music/genre' sortcriteria='+dc:title' class='object.container' createClass='object.item.audioItem.musicTrack'>
				<container buildon='upnp:genre' sortcriteria='+dc:title' class='object.container.genre.musicGenre' createClass='object.item.audioItem.musicTrack' />
			</container>
			<container name='genrealbum' visibility="advanced" sortcriteria='+dc:title' class='object.container' createClass='object.item.audioItem.musicTrack'>
				<container buildon='upnp:genre' sortcriteria='+dc:title' class='object.container.genre.musicGenre' createClass='object.item.audioItem.musicTrack' >
					<container buildon='upnp:album' albumart='1' sortcriteria='+upnp:originalTrackNumber' createClass='object.item.audioItem.musicTrack' class='object.container.album.musicAlbum' />
				</container>
			</container>
			<container name='genreartist' visibility="advanced" id='music/genreartistalbum' sortcriteria='+dc:title' class='object.container' createClass='object.item.audioItem.musicTrack'>
				<container name='allname' sortcriteria='+dc:title' createClass='object.item.audioItem.musicTrack' class='object.container' >
					<container name='allname' sortcriteria='+dc:title' createClass='object.item.audioItem.musicTrack' class='object.container' >
						<container name='allname' sortcriteria='+dc:title' createClass='object.item.audioItem.musicTrack' class='object.container' />
						<container buildon='upnp:album' albumart='1' sortcriteria='+upnp:originalTrackNumber' createClass='object.item.audioItem.musicTrack' class='object.container.album.musicAlbum' />
					</container>
					<container buildon='upnp:artist' sortcriteria='+dc:title' class='object.container' createClass='object.item.audioItem.musicTrack'>
						<container name='allname' sortcriteria='+dc:title' createClass='object.item.audioItem.musicTrack' class='object.container' />
						<container buildon='upnp:album' albumart='1' sortcriteria='+upnp:originalTrackNumber' createClass='object.item.audioItem.musicTrack' class='object.container.album.musicAlbum' />
					</container>
				</container>
				<container buildon='upnp:genre' sortcriteria='+dc:title' class='object.container.genre.musicGenre' createClass='object.item.audioItem.musicTrack'>
					<container name='allname' sortcriteria='+dc:title' createClass='object.item.audioItem.musicTrack' class='object.container' >
						<container name='allname' sortcriteria='+dc:title' createClass='object.item.audioItem.musicTrack' class='object.container' />
						<container buildon='upnp:album' albumart='1' sortcriteria='+upnp:originalTrackNumber' createClass='object.item.audioItem.musicTrack' class='object.container.album.musicAlbum' />
					</container>
					<container buildon='upnp:artist' sortcriteria='+dc:title' class='object.container' createClass='object.item.audioItem.musicTrack'>
						<container name='allname' sortcriteria='+dc:title' createClass='object.item.audioItem.musicTrack' class='object.container' />
						<container buildon='upnp:album' albumart='1' sortcriteria='+upnp:originalTrackNumber' createClass='object.item.audioItem.musicTrack' class='object.container.album.musicAlbum' />
					</container>
				</container>
			</container>
			<container name='rating' visibility="advanced" id='music/rating' sortcriteria='+dc:title' class='object.container' createClass='object.item.audioItem.musicTrack'>
				<container buildon='pv:rating' sortcriteria='+dc:title' class='object.container' createClass='object.item.audioItem.musicTrack' />
			</container>
			<container name='artist' visibility="ipod,advanced" id='music/artists' sortcriteria='+dc:title' class='object.container' createClass='object.item.audioItem.musicTrack'>
				<container name='allname' sortcriteria='+dc:title' createClass='object.item.audioItem.musicTrack' class='object.container' />
				<container buildon='upnp:artist' sortcriteria='+dc:title' class='object.container.person.musicArtist' createClass='object.item.audioItem.musicTrack' />
			</container>
			<container name='album' visibility="ipod,advanced" id='music/albums' sortcriteria='+dc:title' createClass='object.item.audioItem.musicTrack' class='object.container' >
				<container buildon='upnp:album' albumart='1' sortcriteria='+upnp:originalTrackNumber' createClass='object.item.audioItem.musicTrack' class='object.container.album.musicAlbum' />
			</container>
			<container name='composer' visibility="ipod,advanced" id='music/composers' sortcriteria='+dc:title' createClass='object.item.audioItem.musicTrack' class='object.container' >
				<container buildon='upnp:author' sortcriteria='+dc:title' createClass='object.item.audioItem.musicTrack' class='object.container.album.musicAlbum' />
			</container>
			<container name='folder' visibility="simple,advanced,folder" id='music/folders' class='object.container.storageFolder' createClass='object.item.audioItem.musicTrack'>
				<container buildon='res' sortcriteria='+upnp:originalTrackNumber,+dc:title' createClass='object.item.audioItem.musicTrack' class='object.container.storageFolder' />
			</container>
			<container name='playlists' visibility="advanced,ipod,simple" id='music/playlists' class='object.container' createClass='object.item.audioItem.musicTrack,object.item.audioItem.online.musicTrack' sortcriteria='+upnp:originalTrackNumber,+dc:title'   restricted='0' flags='pv:playlistRoot=Music' >
				<container name='playlistrecentlyadded' filteron='pv:addedLast60' sortcriteria='-pv:addedTime' createClass='object.item.audioItem.musicTrack' maxitems='500' upnp:originalTrackNumber='3' restricted='1' class='object.container.playlistContainer' flags='pv:smartplaylist=1' />
				<container name='playlistmostplayed' filteron='pv:playcount' sortcriteria='-pv:playcount' createClass='object.item.audioItem.musicTrack' maxitems='500' upnp:originalTrackNumber='1'  restricted='1' class='object.container.playlistContainer' flags='pv:smartplaylist=1' />
				<container name='playlistlastplayed' filteron='pv:lastPlayedTime' sortcriteria='-pv:lastPlayedTime' createClass='object.item.audioItem.musicTrack' maxitems='500' upnp:originalTrackNumber='2' restricted='1' class='object.container.playlistContainer' flags='pv:smartplaylist=1' />
				<container name='playlisthighlyrated' filteron='pv:highrated' sortcriteria='-pv:rating' createClass='object.item.audioItem.musicTrack' maxitems='500' upnp:originalTrackNumber='4' class='object.container.playlistContainer' restricted='1'  flags='pv:smartplaylist=1' />
				<container buildon='upnp:playlist' sortcriteria='+upnp:originalTrackNumber' upnp:originalTrackNumber='5' createClass='object.item.audioItem.musicTrack,object.item.audioItem.online.musicTrack' class='object.container.playlistContainer' />
			</container>
		</container>
	</navtree>
</view>
Second file is used to view my best-of compilations (without displaying the year)

Code: Select all

<view name='best' path='mypersonal.view' subviews="advanced,ipod,simple,folder">
	<include>
		<tree path='16' />
	</include>
	<navtree sortcriteria='+upnp:originalTrackNumber'>
		<container name='music' id='music' multiview='1' sortcriteria='+dc:title' upnp:originalTrackNumber='1' createClass='object.item.audioItem.musicTrack'>
			<container name='Best Compilations' visibility="advanced, simple" id='music/bestcompilations' sortcriteria='+dc:title' class='object.container' createClass='object.item.audioItem.musicTrack'>				
				<container name='allname'  buildon='upnp:album' sortcriteria='+upnp:originalTrackNumber' createClass='object.item.audioItem.musicTrack' class='object.container.album.musicAlbum' />
				<container buildon='upnp:albumArtist[5]' sortcriteria='+dc:title' class='object.container' createClass='object.item.audioItem.musicTrack'>
					<container buildon='upnp:albumArtist' sortcriteria='+dc:date' class='object.container.person.albumartist' createClass='object.item.audioItem.musicTrack'>
							<container buildon='upnp:album' albumart='1' sortcriteria='+upnp:originalTrackNumber' class='object.container' createClass='object.item.audioItem.musicTrack' />
					</container>
				</container>
			</container>
		</container>
	</navtree>
</view>
Third file is displaying my soundtracks (sorted by album title).

Code: Select all

<view name='soundtracks' path='mypersonal.view' subviews="advanced,ipod,simple,folder">
	<include>
		<tree path='17' />
	</include>
	<navtree sortcriteria='+upnp:originalTrackNumber'>
		<container name='music' id='music' multiview='1' sortcriteria='+dc:title' upnp:originalTrackNumber='1' createClass='object.item.audioItem.musicTrack'>
			<container name='Soundtracks' visibility="advanced, simple" id='music/soundtracks' sortcriteria='+dc:title' class='object.container' createClass='object.item.audioItem.musicTrack'>				
				<container name='allname'  buildon='upnp:album' sortcriteria='+upnp:originalTrackNumber' createClass='object.item.audioItem.musicTrack' class='object.container.album.musicAlbum' />
				<container buildon='upnp:album[5]' sortcriteria='+dc:title' class='object.container' createClass='object.item.audioItem.musicTrack'>
					<container buildon='upnp:album' albumart='1' sortcriteria='+upnp:originalTrackNumber' class='object.container' createClass='object.item.audioItem.musicTrack'/>
				</container>
			</container>
		</container>
	</navtree>
</view>

Re: Custom Navigation Trees: Different Structures per Share

Posted: Tue Aug 25, 2009 6:13 pm
by PeeBee
The 5.1 Betas allow you to have a different view per client.

PB

Re: Custom Navigation Trees: Different Structures per Share

Posted: Wed Aug 26, 2009 9:40 am
by ldh2002
PeeBee wrote:The 5.1 Betas allow you to have a different view per client.
The 5.0.x version also allows for this. My intention, however, was to have different views on one client, active simultaneously.

Cheers ldh

Re: Custom Navigation Trees: Different Structures per Share

Posted: Fri Sep 18, 2009 3:26 pm
by hvaleton
Hi ldh2002,

I have exactly the same problem you seem to have found the answer for.
My collection consists of two distinct sub collections: classical and pop music
I have tried to distinguish between those two by using 'filteron'. But this can only filter on the fact that a certain tag is filled or not. It cannot filter on actual content.
So I determine pop music by filtering on the fact that the 'album artist' tag is filled.
This of course implies having to get rid of all 'album artist' tags in my classical flacs.
Next I determine classical music by filtering on the the fact that the 'Composer' tag is filled.
This is rather more easily done by deleting all composer tags in my pop collection, which I'm not interested in anyway.
But still, it's not a very charming solution (not to mention time consuming) and in some cases it doesn't even work because of some tags that remain mysteriously impervious to deleting....
So if your solution still works in the new 5.1 version of TMS I woud be very happy.
Have you tried it out yet?

I remember Twonky stating somewhere in the custom tree manual that the < tree path > functionality would only be activated in a later release....

Another thing that puzzles me is your usage of a number to indicate a share. Is there a specific reason for this? Why not simply use the name of the share, in my case M:\music\01_KLASSIEK and M:\music\02_POP ?
And why start with 15?

I'd be very grateful for your thoughts on the above.

Thanks in advance,

Hans

Re: Custom Navigation Trees: Different Structures per Share

Posted: Thu Oct 22, 2009 9:45 pm
by ldh2002
Hello Hans,

eventually I upgraded to v5.1 to see how it behaves.

Most important point first:
I am going to downgrade again pretty soon.

The <include>-tag doesn't seem to exist or work anymore in v5.1

When I experimented with the <include>-tag in v5.0.68 I noticed that the value I have to use as <tree path > is not the actual path in the OS, but the path that Twonky assigns to the Share in its own tree structure.

Closing, I personally hope that a future subversion of Twonky will continue using <include>
For the whole community I hope for an updated TMS-View-Configuration documentation which is currently quite outdated.

Gruß

Lars