cache_dir != '') { $cache_file = $this->cache_dir.'/rsscache_'.md5($rss_url); $timedif = @ (time() - filemtime($cache_file)); if ($timedif < $this->cache_time) { // cached file is fresh enough, return cached array $result = unserialize(join('', file($cache_file))); // set 'cached' to 1 only if cached file is correct if ($result) $result['cached'] = 1; } else { // cached file is too old, create new $result = $this->Parse($rss_url); $serialized = serialize($result); if ($f = @ fopen($cache_file, 'w')) { fwrite($f, $serialized, strlen($serialized)); fclose($f); } if ($result) $result['cached'] = 0; } } // If CACHE DISABLED >> load and parse the file directly else { $result = $this->Parse($rss_url); if ($result) $result['cached'] = 0; } // return result return $result; } // ------------------------------------------------------------------- // Modification of preg_match(); return trimed field with index 1 // from 'classic' preg_match() array output // ------------------------------------------------------------------- function my_preg_match($pattern, $subject) { // start regullar expression preg_match($pattern, $subject, $out); // if there is some result... process it and return it if (isset ($out[1])) { // Process CDATA (if present) if ($this->CDATA == 'content') { // Get CDATA content (without CDATA tag) $out[1] = strtr($out[1], array (' '', ']]>' => '')); } elseif ($this->CDATA == 'strip') { // Strip CDATA $out[1] = strtr($out[1], array (' '', ']]>' => '')); } // If code page is set convert character encoding to required if ($this->cp != '') //$out[1] = $this->MyConvertEncoding($this->rsscp, $this->cp, $out[1]); $out[1] = iconv($this->rsscp, $this->cp.'//TRANSLIT', $out[1]); // Return result return trim($out[1]); } else { // if there is NO result, return empty string return ''; } } // ------------------------------------------------------------------- // Replace HTML entities &something; by real characters // ------------------------------------------------------------------- function unhtmlentities($string) { // Get HTML entities table $trans_tbl = get_html_translation_table(HTML_ENTITIES, ENT_QUOTES); // Flip keys<==>values $trans_tbl = array_flip($trans_tbl); // Add support for ' entity (missing in HTML_ENTITIES) $trans_tbl += array (''' => "'"); // Replace entities by values return strtr($string, $trans_tbl); } // ------------------------------------------------------------------- // Parse() is private method used by Get() to load and parse RSS file. // Don't use Parse() in your scripts - use Get($rss_file) instead. // ------------------------------------------------------------------- function Parse($rss_url) { // Open and load RSS file $urlParts = parse_url($rss_url); $host = $urlParts['host']; $uri = $urlParts['path']; if (strcmp($urlParts['query'], '') != 0) { $uri .= '?'.$urlParts['query']; } if (strcmp($urlParts['fragment'], '') != 0) { $fragment = $urlParts['fragment']; $fragment = substr($fragment, 4, strlen($fragment) - 3); $uri = $uri.$fragment; } if ($f = fsockopen($host, 80, $errno, $errstr, $this->connection_time)) { $rss_content = ''; fputs($f, "GET $uri HTTP/1.0\r\nHost: $host\r\n\r\n"); while (!feof($f)) { $rss_content .= fgets($f, 512); } fclose($f); // Parse document encoding $result['encoding'] = $this->my_preg_match("'encoding=[\'\"](.*?)[\'\"]'si", $rss_content); // if document codepage is specified, use it if ($result['encoding'] != '') { $this->rsscp = $result['encoding']; } // This is used in my_preg_match() // otherwise use the default codepage else { $this->rsscp = $this->default_cp; } // This is used in my_preg_match() // Parse CHANNEL info preg_match("'(.*?)'si", $rss_content, $out_channel); foreach($this->channeltags as $channeltag) { $temp = $this->my_preg_match("'<$channeltag.*?>(.*?)'si", $out_channel[1]); if ($temp != '') $result[$channeltag] = $temp; // Set only if not empty } // If date_format is specified and lastBuildDate is valid if ($this->date_format != '' && ($timestamp = strtotime($result['lastBuildDate'])) !== -1) { // convert lastBuildDate to specified date format $result['lastBuildDate'] = date($this->date_format, $timestamp); } // Parse TEXTINPUT info preg_match("']*[^/])>(.*?)'si", $rss_content, $out_textinfo); // This a little strange regexp means: // Look for tag with or without any attributes, but skip truncated version (it's not beggining tag) if (isset ($out_textinfo[2])) { foreach ($this->textinputtags as $textinputtag) { $temp = $this->my_preg_match("'<$textinputtag.*?>(.*?)'si", $out_textinfo[2]); if ($temp != '') $result['textinput_'.$textinputtag] = $temp; // Set only if not empty } } // Parse IMAGE info preg_match("']*>(.*?)'si", $rss_content, $out_imageinfo); if (isset ($out_imageinfo[1])) { foreach ($this->imagetags as $imagetag) { $temp = $this->my_preg_match("'<$imagetag.*?>(.*?)'si", $out_imageinfo[1]); if ($temp != '') $result['image_'.$imagetag] = $temp; // Set only if not empty } } // Parse ITEMS preg_match_all("'(.*?)'si", $rss_content, $items); $rss_items = $items[2]; $i = 0; $result['items'] = array (); // create array even if there are no items foreach ($rss_items as $rss_item) { // If number of items is lower then limit: Parse one item if ($i < $this->items_limit || $this->items_limit == 0) { foreach ($this->itemtags as $itemtag) { $temp = $this->my_preg_match("'<$itemtag.*?>(.*?)'si", $rss_item); if ($temp != '') $result['items'][$i][$itemtag] = $temp; // Set only if not empty } // Strip HTML tags and other bullshit from DESCRIPTION if ($this->stripHTML && $result['items'][$i]['description']) $result['items'][$i]['description'] = strip_tags($this->unhtmlentities(strip_tags($result['items'][$i]['description']))); // Strip HTML tags and other bullshit from TITLE if ($this->stripHTML && $result['items'][$i]['title']) $result['items'][$i]['title'] = strip_tags($this->unhtmlentities(strip_tags($result['items'][$i]['title']))); // If date_format is specified and pubDate is valid if ($this->date_format != '' && ($timestamp = strtotime($result['items'][$i]['pubDate'])) !== -1) { // convert pubDate to specified date format $result['items'][$i]['pubDate'] = date($this->date_format, $timestamp); } // Item counter $i ++; } } $result['items_count'] = $i; return $result; } else { return False; //die("Network error: $errstr ($errno)"); } } } ?> blog:ludens


Dutch Design Week 2008

~ studio:ludens @ 0:39 Europe/Amsterdam

Dutch Design WeekOnce again, we are present and showing our products on the Dutch Design Week 2008 in Eindhoven. This time, we have something new to show you. If you want to check out what we’ve been working on the past months, you should definitely check us out! you can find us at the Klokgebouw building on Strijp S.

Official Dutch Design Week website

Our flyer front


Klokgebouw   Strijp-S
Beukenlaan 10151
5616 VJ Eindhoven
Za/18 okt    12:00 - 19:00
Zo/19 okt t/m Wo/22 okt   12:00 - 18:00
Do/25okt t/m Za/25 oct   12:00 - 21:00
Zo/26 okt    12:00 - 18:00

Design your own…

Who wouldn’t want to own a unique lamp, carpet or
coaster, designed by oneself?
With the digital design tools from studio:ludens everyone
can playfully design their own product. The easy controls
provide you with full creative freedom to make something
that tightly fits your personal taste.
…and take your own design-coaster home for free!

Come around and design your own Escher-inspired
coaster. With a laser cutter we’ll produce your design on
the spot. Impress everyone at home with your design

Bookmark and Share


3D Voice Experiment

~ studio:ludens @ 15:29 Europe/Amsterdam

We are experimenting with a 3D shape generator that responds to your voice. Here is a quick and dirty test we did. We are using vvvv to prototype this.


Youtube video

Bookmark and Share


Feedback is important

~ studio:ludens @ 20:30 Europe/Amsterdam


We at studio:ludens are working hard to create the coolest, prettiest, and most useful products. To do this. we need your input. Why? If we want to create a product that should suit each individual, we need to know what each of them thinks. And, in this case, that means you. We want to be open to everybody who has an opinion on what we do. We believe that this is the only way to create truly personalised products.

That’s why we’d love to hear from you. We want to invite you to tell us what you think of our products. Yor personal opinion is what matters here. Every comment will help us to improve our products and get inspired. So, post a comment and help us help you!

The studio:ludens Design Team

Bookmark and Share


epa:kato, our new product

~ studio:ludens @ 17:44 Europe/Amsterdam

epa:kato online design tool

After a couple of weeks of testing, tweaking and tuning, we are ready to present to you epa:kato, ‘design your own coaster’. With this on-line design tool (based on Flash), you can play with shape, patterns and repetition to create a unique design. Read more on the product page

Example coasters - with pouch

The pattern system

To help you design a shape that always fits together (really, all shapes always fit together!) we use the system of regular tilings in our application. So, when you create a piece of the shape, it will be repeated in different ways to create the eventual design.


epa:kato is a new type of mass customization application. When we design something, we like the open-endedness of the process. We have as much freedom as the materials and production process can give us. We try to translate this feeling of freedom and control to an intuitive interface in our design tools. You shouldn’t be forced to select options from a list, but have as much of the possibilities the production process provides as possible. That’s why we are experimenting with a free form spline tool.

Application screenshot

Your feedback

We realise our design tool is far from perfect. We would like to see this as an experiment where we include you in the design process. After all, it’s you we’re designing the design tools for :).

We would love to hear your responses to our application. So, if you have comments, critique, questions, suggestions for improvement or praise, please let us know by posting a comment to this blog post.

Bookmark and Share


pictures of DDW

~ studio:ludens @ 15:30 Europe/Amsterdam

Dutch Design WeekThe Dutch Design Week has been a success for us; we had over 250 visitors coming to see the Little Mountain creative environment and our exhibition. We showed the prototypes for out two new online design applications: lux:ludens and coaster:2.0. We received the most interest for the latter: an easy and fun way to design your own coasters. Based on the feedback we got from visitors, we decided to bring this product to you first.

Click through for some photos of our humble exhibition.

Bookmark and Share


Coaster 2.0 update

~ studio:ludens @ 15:29 Europe/Amsterdam

coaster 2.0

Now with text!

Well, we updated our coaster:2.0 design application with a number of new things. First of all, we implemented a way to add your own text to the coaster. It’s working now with four different fonts.

Coaster 2.0 now with text

Six pattern types

More patternsSecondly, you have now the ability to experiment with six different pattern types. We got a little bored with the same square rotational pattern, so we made it into a little pattern family. Each pattern has it’s own style, peculiarities and possibilities. Additionally, the hexagonal shapes will give you some more safety margin in creating a sturdy coaster.

And remember: we want designing, experimenting and learning to be free! Our ordering and production system is nearing completion, so soon you will be able to transform your design into a real tangible product. Happy designing!

Bookmark and Share


coaster:2.0 - a creative design tool

~ studio:ludens @ 15:26 Europe/Amsterdam

coaster 2.0

a new sound in mass-customization

Mass-customization has giving you more control over the appearance of the products you buy. You can change the colors of your shoes (Puma) and turn a photo of your pet into everything from a mug to a teddybear ( We however missed the element of creativity in this process. Therefore, studio:ludens says “genere ludens!” (or “create through play!” for all us non-Romans).

a new design-tool for everyone

We hereby launch our very first online creative design tool: coaster:2.0. This tool gives you a major say in the design process of your own coasters. In a nutshell, this application offers you:

  • a fun and easy-to-use design interface
  • cool patterns in no-time
  • infinite design possibilities
  • an option to order your designs online (coming soon)

At the moment you can already design, log in and save designs you make. Very soon the order system will be up and running, allowing you to order your favorite design(s)!


Click the screenshot to start designing or read on for some examples of what you can create with this tool.

Bookmark and Share


Preparations for Dutch Design Week

~ studio:ludens @ 15:24 Europe/Amsterdam

In two weeks, the Dutch Design Week (DDW) will be raging through Eindhoven. From October the 20th to the 28th Eindhoven will be all about design. With over a hundred events scattered around the city, it sure is going to be an event worth remembering.And of course, studio:ludens will be showing off some fresh new work. We are pushing ourselves to finish a number of first prototypes and two on-line design applications, where you can be te designer for once!

To lift up a tip of the veil: the theme of this year’s exhibition by studio:ludens will be light. We have been working on a number of indoor lighting objects that are quite out of the ordinary.

Bookmark and Share