Sign up here and you can log into the forum!

Plugin: Today's Podcasts w/thumbs

UMSP Plugin Depot, the place for sharing plugins & info about them. No requests, just plugins/code.

Plugin: Today's Podcasts w/thumbs   

Postby PaulF » Thu Jun 03, 2010 2:16 pm

If you got here via the new enable/disable screen on the svn checked out plugins, the name has changed so you need to edit /conf/umsp.php
dailypodcasts -> daily-podcasts
I also added code to sort by pubDate so negative limits are treated as positive

I permanently disabled the plugin as a standalone plugin. The plugin is still there, but only run when a MediaItem id points to the plugin


I do podcasts every day, mainly to keep up with my sports teams. I modified zoster's quick and dirty files to do podcasts like I like them.

Podcasts are not uniform so I was able to modify each feed to my liking with an xml file. The xml file limits the fetch to the number of files per day. Some podcast titles don't have the feed name in the item titles so I added header and footer to the xml to append them to the podcast title. Some podcasts feed backwards so I reverse the feed if the limit is negative. I added a feed_list parameter that points to the xml file /conf/umsp.php:

Code: Select all
<?php
        $myMediaItems[] = array(   
            'id'         => 'umsp://plugins/dailypodcasts?feed_list=/boot/sportspods.xml',
            'parentID'   => '0',
            'restricted' => '1',
            'dc:title'   => 'Sports Podcasts',
            'upnp:class' => 'object.container',
        );
        $myMediaItems[] = array(   
            'id'         => 'umsp://plugins/dailypodcasts?feed_list=/boot/pubradiopods.xml',
            'parentID'   => '0',
            'restricted' => '1',
            'dc:title'   => 'Public Radio Podcasts',
            'upnp:class' => 'object.container',
        );
?>


My xml files are on the ext3 stick which is mounted on /boot.
/boot/sportspods.xml:
Code: Select all
<?xml version="1.0"?>
<list>
    <item>
        <description>The Dan Patrick Show</description>
        <url>http://rss.cnn.com/services/podcasting/danpatrick/rss.xml</url>
        <limit>-3</limit>
    </item>
    <item>
        <description>Patrick Reusse on am1500 KSTP</description>
        <url>http://rss.1500espn.com/ondemand/reusse</url>
        <limit>2</limit>
    </item>
    <item>
        <description>Saturday Morning SportsTalk on am1500 KSTP</description>
        <url>http://rss.1500espn.com/ondemand/satsportstalk</url>
        <limit>2</limit>
    </item>
    <item>
        <description>Sunday Morning SportsTalk on am1500 KSTP</description>
        <url>http://rss.1500espn.com/ondemand/sunsportstalk</url>
        <limit>1</limit>
    </item>
    <item>
        <description>Weekday SportsTalk on am1500 KSTP</description>
        <url>http://rss.1500espn.com/ondemand/sportstalk</url>
        <limit>2</limit>
    </item>
    <item>
        <description>Dan Barreiro KFAN AM 1130</description>
        <url>http://www.kfan.com/podcast/KFAN_Barreiro.xml</url>
        <limit>-3</limit>
        <header>Dan Barreiro </header>
    </item>
    <item>
        <description>Purple on Demand Vikings</description>
        <url>http://www.kfan.com/podcast/KFAN_Vikings.xml</url>
        <limit>4</limit>
        <header>Purple on Demand Vikings </header>
    </item>
    <item>
        <description>Joe Soucheray and Garage Logic on am1500 KSTP</description>
        <url>http://rss.1500espn.com/ondemand/garagelogic</url>
        <limit>2</limit>
    </item>
    <item>
        <description>Best of Mike and Mike</description>
        <url>http://sports.espn.go.com/espnradio/podcast/feeds/itunes/podCast?id=2445552</url>
        <limit>1</limit>
    </item>
</list>


/boot/pubradiopods.xm
Code: Select all
<?xml version="1.0"?>
<list>
    <item>
        <description>Car Talk</description>
        <url>http://www.npr.org/rss/podcast.php?id=510208</url>
        <limit>1</limit>
    </item>
    <item>
        <description>The Splendid Table</description>
        <url>http://americanpublicmedia.publicradio.org/podcasts/xml/splendid_table/kitchen_questions.xml</url>
        <limit>1</limit>
    </item>
    <item>
        <description>This American Life</description>
        <url>http://feeds.thisamericanlife.org/talpodcast</url>
        <limit>1</limit>
        <header>This American Life </header>
    </item>
    <item>
        <description>Science Friday</description>
        <url>http://www.npr.org/rss/podcast.php?id=510221</url>
        <limit>10</limit>
        <header>>Science Friday </header>    </item>
    <item>
        <description>Wait Wait Don't Tell Me</description>
        <url>http://www.npr.org/rss/podcast.php?id=35</url>
        <limit>1</limit>
    </item>
</list>


Not quick, but maybe dirty /etc/umsp/plugins/dailypodcasts.php:
Code: Select all
<?php

function _pluginMain($prmQuery) {
    $queryData = array();
    parse_str($prmQuery, $queryData);
    if ($queryData['feed_url'] !='') {
        $items = _pluginItemList($queryData['feed_url'], 64, '', '');
        return $items;
    } # end if
    if ($queryData['feed_list'] !='') {
        $items = _pluginFeedList($queryData['feed_list']);
        return $items;
    } # end if
} # end function

function _pluginItemList($prmFeedUrl, $prmMax, $prmHeader, $prmFooter, $prmImage) {
    # Nodes are currently only parsed by name not parent.
    #
    $newFeed = array(
        'genre'        => 'Podcast', #feed category
        'albumArtURI'  => '', #feed image
        'album'        => '', #feed title
    );
    $reader = new XMLReader();
    $feedXML = file_get_contents($prmFeedUrl);
    $reader->XML($feedXML);
    $retMediaItems = array();
    $max = $prmMax;
    $image = '';
    if($max<0){$max = 0 - $max;};
    while (($max>0) and $reader->read()){
        if (($reader->nodeType == XMLReader::ELEMENT) && ($reader->localName == 'image')) {
            $newFeed['albumArtURI'] = $reader->getAttribute('href');
            if ($newFeed['albumArtURI'] == ''){
                do {
                    $reader->read();
                    if($reader->localName == 'url') {
                            $reader->read();
                            if ($reader->nodeType == XMLReader::TEXT) {
                                $newFeed['albumArtURI'] = $reader->value;
                            } # end if
                    }
                } while (!(($reader->nodeType == XMLReader::END_ELEMENT) && ($reader->localName == 'image')));
            }
        }
        if (($reader->nodeType == XMLReader::ELEMENT) && ($reader->localName == 'item')) {
            $newItem = array();
            #
            # Read item nodes until end
            #
            do {
                $reader->read();
                switch ($reader->localName) {
                    case 'pubDate':
                        $reader->read();
                        if ($reader->nodeType == XMLReader::TEXT) {
                            $newItem['artist'] = $reader->value;
                        } # end if
                        break;
                    case 'guid':
                        $reader->read();
                        if ($reader->nodeType == XMLReader::TEXT) {
                            $newItem['id'] = $reader->value;
                        } # end if
                        break;
                    case 'title':
                        $reader->read();
                        if ($reader->nodeType == XMLReader::TEXT) {
                            $newItem['title'] = $prmHeader . $reader->value . $prmFooter;
                        } # end if
                        break;
                    case 'enclosure':
                        $newItem['url']   = $reader->getAttribute('url');
                        $newItem['type']  = $reader->getAttribute('type');
                        break;
                } # end switch
            } while (!(($reader->nodeType == XMLReader::END_ELEMENT) && ($reader->localName == 'item')));
            #
            # New feed item parsed. Now add as media item:
            #
            $itemType = explode('/', $newItem['type'], 2);
            switch (strtolower($itemType[0])) {
                case 'video':
                    $upnpClass = 'object.item.videoItem';
                    break;
                case 'audio':
                    $upnpClass = 'object.item.audioItem';
                    break;
                case 'image':
                    $upnpClass = 'object.item.imageItem';
                    break;
                default:
                    # default to video item ?
                    $upnpClass = 'object.item.videoItem';
            } # end switch
            $MediaItem = array (
                'id'                => 'umsp://plugins/podcasts?' . $newItem['id'],
                'dc:title'          => $newItem['title'],
                'res'               => $newItem['url'],
                'upnp:class'        => $upnpClass,
                'protocolInfo'      => 'http-get:*:' . $newItem['type'] . ':*',
                'upnp:artist'       => $newItem['artist'], #artist = pubDate
                'upnp:albumArtURI'  => $newFeed['albumArtURI'],
                'upnp:genre'        => $newFeed['genre'],
                'upnp:album'        => $newFeed['album'],
            );
            if($prmMax<0){
                array_unshift($retMediaItems, $MediaItem);
            } else {
                array_push($retMediaItems, $MediaItem);
            }
            $max--;
        } # end if
        if (($reader->nodeType == XMLReader::ELEMENT) && ($reader->localName == 'title')) {
            $reader->read();
            if ($reader->nodeType == XMLReader::TEXT) {
                $newFeed['album'] = $reader->value;
            } # end if
        }
        if (($reader->nodeType == XMLReader::ELEMENT) && ($reader->localName == 'category')) {
            $reader->read();
            if ($reader->nodeType == XMLReader::TEXT) {
                $newFeed['genre'] = $reader->value;
            } # end if
        }
    } #end while
    return $retMediaItems;   
} # end function

function _pluginFeedList($prmFeedList) {
    # Nodes are currently only parsed by name not parent.
    #
    $listreader = new XMLReader();
    $feedlistXML = file_get_contents($prmFeedList);
    $listreader->XML($feedlistXML);
    $retListItems = array();
    while ($listreader->read()) {
        if (($listreader->nodeType == XMLReader::ELEMENT) && ($listreader->localName == 'item')) {
            $footer = '';
            $header = '';
            $newItem = array();
            #
            # Read item nodes until end
            #
            do {
                $listreader->read();
                switch ($listreader->localName) {
                    case 'image':
                        $listreader->read();
                        if ($listreader->nodeType == XMLReader::TEXT) {
                            $image = $listreader->value;
                        } # end if
                        break;
                    case 'header':
                        $listreader->read();
                        if ($listreader->nodeType == XMLReader::TEXT) {
                            $header = $listreader->value;
                        } # end if
                        break;
                    case 'footer':
                        $listreader->read();
                        if ($listreader->nodeType == XMLReader::TEXT) {
                            $footer = $listreader->value;
                        } # end if
                        break;
                    case 'description':
                        $listreader->read();
                        if ($listreader->nodeType == XMLReader::TEXT) {
                            $description = $listreader->value;
                        } # end if
                        break;
                    case 'url':
                        $listreader->read();
                        if ($listreader->nodeType == XMLReader::TEXT) {
                            $url = utf8_decode($listreader->value);
                        } # end if
                        break;
                    case 'limit':
                        $listreader->read();
                        if ($listreader->nodeType == XMLReader::TEXT) {
                            $limit = (int)utf8_decode($listreader->value);
                        } # end if
                        break;
                } # end switch
            } while (!(($listreader->nodeType == XMLReader::END_ELEMENT) && ($listreader->localName == 'item')));
            #
            # New feed item parsed. Now add as media item(make playlist oldest first):
            #
            $ListItem = _pluginItemList($url, $limit, $header, $footer, $image);
            if($ListItem != ''){
                $retListItems = array_merge($retListItems, $ListItem);
            }
        } # end if
    } #end while
    return $retListItems;   
} # end function

?>


It was really fun making my podcasts like I like them. I hope others like my way. too.
Last edited by PaulF on Tue Aug 24, 2010 2:39 pm, edited 2 times in total.
User avatar
PaulF
Developer
 
Posts: 420
Joined: Sat May 08, 2010 8:34 pm
Location: Oregon

Re: Today's Podcasts w/thumbs   

Postby PaulF » Fri Jun 11, 2010 8:49 pm

I had a bug because I was having trouble reading image URLs from the feed XML so I switched to PHP's Simple XML objects. It did make things a lot simpler, but figuring out the correct combination of functions to read XML name-spaces, like itunes:image, was not simple.

Going from XML:
Code: Select all
   <itunes:image href="http://i.cdn.turner.com/si/.element/img/1.0/logos/danpatrick/podcasting/dp.albumart.jpg" />
to
Code: Select all
    $itunesimage = $simplexml->channel[0]->children('itunes', true)->image->attributes();
    $newFeed = array (
        'itunesimage' => (string)$itunesimage['href'],
took hours and many searches to figure out.

New dailypodcasts.php:
Code: Select all
<?php

function _pluginMain($prmQuery) {
    $queryData = array();
    parse_str($prmQuery, $queryData);
    if ($queryData['feed_url'] !='') {
        $items = _pluginItemList($queryData['feed_url'], 64, '', '');
        return $items;
    } # end if
    if ($queryData['feed_list'] !='') {
        $items = _pluginFeedList($queryData['feed_list']);
        return $items;
    }
}

function _pluginItemList($prmFeedUrl, $prmMax, $prmHeader, $prmFooter) {
    $retMediaItems = array();
    $feedXML = file_get_contents($prmFeedUrl);
    $simplexml = new SimpleXMLElement($feedXML);
    $itunesimage = $simplexml->channel[0]->children('itunes', true)->image->attributes();
    $newFeed = array (
        'feedimage'   => (string)$simplexml->channel[0]->image->url,
        'itunesimage' => (string)$itunesimage['href'],
        'album'       => (string)$simplexml->channel[0]->title
    );
    $max = $prmMax;
    if($max<0){$max = 0 - $max;};
    foreach ($simplexml->channel[0]->item as $item) {
        $newItem = array (
            'title'   => (string)$item->title,
            'artist'  => (string)$item->pubDate,
            'id'      => (string)$item->guid,
            'url'     => (string)$item->enclosure['url'],
            'type'    => (string)$item->enclosure['type'],
            'genre'   => (string)$item->category
        );
        $itemType = explode('/', $newItem['type'], 2);
        switch (strtolower($itemType[0])) {
            case 'video':
                $upnpClass = 'object.item.videoItem';
                break;
            case 'audio':
                $upnpClass = 'object.item.audioItem';
                break;
            case 'image':
                $upnpClass = 'object.item.imageItem';
                break;
            default:
                $upnpClass = 'object.item.videoItem';
        }

        if($newFeed['feedimage'] == ""){
            $arturl = $newFeed['itunesimage'];
        } else {
            $arturl = $newFeed['feedimage'];
        }
        $MediaItem = array (
            'id'                => 'umsp://plugins/podcasts?' . $newItem['id'],
            'dc:title'          => $prmHeader . $newItem['title'] . $prmFoote,
            'res'               => $newItem['url'],
            'upnp:class'        => $upnpClass,
            'protocolInfo'      => 'http-get:*:' . $newItem['type'] . ':*',
            'upnp:artist'       => $newItem['artist'], #artist = pubDate
            'upnp:genre'        => $newItem['genre'],
            'upnp:album'        => $newFeed['album'],
            'upnp:album_art'    => $arturl
        );
        if($prmMax<0){
            array_unshift($retMediaItems, $MediaItem);
        } else {
            array_push($retMediaItems, $MediaItem);
        }
        if(--$max < 1) {break;};
    }
    return $retMediaItems;   
} # end function

function _pluginFeedList($prmFeedList) {
    $listreader = new XMLReader();
    $feedlistXML = file_get_contents($prmFeedList);
    $simplexml = new SimpleXMLElement($feedlistXML);
    $retListItems = array();
    foreach ($simplexml->item as $item) {
        $ListItem = _pluginItemList(
            (string)$item->url,
            (string)$item->limit,
            (string)$item->header,
            (string)$item->footer
        );
        if($ListItem != ''){
            $retListItems = array_merge($retListItems, $ListItem);
        }
    }
    return $retListItems;   
} # end function

?>
User avatar
PaulF
Developer
 
Posts: 420
Joined: Sat May 08, 2010 8:34 pm
Location: Oregon

Re: Plugin: Today's Podcasts w/thumbs   

Postby PaulF » Wed Sep 08, 2010 1:58 pm

I added a menu items so you can make a tree.

If an item contains items the <description> is the title of a folder.

If an <item> contains a <url> the item will list <limit> number of episodes.

I listen to some podcasts that vary the number of episodes per show and it has always bugged me. I found out how to convert the pubDate of the epsidode to a number so I can group episodes by shows.

<limit>2s</limit> will list 2 shows. If the gap between two episodes is greater than 12 hours I assume the two episodes are in separate shows.

Example:
Code: Select all
<?xml version="1.0"?>
<list>
    <item>
        <description>Public Radio</description>
        <item>
            <description>Car Talk</description>
            <item>
                <description>Car Talk</description>
                <url>http://www.npr.org/rss/podcast.php?id=510208</url>
            </item>
        </item>
        <item>
            <description>This American Life</description>
            <item>
                <description>This American Life</description>
                <url>http://feeds.thisamericanlife.org/talpodcast</url>
                <header>This American Life </header>
            </item>
        </item>
        <item>
            <description>Science Friday</description>
            <url>http://www.npr.org/rss/podcast.php?id=510221</url>
            <limit>1s</limit>
            <header>>Science Friday </header>
        </item>
    </item>
    <item>
        <description>Sports</description>
        <item>
            <description>Best of Mike and Mike</description>
            <item>
                <description>Best of Mike and Mike</description>
                <url>http://sports.espn.go.com/espnradio/podcast/feeds/itunes/podCast?id=2445552</url>
            </item>
        </item>
    </item>
</list>

Gives a menu tree:
Code: Select all
Public Radio
  Car Talk
    Car Talk #1035: The Roulette Wheel of Misfortune
    Car Talk #1036: The Lovelorn Mechanic
  This American Life
    This American Life #214: Family Physics
  Science Friday Time To Get Tough, Environmentalists Say
  Science Friday Insomnia Means More Than A Bad Night's Sleep
  Science Friday Can Cognitive Exercise Speed Up Dementia?
  Science Friday Stocky Dinosaur With Menacing Toes Unearthed
  Science Friday Is Organically Produced Food More Nutritious?
  Science Friday Studying Computers To Learn About Ourselves
Sports
  Best of Mike and Mike
    Best of Mike and Mike: 8/11
                |
                V
   Best of Mike and Mike: 9/8


Note: Some shows have two items, one for the folder and one for the episode list. Also, "Science Friday" the main show that bugged me because of varying number of episodes/show now only lists episodes for one Friday's show(example of no show folder, too).
Last edited by PaulF on Thu Sep 09, 2010 5:47 pm, edited 1 time in total.
User avatar
PaulF
Developer
 
Posts: 420
Joined: Sat May 08, 2010 8:34 pm
Location: Oregon

Re: Plugin: Today's Podcasts w/thumbs   

Postby chameleon_skin » Wed Sep 08, 2010 10:51 pm

Perfect! So now we can have both a high-level "Daily Podcasts" folder in UMSP (so they don't get mixed up with Revision3, etc), as well as subfolders within that and episodes of individual podcasts in their own directories. That's really good - better than iTunes taxonomy, actually.

I hadn't even considered the "Science Friday" problem of determining how many episodes to download. I subscribe to a bunch of podcasts, and every one of them is a daily frequency or more. So I think pegging the <limit>Xs</limit> functionality at 12 hours works great.

I'm going to try to update my web app to incorporate your new features, but for some reason my paying clients want me to get some coding done for them. I'll try to get it done within the next week or so, though.
User avatar
chameleon_skin
Developer
 
Posts: 148
Joined: Fri Aug 20, 2010 10:21 am
Location: Bay Area, California

Re: Plugin: Today's Podcasts w/thumbs   

Postby PaulF » Fri Sep 10, 2010 8:50 pm

Since daily-podcasts now has a folder tree, I now enable daily-podcasts in the webend daily-podcasts configure page. The script will now look for a config key called DAILY_PODCASTS_XML. The key should point to an XML file. No need for a /conf/umsp.php MediaItem(although that method still works).

Code: Select all
For enabling:
Do:       config_tool -c DAILY_PODCASTS_XML=<xml file path>
Go to:   http://<wdtvlive IP>/plugins/umsp/config.php
User avatar
PaulF
Developer
 
Posts: 420
Joined: Sat May 08, 2010 8:34 pm
Location: Oregon

Re: Plugin: Today's Podcasts w/thumbs   

Postby chameleon_skin » Sat Sep 11, 2010 12:07 am

I've got my web application set up to use your new features. However, it looks like your new code isn't properly pulling some podcasts under the new structure. Here is a section of my new xml document:

Code: Select all
<?xml version="1.0" encoding="UTF-8"?>
<list>
  <item>
    <description>Politics</description>
    <item>
      <description>Lawrence Lessig</description>
      <url>http://lessig.blip.tv/rss/itunes</url>
      <limit>3</limit>
    </item>
    <item>
      <description>KQED's Forum</description>
      <item>
        <description>KQED's Forum</description>
        <url>http://www.kqed.org/.pod/forum</url>
      </item>
    </item>
    <item>
      <description>KQED's The California Report Podcast</description>
      <item>
        <description>KQED's The California Report Podcast</description>
        <url>http://www.npr.org/rss/podcast.php?id=510005</url>
      </item>
    </item>
    <item>
      <description>NPR Programs: Talk of the Nation</description>
      <item>
        <description>NPR Programs: Talk of the Nation</description>
        <url>http://www.npr.org/templates/rss/podcast/TOTNPodcast.xml</url>
        <limit>2s</limit>
      </item>
    </item>
  </item>
</list>


The episodes of "Lawrence Lessig" and "Talk of the Nation" are being properly pulled, but the episodes of KQED Forum and the California Report are not - I'm getting a "no media on server" error. So you can see that some, but not all, of the podcasts I have in individual subdirectories of "Politics" are not retrieving episodes.

To ensure it isn't a problem with the podcast itself, I kept around my xml files from your old XMLformat as well. With that xml, it is pulling the episodes of Forum correctly:

Code: Select all
<?xml version="1.0" encoding="UTF-8"?>
<list>
  <item>
    <description>KQED's Forum</description>
    <url>http://www.kqed.org/.pod/forum</url>
  </item>
  <item>
    <description>NPR: Hourly News Summary Podcast</description>
    <url>http://www.npr.org/rss/podcast.php?id=500005</url>
  </item>
  <item>
    <description>KQED's The California Report Podcast</description>
    <url>http://www.npr.org/rss/podcast.php?id=510005</url>
  </item>
</list>


If it will help you to troubleshoot, I can send you both sets of XML files in their entirety - let me know.
User avatar
chameleon_skin
Developer
 
Posts: 148
Joined: Fri Aug 20, 2010 10:21 am
Location: Bay Area, California

Re: Plugin: Today's Podcasts w/thumbs   

Postby PaulF » Sat Sep 11, 2010 11:20 am

The apostrophes in the descriptions were being escaped with backslashes and the the backslashes were being escaped with parse_str. Google pointed me to stripcslashes() after several search attempts. Hope that fixes it. Going mountain biking(much tamer than b-rad). Will check back later today.
User avatar
PaulF
Developer
 
Posts: 420
Joined: Sat May 08, 2010 8:34 pm
Location: Oregon

Re: Plugin: Today's Podcasts w/thumbs   

Postby chameleon_skin » Sat Sep 11, 2010 7:42 pm

I checked it out, and now it works great for me. I've uploaded the changes to my webapp to include support for your new features. I've also added instructions on the output page with step-by-step instructions on enabling the plugin, how to make changes via config-tool, etc.
User avatar
chameleon_skin
Developer
 
Posts: 148
Joined: Fri Aug 20, 2010 10:21 am
Location: Bay Area, California

Re: Plugin: Today's Podcasts w/thumbs   

Postby PaulF » Sat Sep 11, 2010 11:04 pm

chameleon_skin wrote:I checked it out, and now it works great for me. I've uploaded the changes to my webapp to include support for your new features. I've also added instructions on the output page with step-by-step instructions on enabling the plugin, how to make changes via config-tool, etc.
Great, thanks. At least two of us are using it. I use it almost every day.

"Science Friday" got me again today. This Friday's episodes kept showing up twice. I added dumps everywhere in my code and finally figured out the NPR feed actually has the dupes.
User avatar
PaulF
Developer
 
Posts: 420
Joined: Sat May 08, 2010 8:34 pm
Location: Oregon

Re: Plugin: Today's Podcasts w/thumbs   

Postby mad_ady » Sat Nov 20, 2010 12:53 am

Quick question - is there a way to reverse the order of the feeds as they are displayed in the UMSP server? I have some feeds that are sorted oldest-first and I'd like to know if I can do anything from the configuration to reverse the sort:

For instance, this RSS is sorted properly when viewed with a RSS reader: http://www.ted.com/talks/rss, but appears reversed when viewed in Daily podcasts
Code: Select all
<item>                                                                 
        <description>TED Talks</description>                               
        <item>                                             
            <description>TED Talks</description>             
            <url>http://www.ted.com/talks/rss</url>     
            <limit>48</limit>                                           
        </item>                                                 
    </item>             


If this has already been discussed and I missed it, please kick me to the right thread :)
User avatar
mad_ady
Developer
 
Posts: 2996
Joined: Fri Nov 05, 2010 9:08 am
Location: Bucharest, Romania

Next

Return to UMSP Plugins

Who is online

Users browsing this forum: No registered users and 3 guests