diff --git a/pyfpdb/Database.py b/pyfpdb/Database.py
index edf99cf0..7b376944 100755
--- a/pyfpdb/Database.py
+++ b/pyfpdb/Database.py
@@ -116,31 +116,30 @@ class Database:
         row = c.fetchone()
         return row[0]
 
-#    def get_cards(self, hand):
-#    this version is for the PTrackSv2 db
-#        c = self.connection.cursor()
-#        c.execute(self.sql.query['get_cards'], hand)
-#        colnames = [desc[0] for desc in c.description]
-#        cards = {}
-#        for row in c.fetchall():
-#            s_dict = {}
-#            for name, val in zip(colnames, row):
-#                s_dict[name] = val
-#            cards[s_dict['seat_number']] = s_dict
-#        return (cards)
-
     def get_cards(self, hand):
-#    this version is for the fpdb db
+        """Get and return the cards for each player in the hand."""
+        cards = {} # dict of cards, the key is the seat number example: {1: 'AcQd9hTs5d'}
         c = self.connection.cursor()
         c.execute(self.sql.query['get_cards'], hand)
         colnames = [desc[0] for desc in c.description]
-        cards = {}
         for row in c.fetchall():
             s_dict = {}
             for name, val in zip(colnames, row):
                 s_dict[name] = val
-            cards[s_dict['seat_number']] = s_dict
-        return (cards)
+            cards[s_dict['seat_number']] = (self.convert_cards(s_dict))
+        return cards
+
+    def convert_cards(self, d):
+        ranks = ('', '', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A')
+        cards = ""
+        for i in range(1, 8):
+            if d['card' + str(i) + 'Value'] == None:
+                break
+            elif d['card' + str(i) + 'Value'] == 0:
+                cards += "xx"
+            else:
+                cards += ranks[d['card' + str(i) + 'Value']] + d['card' +str(i) + 'Suit']
+        return cards
 
     def get_action_from_hand(self, hand_no):
         action = [ [], [], [], [], [] ]
@@ -214,6 +213,7 @@ if __name__=="__main__":
     for p in stat_dict.keys():
         print p, "  ", stat_dict[p]
 
+    print "cards =", db_connection.get_cards(73525)
     db_connection.close_connection
 
     print "press enter to continue"
diff --git a/pyfpdb/GuiBulkImport.py b/pyfpdb/GuiBulkImport.py
index 46ac3f0f..915e9a39 100755
--- a/pyfpdb/GuiBulkImport.py
+++ b/pyfpdb/GuiBulkImport.py
@@ -35,6 +35,20 @@ import Configuration
 
 class GuiBulkImport():
 
+    def import_dir(self):
+        """imports a directory, non-recursive. todo: move this to fpdb_import so CLI can use it"""
+
+        self.path = self.inputFile
+        self.importer.addImportDirectory(self.path)
+        self.importer.setCallHud(False)
+        starttime = time()
+        if not self.importer.settings['threads'] > 1:
+            (stored, dups, partial, errs, ttime) = self.importer.runImport()
+            print 'GuiBulkImport.import_dir done: Stored: %d Duplicates: %d Partial: %d Errors: %d in %s seconds - %d/sec'\
+                 % (stored, dups, partial, errs, ttime, stored / ttime)
+        else:
+            self.importer.RunImportThreaded()
+
     def load_clicked(self, widget, data=None):
 #    get the dir to import from the chooser
         self.inputFile = self.chooser.get_filename()
@@ -66,6 +80,7 @@ class GuiBulkImport():
         self.lab_info.set_text("Import finished")
 
     def get_vbox(self):
+        """returns the vbox of this thread"""
         return self.vbox
 
     def __init__(self, db, settings, config):
diff --git a/pyfpdb/HUD_main.py b/pyfpdb/HUD_main.py
index a8b800d1..2084850b 100755
--- a/pyfpdb/HUD_main.py
+++ b/pyfpdb/HUD_main.py
@@ -29,6 +29,11 @@ Main for FreePokerTools HUD.
 
 #    Standard Library modules
 import sys
+
+#    redirect the stderr
+errorfile = open('HUD-error.txt', 'w', 0)
+sys.stderr = errorfile
+
 import os
 import thread
 import time
@@ -72,7 +77,7 @@ class HUD_main(object):
     def destroy(*args):             # call back for terminating the main eventloop
         gtk.main_quit()
     
-    def create_HUD(self, new_hand_id, table, table_name, max, poker_game, is_tournament, stat_dict):
+    def create_HUD(self, new_hand_id, table, table_name, max, poker_game, is_tournament, stat_dict, cards):
         
         def idle_func():
             
@@ -82,20 +87,21 @@ class HUD_main(object):
                 self.vb.add(newlabel)
                 newlabel.show()
     
-                self.hud_dict[table_name] = Hud.Hud(self, table, max, poker_game, self.config, self.db_connection)
                 self.hud_dict[table_name].tablehudlabel = newlabel
-                self.hud_dict[table_name].create(new_hand_id, self.config, stat_dict)
+                self.hud_dict[table_name].create(new_hand_id, self.config, stat_dict, cards)
                 for m in self.hud_dict[table_name].aux_windows:
                     m.update_data(new_hand_id, self.db_connection)
                     m.update_gui(new_hand_id)
-                self.hud_dict[table_name].update(new_hand_id, self.config, stat_dict)
+                self.hud_dict[table_name].update(new_hand_id, self.config)
                 self.hud_dict[table_name].reposition_windows()
                 return False
             finally:
                 gtk.gdk.threads_leave()
+
+        self.hud_dict[table_name] = Hud.Hud(self, table, max, poker_game, self.config, self.db_connection)
         gobject.idle_add(idle_func)
     
-    def update_HUD(self, new_hand_id, table_name, config, stat_dict):
+    def update_HUD(self, new_hand_id, table_name, config):
         """Update a HUD gui from inside the non-gui read_stdin thread."""
 #    This is written so that only 1 thread can touch the gui--mainly
 #    for compatibility with Windows. This method dispatches the 
@@ -103,7 +109,7 @@ class HUD_main(object):
         def idle_func():
             gtk.gdk.threads_enter()
             try:
-                self.hud_dict[table_name].update(new_hand_id, config, stat_dict)
+                self.hud_dict[table_name].update(new_hand_id, config)
                 for m in self.hud_dict[table_name].aux_windows:
                     m.update_gui(new_hand_id)
                 return False
@@ -145,6 +151,7 @@ class HUD_main(object):
             try:
                 (table_name, max, poker_game) = self.db_connection.get_table_name(new_hand_id)
                 stat_dict = self.db_connection.get_stats_from_hand(new_hand_id)
+                cards = self.db_connection.get_cards(new_hand_id)
             except:
                 print "skipping ", new_hand_id
                 sys.stderr.write("Database error in hand %d. Skipping.\n" % int(new_hand_id))
@@ -163,9 +170,11 @@ class HUD_main(object):
 
 #    Update an existing HUD
             if temp_key in self.hud_dict:
+                self.hud_dict[temp_key].stat_dict = stat_dict
+                self.hud_dict[temp_key].cards = cards
                 for aw in self.hud_dict[temp_key].aux_windows:
                     aw.update_data(new_hand_id, self.db_connection)
-                self.update_HUD(new_hand_id, temp_key, self.config, stat_dict)
+                self.update_HUD(new_hand_id, temp_key, self.config)
     
 #    Or create a new HUD
             else:
@@ -175,11 +184,12 @@ class HUD_main(object):
                     tablewindow = Tables.discover_table_by_name(self.config, table_name)
 
                 if tablewindow == None:
+#    If no client window is found on the screen, complain and continue
                     if is_tournament:
                         table_name = tour_number + " " + tab_number
                     sys.stderr.write("table name "+table_name+" not found, skipping.\n")
                 else:
-                    self.create_HUD(new_hand_id, tablewindow, temp_key, max, poker_game, is_tournament, stat_dict)
+                    self.create_HUD(new_hand_id, tablewindow, temp_key, max, poker_game, is_tournament, stat_dict, cards)
 
 if __name__== "__main__":
     sys.stderr.write("HUD_main starting\n")
diff --git a/pyfpdb/Hud.py b/pyfpdb/Hud.py
index f77b7318..12f66175 100644
--- a/pyfpdb/Hud.py
+++ b/pyfpdb/Hud.py
@@ -48,6 +48,8 @@ import HUD_main
 class Hud:
     
     def __init__(self, parent, table, max, poker_game, config, db_connection):
+#    __init__ is (now) intended to be called from the stdin thread, so it
+#    cannot touch the gui
         self.parent        = parent
         self.table         = table
         self.config        = config
@@ -57,26 +59,28 @@ class Hud:
         self.deleted       = False
         self.stacked       = True
         self.site          = table.site
-        self.colors = config.get_default_colors(self.table.site)
+        self.mw_created    = False
 
-        self.stat_windows = {}
+        self.stat_windows  = {}
         self.popup_windows = {}
-        self.aux_windows = []
+        self.aux_windows   = []
         
         (font, font_size) = config.get_default_font(self.table.site)
+        self.colors        = config.get_default_colors(self.table.site)
+
         if font == None:
             font = "Sans"
         if font_size == None:
             font_size = "8"
-            
-        self.font = pango.FontDescription(font + " " + font_size)
-            
+        self.font = pango.FontDescription(font + " " + font_size)            
         # do we need to add some sort of condition here for dealing with a request for a font that doesn't exist?
 
+    def create_mw(self):
+
 #	Set up a main window for this this instance of the HUD
         self.main_window = gtk.Window()
         self.main_window.set_gravity(gtk.gdk.GRAVITY_STATIC)
-        self.main_window.set_title(table.name + " FPDBHUD")
+        self.main_window.set_title(self.table.name + " FPDBHUD")
         self.main_window.destroyhandler = self.main_window.connect("destroy", self.kill_hud)
         self.main_window.set_decorated(False)
         self.main_window.set_opacity(self.colors["hudopacity"])
@@ -123,6 +127,7 @@ class Hud:
         self.ebox.connect_object("button-press-event", self.on_button_press, self.menu)
 
         self.main_window.show_all()
+        self.mw_created = True
 
 # TODO: fold all uses of this type of 'topify' code into a single function, if the differences between the versions don't
 # create adverse effects?
@@ -228,13 +233,17 @@ class Hud:
                 return self.stat_dict[key]['seat']
         sys.stderr.write("Error finding actual seat.\n")
 
-    def create(self, hand, config, stat_dict):
+    def create(self, hand, config, stat_dict, cards):
 #    update this hud, to the stats and players as of "hand"
 #    hand is the hand id of the most recent hand played at this table
 #
 #    this method also manages the creating and destruction of stat
 #    windows via calls to the Stat_Window class
+        if not self.mw_created:
+            self.create_mw()
+            
         self.stat_dict = stat_dict
+        self.cards = cards
         sys.stderr.write("------------------------------------------------------------\nCreating hud from hand %s\n" % hand)
         adj = self.adj_seats(hand, config)
         sys.stderr.write("adj = %s\n" % adj)
@@ -274,37 +283,35 @@ class Hud:
         if os.name == "nt":
             gobject.timeout_add(500, self.update_table_position)
             
-    def update(self, hand, config, stat_dict):
+    def update(self, hand, config):
         self.hand = hand   # this is the last hand, so it is available later
-        self.stat_dict = stat_dict  # so this is available for popups, etc
         self.update_table_position()
-        self.stat_dict = stat_dict
 
-        for s in stat_dict:
+        for s in self.stat_dict:
             try:
-                self.stat_windows[stat_dict[s]['seat']].player_id = stat_dict[s]['player_id']
+                self.stat_windows[self.stat_dict[s]['seat']].player_id = self.stat_dict[s]['player_id']
             except: # omg, we have more seats than stat windows .. damn poker sites with incorrect max seating info .. let's force 10 here
                 self.max = 10
-                self.create(hand, config, stat_dict)
-                self.stat_windows[stat_dict[s]['seat']].player_id = stat_dict[s]['player_id']
+                self.create(hand, config, self.stat_dict, self.cards)
+                self.stat_windows[self.stat_dict[s]['seat']].player_id = self.stat_dict[s]['player_id']
                 
             for r in range(0, config.supported_games[self.poker_game].rows):
                 for c in range(0, config.supported_games[self.poker_game].cols):
                     this_stat = config.supported_games[self.poker_game].stats[self.stats[r][c]]
-                    number = Stats.do_stat(stat_dict, player = stat_dict[s]['player_id'], stat = self.stats[r][c])
+                    number = Stats.do_stat(self.stat_dict, player = self.stat_dict[s]['player_id'], stat = self.stats[r][c])
                     statstring = this_stat.hudprefix + str(number[1]) + this_stat.hudsuffix
                     
                     if this_stat.hudcolor != "":
                         self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(self.colors['hudfgcolor']))
                         self.stat_windows[stat_dict[s]['seat']].label[r][c].modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse(this_stat.hudcolor))
                         
-                    self.stat_windows[stat_dict[s]['seat']].label[r][c].set_text(statstring)
+                    self.stat_windows[self.stat_dict[s]['seat']].label[r][c].set_text(statstring)
                     if statstring != "xxx": # is there a way to tell if this particular stat window is visible already, or no?
-                        self.stat_windows[stat_dict[s]['seat']].window.show_all()
+                        self.stat_windows[self.stat_dict[s]['seat']].window.show_all()
 #                        self.reposition_windows()
-                    tip = stat_dict[s]['screen_name'] + "\n" + number[5] + "\n" + \
+                    tip = self.stat_dict[s]['screen_name'] + "\n" + number[5] + "\n" + \
                           number[3] + ", " + number[4]
-                    Stats.do_tip(self.stat_windows[stat_dict[s]['seat']].e_box[r][c], tip)
+                    Stats.do_tip(self.stat_windows[self.stat_dict[s]['seat']].e_box[r][c], tip)
 
     def topify_window(self, window):
         """Set the specified gtk window to stayontop in MS Windows."""
diff --git a/pyfpdb/Mucked.py b/pyfpdb/Mucked.py
index 07021c7e..1e550edc 100755
--- a/pyfpdb/Mucked.py
+++ b/pyfpdb/Mucked.py
@@ -154,7 +154,7 @@ class Stud_list:
             winners = winners + player
         pot_dec = "%.2f" % (float(pot)/100)
 
-        hero_cards = self.get_hero_cards(self.parent.hero, self.parent.mucked_cards.cards)
+        hero_cards = self.get_hero_cards(self.parent.hero, self.parent.hud.cards)
         self.info_row = ((new_hand_id, hero_cards, pot_dec, winners), )
 
     def get_hero_cards(self, hero, cards):
@@ -163,11 +163,10 @@ class Stud_list:
         if hero == '':
             return "xxxxxx"
         else:
-            for k in cards.keys():
-                if cards[k]['screen_name'] == hero:
-                    return   trans[cards[k]['card1Value']] + cards[k]['card1Suit'] \
-                           + trans[cards[k]['card2Value']] + cards[k]['card2Suit'] \
-                           + trans[cards[k]['card3Value']] + cards[k]['card3Suit']
+#    find the hero's seat from the stat_dict
+            for stat in self.parent.hud.stat_dict.itervalues():
+                if stat['screen_name'] == hero:
+                    return self.parent.hud.cards[stat['seat']][0:6]
         return "xxxxxx"
             
     def update_gui(self, new_hand_id):
@@ -225,25 +224,7 @@ class Stud_cards:
                 
         self.container.add(self.grid)
 
-    def translate_cards(self, old_cards):
-        ranks = ('', '', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A')
-
-        for c in old_cards.keys():
-            for i in range(1, 8):
-                rank = 'card' + str(i) + 'Value'
-                suit = 'card' + str(i) + 'Suit'
-                key = 'hole_card_' + str(i)
-                if old_cards[c][rank] == 0:
-                    old_cards[c][key] = 'xx'
-                else:
-                    old_cards[c][key] = ranks[old_cards[c][rank]] + old_cards[c][suit]
-        return old_cards
-
     def update_data(self, new_hand_id, db_connection):
-#        db_connection = Database.Database(self.config, 'fpdb', '')
-        cards = db_connection.get_cards(new_hand_id)
-        self.cards = self.translate_cards(cards)
-
         self.tips = []
         action = db_connection.get_action_from_hand(new_hand_id)
         for street in action:
@@ -261,13 +242,13 @@ class Stud_cards:
 
     def update_gui(self, new_hand_id):
         self.clear()
-        for c in self.cards.keys():
-            self.grid_contents[(1, self.cards[c]['seat_number'] - 1)].set_text(self.cards[c]['screen_name'])
-            for i in ((0, 'hole_card_1'), (1, 'hole_card_2'), (2, 'hole_card_3'), (3, 'hole_card_4'), 
-                      (4, 'hole_card_5'), (5, 'hole_card_6'), (6, 'hole_card_7')):
-                if not self.cards[c][i[1]] == "xx":
-                    self.seen_cards[(i[0], self.cards[c]['seat_number'] - 1)]. \
-                        set_from_pixbuf(self.card_images[self.split_cards(self.cards[c][i[1]])])
+        for c, cards in self.parent.hud.cards.iteritems():
+            self.grid_contents[(1, c - 1)].set_text(self.get_screen_name(c))
+            for i in ((0, cards[0:2]), (1, cards[2:4]), (2, cards[4:6]), (3, cards[6:8]), 
+                      (4, cards[8:10]), (5, cards[10:12]), (6, cards[12:14])):
+                if not i[1] == "xx":
+                    self.seen_cards[(i[0], c - 1)]. \
+                        set_from_pixbuf(self.card_images[self.split_cards(i[1])])
 ##    action in tool tips for 3rd street cards
         for c in (0, 1, 2):
             for r in range(0, self.rows):
@@ -279,6 +260,13 @@ class Stud_cards:
             for r in range(0, self.rows):
                 self.eb[(round_to_col[round], r)].set_tooltip_text(self.tips[round])
 
+    def get_screen_name(self, seat_no):
+        """Gets and returns the screen name from stat_dict, given seat number."""
+        for k in self.parent.hud.stat_dict.keys():
+            if self.parent.hud.stat_dict[k]['seat'] == seat_no:
+                return self.parent.hud.stat_dict[k]['screen_name']
+        return "No Name"
+
     def split_cards(self, card):
         return (card[0], card[1].upper())
 
diff --git a/pyfpdb/Tables.py b/pyfpdb/Tables.py
index def4bd58..20dc4454 100755
--- a/pyfpdb/Tables.py
+++ b/pyfpdb/Tables.py
@@ -390,9 +390,9 @@ if __name__=="__main__":
     print discover_table_by_name(c, "Ringe")
 #    print discover_tournament_table(c, "118942908", "3")
 
-#    tables = discover(c)
-#    for t in tables.keys():
-#        print tables[t]
+    tables = discover(c)
+    for t in tables.keys():
+        print tables[t]
 
     print "press enter to continue"
     sys.stdin.readline()