java 1.6 jogl issues on mac os x

marcus • April 30th, 2008

after apple released java 1.6 for mac os x today to the public i got curious to see how my processing (v0135) sketches/apps worked with the new version. unfortunately once you switch to 1.6 in your java preferences, processings opengl throws java.lang.UnsatisfiedLinkErrors after messing around with it for a while i discovered that you had to upgrade to the latest nightly jogl build to make it work...

until the processing team releases a fixed version use this updated library to solve your mac p5/opengl issues. (simply replace the old opengl folder in your ./Processing 0135/libraries/ directory) » opengl-mac-java1.6-fix.zip
 

libCollada 0.2 released

marcus • September 22nd, 2007





libCollada now does colors!

the library is getting nearer to being actually useful. it now creates new collada materials and effects for you as needed without writing a line of extra code.

» project page
» download collada-0.2.zip

libCollada 0.1 released

marcus • September 14th, 2007

finally i found some time to finish a first release of my collada library for processing today.

it’s still quite basic and only exports triangles without any material information. however there have been major refactorings under the hood that will allow to add new features much easier.

it might output garbage when you try to do something clever but give it a go
- your comments & critics are appreciated!

» project page

» download collada-0.1.zip

libCollada examples: point cloud

marcus • September 14th, 2007

A simple point cloud generated in processing, exported with libCollada and rendered in Maya/ MentalRay. (The code is also included in the libCollada distribution examples)






opensource

marcus • September 14th, 2007

Processing Libraries

» libCollada – a collada export plugin for processing

» libTablet – cross-platform drawing tablet support for processing

mysql backup script 0.1

marcus • May 26th, 2007

here’s a way to quickly backup all databases from a mysql server.
can be easily automated with a cronjob.

download the source

#!/usr/bin/env ruby -w

require "mysql"
require "fileutils"
require "rubygems"
require_gem "actionmailer"

# --------------------------------------------------------------------------------
# mysql backup script
# platform: linux/ mac os x
# author: Marcus Wendt (www.marcuswendt.com)
# created: Jan 10, 2007
# version: 0.1
# --------------------------------------------------------------------------------
module MW
  module Utils
    class MySQLBackup
      # configuration
      @@name = 'backup-name'
      @@baseurl = 'https://www.your-host.com/backup_dir'

      @@db_server = 'localhost'
      @@db_user = 'XXXX'
      @@db_pass = 'XXX'

      # further options
      @@verbose = true
      @@verbose_level = 1 # set this to 0 to see all messages
      @@mysqLdump = '/usr/local/mysql/bin/mysqldump'
      @@file_opts = {}
      @@tar_opts = 'cjf'
      @@tar_suffix = 'tar.bz2'

      # do it!
      def initialize
        @@file_opts = {:verbose => @@verbose} if @@verbose_level == 0

        @time_start = Time.now
        nl
        line
        log "mysql backup script started #{format_time(@time_start)} ..."
        line

        # setup directories
        nl
        log "> checking directory structure"
        FileUtils.mkdir_p(archive_dir, @@file_opts)
        remove_tmp
        FileUtils.mkdir_p(tmp_dir, @@file_opts)

        # dump data
        nl
        log "> dumping databases"
        for db in databases
          log  "  #{db} ..."
          exec "    #{@@mysqLdump} --user=#{@@db_user} --password=#{@@db_pass} #{db} > #{tmp_dir}/#{db}.sql"
        end

        # compress data
        nl
        log "> creating archive"
        FileUtils.cd(tmp_dir, @@file_opts)
        exec "  tar #{@@tar_opts} #{filename} *.sql"
        FileUtils.mv("#{tmp_dir}/#{filename}", "#{archive_dir}/#{filename}", @@file_opts)

        # clean up
        nl
        log "> cleaning up"
        remove_tmp

        # show final message
        @time_end = Time.now
        duration = round(@time_end - @time_start,2)
        nl
        log "finished! (script executed in #{duration} seconds)"

        # send notifications
      end

      # name of the current archive file
      def filename
         "#{name}.#{@@tar_suffix}"
      end

      # name of the current backup
      def name
        "#{timestamp}_#{@@name}"
      end

      def wd
        Dir.getwd    
      end

      def format_time(time)
        time.strftime("%H:%M")    
      end

      def timestamp
        @timestamp = Time.now.strftime("%Y.%m.%d_%H_%M") if @timestamp.nil?
        return @timestamp
      end

      def archive_dir
        @archive_dir = "#{wd}/archives" if @archive_dir.nil?
        return @archive_dir
      end

      def tmp_dir
        "#{archive_dir}/tmp"
      end

      def remove_tmp
        FileUtils.rm_rf(tmp_dir, @@file_opts) if File.exists?(tmp_dir)
      end

      def databases
        database_list=[]
        db = MySQLHelper.new 
        db.connect(@@db_server, @@db_user, @@db_pass)
        dbr = db.query('SHOW DATABASES')
        while row = dbr.fetch_row
          database_list << row.to_s
        end
        dbr.free
        db.close
        return database_list
      end

      def exec(command)
        log(command.gsub(@@db_pass, '****').gsub(@@db_user, '****'), 0)
        return `#{command}`
      end

      def log(str, level=1)
        puts str if @@verbose && level >= @@verbose_level
      end

      def line
        log "----------------------------------------------------"
      end

      def nl 
        log ""
      end

      def round(numeric, precision)
        pow=10.0**precision.to_f
        (numeric*pow).round / pow
      end
    end

    # helper classes
    # ----------------------------------------------------------------------
    class MySQLHelper
      def connect(server, user, pass)
        begin
          @dbh = Mysql.real_connect(server, user, pass)
        rescue Mysql::Error => e
          puts "Error code: #{e.errno}"
          puts "Error message: #{e.error}"
          puts "Error SQLSTATE: #{e.sqlstate}" if e.respond_to?("sqlstate")
        end
      end

      def query(sql)
        @dbr = @dbh.query(sql) if @dbh
      end

      def free
        @dbr.free if @dbr
      end

      def close
        @dbh.close if @dbh
      end
    end
  end
end

# go!
MW::Utils::MySQLBackup.new

Strip contact data from strings

marcus • May 26th, 2007

we had to find a way to prevent users from publishing their contact information for our documenta accommodation project. here are a few regexp's that make you life easier (it's not 100% waterproof, but prevents most forms of cheating)
patterns = [
  /([\w\._%-]+[\s]*)(@|at|\[at\]|\(at\))([\s]*[\w\.-]+[\s]*\.[\s]*[a-zA-Z]{2,4})/i,
  /([http\:\/\/]*)([\s]*)([www\.]*)([\s]*)([\w\.-]+)([\s]*)\.([\s]*)(de|at|ch|com|org|net)/i,
  /[\d]{2,}/
]

result = orig
for p in patterns
  result = result.gsub(p, '')
end
the full script, including test:
#!/usr/bin/env ruby -w

#
# INPUT
#
orig = 
"""test@web.de
test2 @ web.de
test3 @ web . de
test4 AT web.de
test5(aT)betrug.de
test6 (at) betrug.de
test7[At]betrug.de
test8 [at] betrug.de
http://www.betrug.de
www.betrug.de
betrug.de
www.betrug.com
http://www.betrug.com
www . betrug . com
www. betrug.de
01702138958
01602138958 
0171 2138958
0561 1234567
+49 171 2138958
00491712138958
171 213895
"""

#
# REGEXP PATTERNS 
#
patterns = [
  /([\w\._%-]+[\s]*)(@|at|\[at\]|\(at\))([\s]*[\w\.-]+[\s]*\.[\s]*[a-zA-Z]{2,4})/i,
  /([http\:\/\/]*)([\s]*)([www\.]*)([\s]*)([\w\.-]+)([\s]*)\.([\s]*)(de|at|ch|com|org|net)/i,
  /[\d]{2,}/
]

result = orig
for p in patterns
  result = result.gsub(p, '')
end


#
# TEST
#
spacer = ""; 50.times do  spacer << "-" end
  
puts spacer
puts "ORIGINAL"
puts spacer

i=0
for line in orig
  puts "#{i}: #{line}"
  i=i+1
end  

puts spacer

i=0
for line in result
  puts "#{i}: #{line}"
  i=i+1
end

Easy templating in ruby

marcus • May 26th, 2007

ruby templating the easy way:
#!/usr/bin/ruby -w

require 'erb'

module MW
  module Utils
    module Template
      
      ENDL = "\n"
      
      #
      # compiles the given template
      #
      def self.compile(template, locals={})
        # create code for easyaccess locals
        local_code = "<% " << ENDL
        for key in locals.keys
          local_code << "#{key} = locals[:#{key}]" << ENDL
        end
        local_code << "%>" << ENDL
        template = local_code << template
  
  puts template
  
        # compile template
        erb = ERB.new(template, 0, "%<>")
        compiled = erb.result(binding)
        compiled.gsub(/\n$/,'') # chomp the trailing newline
      end
    end
  end
end


#
# test 1
#
t = "hi <%= firstname %> <%= lastname %>"
puts MW::Utils::Template.compile(t, :firstname=>"peter", :lastname=>"meier")
puts MW::Utils::Template.compile(t, :firstname=>"marcus", :lastname=>"wendt")

#
# test 2
#
class TestUser
  attr_accessor :first, :last
end

u = TestUser.new
u.first = "peter"
u.last = "meier"

t = "hallo <%= user.first %> <%= user.last %>"
puts MW::Utils::Template.compile(t, :user=>u)

random pronounceable password generator

marcus • May 26th, 2007

a quick & simple random pronounceable password generator for ruby.

def random_pronouncable_password(size = 6)
  consonants = %w(b c d f g h j k l m n p qu r s t v w x z ch cr fr nd ng nk nt ph pr rd sh sl sp
st th tr 0 1 2 3 4 5 6 7 8 9 0)
  vocals = %w(a e i o u y)
  
  alternate=true
  password=''
  
  (size * 2).times do
    # get a random vocal or consonant
    chunk = (alternate ? consonants[rand * consonants.size] : vocals[rand * vocals.size])
    alternate = !alternate
    # randomly swap its case & add to password
    chunk = chunk.swapcase if rand > 0.5
    password << chunk
  end
  
  password
end
3d 4-space abstract aesthetic system aesthetics algorithm alien ambient ambisonics animation architecture art artificial audio audio research black&white book caskets classic clicks & cuts code color computer-vision conceptual art consoles cpp culture ddr design devices digtial fabrication documenta documentation drawing dynamics electricity electromagnetism electronics environment event exhibition experimental exploration fashion festival film flocking folk food fractal furniture gamedev generative genetic geometry glitch graphic hacks haptics hardware history hyperspace ideas illustration images inspiration installation instrument intelligence interactive interieur japan java knowledge management landscape library life light liquid live london math micro minimal modernism monochrome motion motion graphics multiples music naming nature nervous ink networked networking opensource osx painting paper particles performance personal photography physics playful politics press print processing processing.org programming quotes recipes research retro romance ruby scripts sculpture SENDUNG.net shopping snippets social software sound space space exploration craft space exploration craft orbiter supercollider swiss systems technology theory theremin toys transformed travel tricks typography universe video visual vj water web2.0 xcode