diff --git a/source/net/sourceforge/filebot/ResourceManager.java b/source/net/sourceforge/filebot/ResourceManager.java
index f2bf5807..39f41c3d 100644
--- a/source/net/sourceforge/filebot/ResourceManager.java
+++ b/source/net/sourceforge/filebot/ResourceManager.java
@@ -19,7 +19,7 @@ public final class ResourceManager {
 	
 	private static final Cache cache = CacheManager.getInstance().getCache("resource");
 	
-	
+
 	public static Icon getIcon(String name) {
 		return getIcon(name, null);
 	}
@@ -41,12 +41,7 @@ public final class ResourceManager {
 	
 
 	public static Icon getFlagIcon(String languageCode) {
-		return getIcon(String.format("flags/%s", languageCode), "flags/default");
-	}
-	
-
-	public static Icon getArchiveIcon(String type) {
-		return getIcon(String.format("archives/%s", type), "archives/default");
+		return getIcon(String.format("flags/%s", languageCode));
 	}
 	
 
diff --git a/source/net/sourceforge/filebot/ui/AbstractSearchPanel.java b/source/net/sourceforge/filebot/ui/AbstractSearchPanel.java
index 32b80c1a..706c0e15 100644
--- a/source/net/sourceforge/filebot/ui/AbstractSearchPanel.java
+++ b/source/net/sourceforge/filebot/ui/AbstractSearchPanel.java
@@ -7,6 +7,7 @@ import static javax.swing.ScrollPaneConstants.*;
 import java.awt.Window;
 import java.awt.event.ActionEvent;
 import java.net.URI;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
 import java.util.logging.Level;
@@ -53,7 +54,7 @@ public abstract class AbstractSearchPanel<S, E> extends JComponent {
 	
 	protected final EventList<String> searchHistory = createSearchHistory();
 	
-	
+
 	public AbstractSearchPanel() {
 		historyPanel.setColumnHeader(2, "Duration");
 		
@@ -73,7 +74,7 @@ public abstract class AbstractSearchPanel<S, E> extends JComponent {
 		
 		searchTextField.getEditor().setAction(searchAction);
 		
-		searchTextField.getSelectButton().setModel(createSearchEngines());
+		searchTextField.getSelectButton().setModel(Arrays.asList(createSearchEngines()));
 		searchTextField.getSelectButton().setLabelProvider(createSearchEngineLabelProvider());
 		
 		try {
@@ -98,7 +99,7 @@ public abstract class AbstractSearchPanel<S, E> extends JComponent {
 	}
 	
 
-	protected abstract List<S> createSearchEngines();
+	protected abstract S[] createSearchEngines();
 	
 
 	protected abstract LabelProvider<S> createSearchEngineLabelProvider();
@@ -143,6 +144,7 @@ public abstract class AbstractSearchPanel<S, E> extends JComponent {
 		return history;
 	}
 	
+
 	private final AbstractAction searchAction = new AbstractAction("Find", ResourceManager.getIcon("action.find")) {
 		
 		public void actionPerformed(ActionEvent e) {
@@ -155,12 +157,12 @@ public abstract class AbstractSearchPanel<S, E> extends JComponent {
 		}
 	};
 	
-	
+
 	private class SearchTask extends SwingWorker<Collection<? extends SearchResult>, Void> {
 		
 		private final RequestProcessor<?, E> requestProcessor;
 		
-		
+
 		public SearchTask(RequestProcessor<?, E> requestProcessor) {
 			this.requestProcessor = requestProcessor;
 		}
@@ -235,7 +237,7 @@ public abstract class AbstractSearchPanel<S, E> extends JComponent {
 		
 		private final RequestProcessor<?, E> requestProcessor;
 		
-		
+
 		public FetchTask(RequestProcessor<?, E> requestProcessor) {
 			this.requestProcessor = requestProcessor;
 		}
@@ -292,7 +294,7 @@ public abstract class AbstractSearchPanel<S, E> extends JComponent {
 		
 		private final String searchText;
 		
-		
+
 		public Request(String searchText) {
 			this.searchText = searchText;
 		}
@@ -315,7 +317,7 @@ public abstract class AbstractSearchPanel<S, E> extends JComponent {
 		
 		private long duration = 0;
 		
-		
+
 		public RequestProcessor(R request, JComponent component) {
 			this.request = request;
 			this.tab = new FileBotTab<JComponent>(component);
diff --git a/source/net/sourceforge/filebot/ui/panel/episodelist/EpisodeListPanel.java b/source/net/sourceforge/filebot/ui/panel/episodelist/EpisodeListPanel.java
index 06e9dd9b..27708d9f 100644
--- a/source/net/sourceforge/filebot/ui/panel/episodelist/EpisodeListPanel.java
+++ b/source/net/sourceforge/filebot/ui/panel/episodelist/EpisodeListPanel.java
@@ -10,9 +10,7 @@ import java.beans.PropertyChangeListener;
 import java.io.File;
 import java.io.IOException;
 import java.net.URI;
-import java.util.ArrayList;
 import java.util.Collection;
-import java.util.List;
 
 import javax.swing.AbstractAction;
 import javax.swing.Icon;
@@ -70,16 +68,14 @@ public class EpisodeListPanel extends AbstractSearchPanel<EpisodeListProvider, E
 	
 
 	@Override
-	protected List<EpisodeListProvider> createSearchEngines() {
-		List<EpisodeListProvider> engines = new ArrayList<EpisodeListProvider>(4);
-		
-		engines.add(new TVRageClient());
-		engines.add(new AnidbClient());
-		engines.add(new TVDotComClient());
-		engines.add(new IMDbClient());
-		engines.add(new TheTVDBClient(Settings.userRoot().get("thetvdb.apikey")));
-		
-		return engines;
+	protected EpisodeListProvider[] createSearchEngines() {
+		return new EpisodeListProvider[] {
+				new TVRageClient(),
+				new AnidbClient(),
+				new TVDotComClient(),
+				new IMDbClient(),
+				new TheTVDBClient(Settings.userRoot().get("thetvdb.apikey"))
+		};
 	}
 	
 
diff --git a/source/net/sourceforge/filebot/ui/panel/rename/EpisodeExpressionFormatter.java b/source/net/sourceforge/filebot/ui/panel/rename/EpisodeExpressionFormatter.java
index e185fb8a..c94cf79e 100644
--- a/source/net/sourceforge/filebot/ui/panel/rename/EpisodeExpressionFormatter.java
+++ b/source/net/sourceforge/filebot/ui/panel/rename/EpisodeExpressionFormatter.java
@@ -38,7 +38,7 @@ class EpisodeExpressionFormatter extends ExpressionFormat implements MatchFormat
 		Episode episode = (Episode) match.getValue();
 		File mediaFile = (File) match.getCandidate();
 		
-		return format(new EpisodeFormatBindingBean(episode, mediaFile));
+		return format(new EpisodeFormatBindingBean(episode, mediaFile)).trim();
 	}
 	
 }
diff --git a/source/net/sourceforge/filebot/ui/panel/subtitle/SubtitleListCellRenderer.java b/source/net/sourceforge/filebot/ui/panel/subtitle/SubtitleListCellRenderer.java
index 848d6971..27fd0104 100644
--- a/source/net/sourceforge/filebot/ui/panel/subtitle/SubtitleListCellRenderer.java
+++ b/source/net/sourceforge/filebot/ui/panel/subtitle/SubtitleListCellRenderer.java
@@ -4,8 +4,6 @@ package net.sourceforge.filebot.ui.panel.subtitle;
 
 import java.awt.Color;
 import java.awt.Dimension;
-import java.util.HashMap;
-import java.util.Map;
 
 import javax.swing.JLabel;
 import javax.swing.JList;
@@ -24,8 +22,6 @@ public class SubtitleListCellRenderer extends AbstractFancyListCellRenderer {
 	
 	private final JProgressBar progressBar = new JProgressBar(0, 100);
 	
-	private final Map<String, String> languageCodeMap = mapLanguageCodeByName(Language.availableLanguages());
-	
 
 	public SubtitleListCellRenderer() {
 		setHighlightingEnabled(false);
@@ -54,8 +50,8 @@ public class SubtitleListCellRenderer extends AbstractFancyListCellRenderer {
 		titleLabel.setText(subtitle.getName());
 		
 		if (languageLabel.isVisible()) {
-			languageLabel.setText(subtitle.getLanguageName());
-			languageLabel.setIcon(ResourceManager.getFlagIcon(languageCodeMap.get(subtitle.getLanguageName())));
+			languageLabel.setText(subtitle.getLanguage().getName());
+			languageLabel.setIcon(ResourceManager.getFlagIcon(subtitle.getLanguage().getCode()));
 		}
 		
 		//TODO download + progress
@@ -70,17 +66,6 @@ public class SubtitleListCellRenderer extends AbstractFancyListCellRenderer {
 	}
 	
 
-	private Map<String, String> mapLanguageCodeByName(Language[] languages) {
-		Map<String, String> map = new HashMap<String, String>();
-		
-		for (Language language : languages) {
-			map.put(language.getName(), language.getCode());
-		}
-		
-		return map;
-	}
-	
-
 	public JLabel getLanguageLabel() {
 		return languageLabel;
 	}
diff --git a/source/net/sourceforge/filebot/ui/panel/subtitle/SubtitleListComponent.java b/source/net/sourceforge/filebot/ui/panel/subtitle/SubtitleListComponent.java
index ff552876..2a338539 100644
--- a/source/net/sourceforge/filebot/ui/panel/subtitle/SubtitleListComponent.java
+++ b/source/net/sourceforge/filebot/ui/panel/subtitle/SubtitleListComponent.java
@@ -3,6 +3,7 @@ package net.sourceforge.filebot.ui.panel.subtitle;
 
 
 import java.awt.event.ActionEvent;
+import java.util.List;
 
 import javax.swing.AbstractAction;
 import javax.swing.Action;
@@ -18,7 +19,6 @@ import net.sourceforge.filebot.ResourceManager;
 import ca.odell.glazedlists.BasicEventList;
 import ca.odell.glazedlists.EventList;
 import ca.odell.glazedlists.FilterList;
-import ca.odell.glazedlists.GlazedLists;
 import ca.odell.glazedlists.ListSelection;
 import ca.odell.glazedlists.TextFilterator;
 import ca.odell.glazedlists.swing.EventListModel;
@@ -34,10 +34,17 @@ public class SubtitleListComponent extends JComponent {
 	
 	private JTextField filterEditor = new JTextField();
 	
-	
+
 	public SubtitleListComponent() {
-		TextFilterator<SubtitlePackage> filterator = GlazedLists.toStringTextFilterator();
-		TextComponentMatcherEditor<SubtitlePackage> matcherEditor = new TextComponentMatcherEditor<SubtitlePackage>(filterEditor, filterator);
+		// allow filtering by language name and subtitle name
+		TextComponentMatcherEditor<SubtitlePackage> matcherEditor = new TextComponentMatcherEditor<SubtitlePackage>(filterEditor, new TextFilterator<SubtitlePackage>() {
+			
+			@Override
+			public void getFilterStrings(List<String> list, SubtitlePackage element) {
+				list.add(element.getLanguage().getName());
+				list.add(element.getName());
+			}
+		});
 		
 		JList list = new JList(new EventListModel<SubtitlePackage>(new FilterList<SubtitlePackage>(model, matcherEditor)));
 		list.setCellRenderer(renderer);
@@ -68,6 +75,7 @@ public class SubtitleListComponent extends JComponent {
 		renderer.getLanguageLabel().setVisible(visible);
 	}
 	
+
 	private final Action clearFilterAction = new AbstractAction(null, ResourceManager.getIcon("edit.clear")) {
 		
 		@Override
diff --git a/source/net/sourceforge/filebot/ui/panel/subtitle/SubtitlePackage.java b/source/net/sourceforge/filebot/ui/panel/subtitle/SubtitlePackage.java
index bff0411c..d6167f85 100644
--- a/source/net/sourceforge/filebot/ui/panel/subtitle/SubtitlePackage.java
+++ b/source/net/sourceforge/filebot/ui/panel/subtitle/SubtitlePackage.java
@@ -2,9 +2,11 @@
 package net.sourceforge.filebot.ui.panel.subtitle;
 
 
-import javax.swing.Icon;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.ResourceBundle;
 
-import net.sourceforge.filebot.ResourceManager;
 import net.sourceforge.filebot.web.SubtitleDescriptor;
 import net.sourceforge.tuned.DownloadTask;
 
@@ -13,25 +15,16 @@ public class SubtitlePackage {
 	
 	private final SubtitleDescriptor subtitleDescriptor;
 	
-	private final ArchiveType archiveType;
-	
-	private final Icon archiveIcon;
+	private final Language language;
 	
 	private final DownloadTask downloadTask;
 	
-	
+
 	public SubtitlePackage(SubtitleDescriptor subtitleDescriptor) {
 		this.subtitleDescriptor = subtitleDescriptor;
 		
-		downloadTask = subtitleDescriptor.createDownloadTask();
-		
-		archiveType = ArchiveType.forName(subtitleDescriptor.getArchiveType());
-		archiveIcon = ResourceManager.getArchiveIcon(archiveType.getExtension());
-	}
-	
-
-	public SubtitleDescriptor getSubtitleDescriptor() {
-		return subtitleDescriptor;
+		this.language = new Language(languageCodeByName.get(subtitleDescriptor.getLanguageName()), subtitleDescriptor.getLanguageName());
+		this.downloadTask = subtitleDescriptor.createDownloadTask();
 	}
 	
 
@@ -40,24 +33,13 @@ public class SubtitlePackage {
 	}
 	
 
-	public String getLanguageName() {
-		return subtitleDescriptor.getLanguageName();
+	public Language getLanguage() {
+		return language;
 	}
 	
 
 	public ArchiveType getArchiveType() {
-		return archiveType;
-	}
-	
-
-	public Icon getArchiveIcon() {
-		return archiveIcon;
-	}
-	
-
-	@Override
-	public String toString() {
-		return getName();
+		return ArchiveType.forName(subtitleDescriptor.getArchiveType());
 	}
 	
 
@@ -65,4 +47,29 @@ public class SubtitlePackage {
 		return downloadTask;
 	}
 	
+
+	@Override
+	public String toString() {
+		return subtitleDescriptor.getName();
+	}
+	
+
+	/**
+	 * Map english language name to language code.
+	 */
+	private static final Map<String, String> languageCodeByName = mapLanguageCodeByName();
+	
+
+	private static Map<String, String> mapLanguageCodeByName() {
+		ResourceBundle bundle = ResourceBundle.getBundle(Language.class.getName(), Locale.ENGLISH);
+		
+		Map<String, String> map = new HashMap<String, String>();
+		
+		for (String code : bundle.keySet()) {
+			map.put(bundle.getString(code), code);
+		}
+		
+		return map;
+	}
+	
 }
diff --git a/source/net/sourceforge/filebot/ui/panel/subtitle/SubtitlePanel.java b/source/net/sourceforge/filebot/ui/panel/subtitle/SubtitlePanel.java
index fc6239ac..7d11d0d0 100644
--- a/source/net/sourceforge/filebot/ui/panel/subtitle/SubtitlePanel.java
+++ b/source/net/sourceforge/filebot/ui/panel/subtitle/SubtitlePanel.java
@@ -21,6 +21,7 @@ import net.sourceforge.filebot.ui.AbstractSearchPanel;
 import net.sourceforge.filebot.ui.SelectDialog;
 import net.sourceforge.filebot.web.OpenSubtitlesSubtitleClient;
 import net.sourceforge.filebot.web.SearchResult;
+import net.sourceforge.filebot.web.SublightSubtitleClient;
 import net.sourceforge.filebot.web.SubsceneSubtitleClient;
 import net.sourceforge.filebot.web.SubtitleDescriptor;
 import net.sourceforge.filebot.web.SubtitleProvider;
@@ -35,7 +36,7 @@ public class SubtitlePanel extends AbstractSearchPanel<SubtitleProvider, Subtitl
 	
 	private final LanguageComboBoxModel languageModel = new LanguageComboBoxModel();
 	
-	
+
 	public SubtitlePanel() {
 		historyPanel.setColumnHeader(0, "Show / Movie");
 		historyPanel.setColumnHeader(1, "Number of Subtitles");
@@ -76,14 +77,15 @@ public class SubtitlePanel extends AbstractSearchPanel<SubtitleProvider, Subtitl
 	
 
 	@Override
-	protected List<SubtitleProvider> createSearchEngines() {
-		List<SubtitleProvider> engines = new ArrayList<SubtitleProvider>(2);
+	protected SubtitleProvider[] createSearchEngines() {
+		String clientInfo = String.format("%s v%s", getApplicationName(), getApplicationVersion());
 		
-		engines.add(new OpenSubtitlesSubtitleClient(String.format("%s v%s", getApplicationName(), getApplicationVersion())));
-		engines.add(new SubsceneSubtitleClient());
-		engines.add(new SubtitleSourceClient());
-		
-		return engines;
+		return new SubtitleProvider[] {
+				new OpenSubtitlesSubtitleClient(clientInfo),
+				new SubsceneSubtitleClient(),
+				new SublightSubtitleClient(clientInfo),
+				new SubtitleSourceClient()
+		};
 	}
 	
 
@@ -111,13 +113,13 @@ public class SubtitlePanel extends AbstractSearchPanel<SubtitleProvider, Subtitl
 		return new SubtitleRequestProcessor(new SubtitleRequest(provider, text, languageName));
 	}
 	
-	
+
 	protected static class SubtitleRequest extends Request {
 		
 		private final SubtitleProvider provider;
 		private final String languageName;
 		
-		
+
 		public SubtitleRequest(SubtitleProvider provider, String searchText, String languageName) {
 			super(searchText);
 			
@@ -202,6 +204,7 @@ public class SubtitlePanel extends AbstractSearchPanel<SubtitleProvider, Subtitl
 		
 	}
 	
+
 	private final PreferencesEntry<Language> persistentSelectedLanguage = getSettings().entry("language.selected", new AbstractAdapter<Language>() {
 		
 		@Override
diff --git a/source/net/sourceforge/filebot/web/Episode.java b/source/net/sourceforge/filebot/web/Episode.java
index 12e3037c..749ce6c7 100644
--- a/source/net/sourceforge/filebot/web/Episode.java
+++ b/source/net/sourceforge/filebot/web/Episode.java
@@ -12,9 +12,9 @@ public class Episode implements Serializable {
 	private final String episode;
 	private final String title;
 	
-	
-	public Episode(String seriesName, Integer season, Integer episode, String title) {
-		this(seriesName, season.toString(), episode.toString(), title);
+
+	public Episode(String seriesName, int season, int episode, String title) {
+		this(seriesName, String.valueOf(season), String.valueOf(episode), title);
 	}
 	
 
diff --git a/source/net/sourceforge/filebot/web/EpisodeFormat.java b/source/net/sourceforge/filebot/web/EpisodeFormat.java
index abc651b4..3222111c 100644
--- a/source/net/sourceforge/filebot/web/EpisodeFormat.java
+++ b/source/net/sourceforge/filebot/web/EpisodeFormat.java
@@ -14,7 +14,7 @@ public class EpisodeFormat extends Format {
 	
 	private static final EpisodeFormat instance = new EpisodeFormat();
 	
-	
+
 	public static EpisodeFormat getInstance() {
 		return instance;
 	}
@@ -24,18 +24,25 @@ public class EpisodeFormat extends Format {
 	public StringBuffer format(Object obj, StringBuffer sb, FieldPosition pos) {
 		Episode episode = (Episode) obj;
 		
-		sb.append(episode.getSeriesName()).append(" - ");
+		// try to format episode number, or use episode "number" string as is
+		String episodeNumber = (episode.getEpisodeNumber() != null ? String.format("%02d", episode.getEpisodeNumber()) : episode.getEpisode());
+		
+		// series name should not be empty or null
+		sb.append(episode.getSeriesName());
 		
 		if (episode.getSeason() != null) {
-			sb.append(episode.getSeason()).append('x');
+			// season and episode
+			sb.append(" - ").append(episode.getSeason()).append('x').append(episodeNumber);
+		} else if (episodeNumber != null) {
+			// episode, but no season
+			sb.append(" - ").append(episodeNumber);
 		}
 		
-		Integer episodeNumber = episode.getEpisodeNumber();
+		if (episode.getTitle() != null) {
+			sb.append(" - ").append(episode.getTitle());
+		}
 		
-		// try to format episode number, or use episode "number" string as is
-		sb.append(episodeNumber != null ? String.format("%02d", episodeNumber) : episode.getEpisode());
-		
-		return sb.append(" - ").append(episode.getTitle());
+		return sb;
 	}
 	
 
diff --git a/source/net/sourceforge/filebot/web/IMDbClient.java b/source/net/sourceforge/filebot/web/IMDbClient.java
index acb09a94..479e32a3 100644
--- a/source/net/sourceforge/filebot/web/IMDbClient.java
+++ b/source/net/sourceforge/filebot/web/IMDbClient.java
@@ -31,7 +31,7 @@ public class IMDbClient implements EpisodeListProvider {
 	
 	private static final String host = "www.imdb.com";
 	
-	
+
 	@Override
 	public String getName() {
 		return "IMDb";
@@ -66,17 +66,16 @@ public class IMDbClient implements EpisodeListProvider {
 			String year = node.getNextSibling().getTextContent().trim();
 			String href = getAttribute("href", node);
 			
-			String nameAndYear = String.format("%s %s", name, year).trim();
-			
-			results.add(new MovieDescriptor(nameAndYear, getImdbId(href)));
+			results.add(new MovieDescriptor(name, Integer.parseInt(year), getImdbId(href)));
 		}
 		
 		// we might have been redirected to the movie page
 		if (results.isEmpty()) {
 			String name = removeQuotationMarks(selectString("//H1/text()", dom));
+			String year = selectString("//H1//A", dom);
 			String url = selectString("//LINK[@rel='canonical']/@href", dom);
 			
-			results.add(new MovieDescriptor(name, getImdbId(url)));
+			results.add(new MovieDescriptor(name, Integer.parseInt(year), getImdbId(url)));
 		}
 		
 		return results;
diff --git a/source/net/sourceforge/filebot/web/MovieDescriptor.java b/source/net/sourceforge/filebot/web/MovieDescriptor.java
index 8b01c7f7..7b017b4c 100644
--- a/source/net/sourceforge/filebot/web/MovieDescriptor.java
+++ b/source/net/sourceforge/filebot/web/MovieDescriptor.java
@@ -4,15 +4,23 @@ package net.sourceforge.filebot.web;
 
 public class MovieDescriptor extends SearchResult {
 	
+	private final int year;
 	private final int imdbId;
 	
-	
-	public MovieDescriptor(String name, int imdbId) {
+
+	public MovieDescriptor(String name, int year, int imdbId) {
 		super(name);
+		
+		this.year = year;
 		this.imdbId = imdbId;
 	}
 	
 
+	public int getYear() {
+		return year;
+	}
+	
+
 	public int getImdbId() {
 		return imdbId;
 	}
@@ -22,10 +30,16 @@ public class MovieDescriptor extends SearchResult {
 	public boolean equals(Object object) {
 		if (object instanceof MovieDescriptor) {
 			MovieDescriptor other = (MovieDescriptor) object;
-			return this.getImdbId() == other.getImdbId() && this.getName() == other.getName();
+			return getImdbId() == other.getImdbId() && getName().equals(other.getName()) && getYear() == other.getYear();
 		}
 		
-		return super.equals(object);
+		return false;
+	}
+	
+
+	@Override
+	public String toString() {
+		return String.format("%s (%d)", getName(), getYear());
 	}
 	
 }
diff --git a/source/net/sourceforge/filebot/web/OpenSubtitlesClient.java b/source/net/sourceforge/filebot/web/OpenSubtitlesClient.java
index 52e14789..e06123da 100644
--- a/source/net/sourceforge/filebot/web/OpenSubtitlesClient.java
+++ b/source/net/sourceforge/filebot/web/OpenSubtitlesClient.java
@@ -24,13 +24,13 @@ public class OpenSubtitlesClient {
 	
 	private static final String url = "http://www.opensubtitles.org/xml-rpc";
 	
-	private final String useragent;
+	private final String clientInfo;
 	
 	private String token = null;
 	
-	
-	public OpenSubtitlesClient(String useragent) {
-		this.useragent = useragent;
+
+	public OpenSubtitlesClient(String clientInfo) {
+		this.clientInfo = clientInfo;
 	}
 	
 
@@ -70,7 +70,7 @@ public class OpenSubtitlesClient {
 	@SuppressWarnings("unchecked")
 	public synchronized void login(String username, String password, String language) throws XmlRpcFault {
 		
-		Map<String, String> response = (Map<String, String>) invoke("LogIn", username, password, language, useragent);
+		Map<String, String> response = (Map<String, String>) invoke("LogIn", username, password, language, clientInfo);
 		checkStatus(response.get("status"));
 		
 		token = response.get("token");
@@ -191,7 +191,7 @@ public class OpenSubtitlesClient {
 				title = title.substring(0, endIndex);
 			}
 			
-			movies.add(new MovieDescriptor(title, new Integer(movie.get("id"))));
+			movies.add(new MovieDescriptor(title, Integer.parseInt(movie.get("year")), Integer.parseInt(movie.get("id"))));
 		}
 		
 		return movies;
diff --git a/source/net/sourceforge/filebot/web/OpenSubtitlesHasher.java b/source/net/sourceforge/filebot/web/OpenSubtitlesHasher.java
index 7207b68b..3655c002 100644
--- a/source/net/sourceforge/filebot/web/OpenSubtitlesHasher.java
+++ b/source/net/sourceforge/filebot/web/OpenSubtitlesHasher.java
@@ -19,14 +19,14 @@ import java.nio.channels.FileChannel.MapMode;
  * checksum of the first and last 64k (even if they overlap because the file is smaller than
  * 128k).
  */
-public class OpenSubtitlesHasher {
+public final class OpenSubtitlesHasher {
 	
 	/**
 	 * Size of the chunks that will be hashed in bytes (64 KB)
 	 */
 	private static final int HASH_CHUNK_SIZE = 64 * 1024;
 	
-	
+
 	public static String computeHash(File file) throws IOException {
 		long size = file.length();
 		long chunkSizeForFile = Math.min(HASH_CHUNK_SIZE, size);
diff --git a/source/net/sourceforge/filebot/web/OpenSubtitlesSubtitleClient.java b/source/net/sourceforge/filebot/web/OpenSubtitlesSubtitleClient.java
index 1a36943f..d6f044f9 100644
--- a/source/net/sourceforge/filebot/web/OpenSubtitlesSubtitleClient.java
+++ b/source/net/sourceforge/filebot/web/OpenSubtitlesSubtitleClient.java
@@ -21,7 +21,7 @@ public class OpenSubtitlesSubtitleClient implements SubtitleProvider {
 	
 	private final OpenSubtitlesClient client;
 	
-	
+
 	public OpenSubtitlesSubtitleClient(String useragent) {
 		this.client = new OpenSubtitlesClient(useragent);
 	}
@@ -39,21 +39,27 @@ public class OpenSubtitlesSubtitleClient implements SubtitleProvider {
 	}
 	
 
-	@SuppressWarnings("unchecked")
 	@Override
 	public List<SearchResult> search(String query) throws Exception {
+		// require login
 		login();
 		
-		return (List) client.searchMoviesOnIMDB(query);
+		@SuppressWarnings("unchecked")
+		List<SearchResult> results = (List) client.searchMoviesOnIMDB(query);
+		
+		return results;
 	}
 	
 
-	@SuppressWarnings("unchecked")
 	@Override
 	public List<SubtitleDescriptor> getSubtitleList(SearchResult searchResult, String languageName) throws Exception {
+		// require login
 		login();
 		
-		return (List) client.searchSubtitles(((MovieDescriptor) searchResult).getImdbId(), languageName);
+		@SuppressWarnings("unchecked")
+		List<SubtitleDescriptor> subtitles = (List) client.searchSubtitles(((MovieDescriptor) searchResult).getImdbId(), languageName);
+		
+		return subtitles;
 	}
 	
 
@@ -64,33 +70,33 @@ public class OpenSubtitlesSubtitleClient implements SubtitleProvider {
 	}
 	
 
-	private synchronized void login() throws Exception {
+	protected synchronized void login() throws Exception {
 		if (!client.isLoggedOn()) {
 			client.loginAnonymous();
 		}
 		
-		logoutTimer.set(12, TimeUnit.MINUTES, true);
+		logoutTimer.set(10, TimeUnit.MINUTES, true);
 	}
 	
 
-	private synchronized void logout() {
-		logoutTimer.cancel();
-		
+	protected synchronized void logout() {
 		if (client.isLoggedOn()) {
 			try {
 				client.logout();
 			} catch (Exception e) {
-				Logger.getLogger(getClass().getName()).log(Level.SEVERE, "Exception while deactivating session", e);
+				Logger.getLogger(getClass().getName()).log(Level.SEVERE, "Logout failed", e);
 			}
 		}
+		
+		logoutTimer.cancel();
 	}
 	
-	private final Timer logoutTimer = new Timer() {
+
+	protected final Timer logoutTimer = new Timer() {
 		
 		@Override
 		public void run() {
 			logout();
 		}
-		
 	};
 }
diff --git a/source/net/sourceforge/filebot/web/SearchResult.java b/source/net/sourceforge/filebot/web/SearchResult.java
index 811d4439..b10a5063 100644
--- a/source/net/sourceforge/filebot/web/SearchResult.java
+++ b/source/net/sourceforge/filebot/web/SearchResult.java
@@ -9,7 +9,7 @@ public abstract class SearchResult implements Serializable {
 	
 	private final String name;
 	
-	
+
 	public SearchResult(String name) {
 		this.name = name;
 	}
diff --git a/source/net/sourceforge/filebot/web/SubtitleSourceClient.java b/source/net/sourceforge/filebot/web/SubtitleSourceClient.java
index c5481d37..f3134f71 100644
--- a/source/net/sourceforge/filebot/web/SubtitleSourceClient.java
+++ b/source/net/sourceforge/filebot/web/SubtitleSourceClient.java
@@ -27,7 +27,7 @@ public class SubtitleSourceClient implements SubtitleProvider {
 	
 	private static final int pageSize = 20;
 	
-	
+
 	@Override
 	public String getName() {
 		return "SubtitleSource";
@@ -59,8 +59,9 @@ public class SubtitleSourceClient implements SubtitleProvider {
 			
 			if (!movieMap.containsKey(imdb)) {
 				String title = getTextContent("title", node);
+				String year = getTextContent("year", node);
 				
-				movieMap.put(imdb, new MovieDescriptor(title, imdb));
+				movieMap.put(imdb, new MovieDescriptor(title, Integer.parseInt(year), imdb));
 			}
 		}
 		
diff --git a/source/net/sourceforge/tuned/Timer.java b/source/net/sourceforge/tuned/Timer.java
index 69aff75c..ca42c06f 100644
--- a/source/net/sourceforge/tuned/Timer.java
+++ b/source/net/sourceforge/tuned/Timer.java
@@ -14,7 +14,7 @@ public abstract class Timer implements Runnable {
 	private ScheduledFuture<?> scheduledFuture;
 	private Thread shutdownHook;
 	
-	
+
 	public Timer() {
 		executor = new ScheduledThreadPoolExecutor(1);
 		executor.setKeepAliveTime(200, TimeUnit.MILLISECONDS);
diff --git a/source/net/sourceforge/tuned/ui/SelectButton.java b/source/net/sourceforge/tuned/ui/SelectButton.java
index 9804c8dc..3b27821b 100644
--- a/source/net/sourceforge/tuned/ui/SelectButton.java
+++ b/source/net/sourceforge/tuned/ui/SelectButton.java
@@ -15,6 +15,8 @@ import java.awt.event.MouseEvent;
 import java.awt.geom.GeneralPath;
 import java.awt.geom.Path2D;
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 
 import javax.swing.BorderFactory;
@@ -39,14 +41,14 @@ public class SelectButton<T> extends JButton {
 	
 	private final SelectIcon selectIcon = new SelectIcon();
 	
-	private List<T> model = new ArrayList<T>(0);
+	private List<T> model = Collections.emptyList();
 	private SingleSelectionModel selectionModel = new DefaultSingleSelectionModel();
 	
 	private LabelProvider<T> labelProvider = new NullLabelProvider<T>();
 	
 	private boolean hover = false;
 	
-	
+
 	public SelectButton() {
 		setContentAreaFilled(false);
 		setFocusable(false);
@@ -63,9 +65,8 @@ public class SelectButton<T> extends JButton {
 	}
 	
 
-	public void setModel(List<T> model) {
-		this.model.clear();
-		this.model.addAll(model);
+	public void setModel(Collection<T> model) {
+		this.model = new ArrayList<T>(model);
 		
 		setSelectedIndex(0);
 	}
@@ -180,7 +181,7 @@ public class SelectButton<T> extends JButton {
 		super.processMouseEvent(e);
 	}
 	
-	
+
 	private class OpenPopupOnClick implements ActionListener {
 		
 		@Override
@@ -205,7 +206,7 @@ public class SelectButton<T> extends JButton {
 		
 		private final T value;
 		
-		
+
 		public SelectPopupMenuItem(String text, Icon icon, T value) {
 			super(text, icon);
 			
@@ -236,7 +237,7 @@ public class SelectButton<T> extends JButton {
 		
 		private Icon icon;
 		
-		
+
 		public SelectIcon() {
 			arrow = new GeneralPath(Path2D.WIND_EVEN_ODD, 3);
 			int x = 25;
diff --git a/test/net/sourceforge/filebot/web/IMDbClientTest.java b/test/net/sourceforge/filebot/web/IMDbClientTest.java
index dce1931b..bd3b03d3 100644
--- a/test/net/sourceforge/filebot/web/IMDbClientTest.java
+++ b/test/net/sourceforge/filebot/web/IMDbClientTest.java
@@ -13,14 +13,15 @@ public class IMDbClientTest {
 	
 	private final IMDbClient imdb = new IMDbClient();
 	
-	
+
 	@Test
 	public void search() throws Exception {
 		List<SearchResult> results = imdb.search("battlestar");
 		
 		MovieDescriptor movie = (MovieDescriptor) results.get(0);
 		
-		assertEquals("Battlestar Galactica (2004)", movie.getName());
+		assertEquals("Battlestar Galactica", movie.getName());
+		assertEquals(2004, movie.getYear());
 		assertEquals(407362, movie.getImdbId(), 0);
 		
 		assertEquals(6, results.size(), 0);
@@ -43,7 +44,7 @@ public class IMDbClientTest {
 
 	@Test
 	public void getEpisodeList() throws Exception {
-		List<Episode> list = imdb.getEpisodeList(new MovieDescriptor("Buffy", 118276));
+		List<Episode> list = imdb.getEpisodeList(new MovieDescriptor("Buffy", 1997, 118276));
 		
 		assertEquals(145, list.size());
 		
@@ -65,7 +66,7 @@ public class IMDbClientTest {
 
 	@Test
 	public void getEpisodeListWithUnknownSeason() throws Exception {
-		List<Episode> list = imdb.getEpisodeList(new MovieDescriptor("Mushishi", 807832));
+		List<Episode> list = imdb.getEpisodeList(new MovieDescriptor("Mushishi", 2005, 807832));
 		
 		assertEquals(26, list.size());
 		
@@ -80,7 +81,7 @@ public class IMDbClientTest {
 
 	@Test
 	public void getEpisodeListLink() throws Exception {
-		assertEquals("http://www.imdb.com/title/tt0407362/episodes", imdb.getEpisodeListLink(new MovieDescriptor("Battlestar Galactica", 407362)).toString());
+		assertEquals("http://www.imdb.com/title/tt0407362/episodes", imdb.getEpisodeListLink(new MovieDescriptor("Battlestar Galactica", 2004, 407362)).toString());
 	}
 	
 
diff --git a/test/net/sourceforge/filebot/web/SubtitleSourceClientTest.java b/test/net/sourceforge/filebot/web/SubtitleSourceClientTest.java
index 65924cd9..73796cb5 100644
--- a/test/net/sourceforge/filebot/web/SubtitleSourceClientTest.java
+++ b/test/net/sourceforge/filebot/web/SubtitleSourceClientTest.java
@@ -13,7 +13,7 @@ public class SubtitleSourceClientTest {
 	
 	private static final SubtitleSourceClient client = new SubtitleSourceClient();
 	
-	
+
 	@Test
 	public void search() throws Exception {
 		List<SearchResult> list = client.search("babylon 5");
@@ -31,7 +31,7 @@ public class SubtitleSourceClientTest {
 
 	@Test
 	public void getSubtitleListAll() throws Exception {
-		List<SubtitleDescriptor> list = client.getSubtitleList(new MovieDescriptor("Buffy", 118276), "English");
+		List<SubtitleDescriptor> list = client.getSubtitleList(new MovieDescriptor("Buffy", 1997, 118276), "English");
 		
 		SubtitleDescriptor sample = list.get(0);
 		
@@ -46,7 +46,7 @@ public class SubtitleSourceClientTest {
 
 	@Test
 	public void getSubtitleListSinglePage() throws Exception {
-		List<SubtitleDescriptor> list = client.getSubtitleList(new MovieDescriptor("Firefly", 303461), 0);
+		List<SubtitleDescriptor> list = client.getSubtitleList(new MovieDescriptor("Firefly", 2002, 303461), 0);
 		
 		SubtitleDescriptor sample = list.get(0);
 		
@@ -60,6 +60,6 @@ public class SubtitleSourceClientTest {
 
 	@Test
 	public void getSubtitleListLink() {
-		assertEquals("http://www.subtitlesource.org/title/tt0303461", client.getSubtitleListLink(new MovieDescriptor("Firefly", 303461), null).toString());
+		assertEquals("http://www.subtitlesource.org/title/tt0303461", client.getSubtitleListLink(new MovieDescriptor("Firefly", 2002, 303461), null).toString());
 	}
 }
diff --git a/test/net/sourceforge/tuned/PreferencesMapTest.java b/test/net/sourceforge/tuned/PreferencesMapTest.java
index 8271a24a..68af6368 100644
--- a/test/net/sourceforge/tuned/PreferencesMapTest.java
+++ b/test/net/sourceforge/tuned/PreferencesMapTest.java
@@ -27,7 +27,7 @@ public class PreferencesMapTest {
 	private static Preferences temp;
 	private static Preferences sequence;
 	
-	
+
 	@BeforeClass
 	public static void setUpBeforeClass() throws Exception {
 		root = Preferences.userRoot().node("junit-test");
@@ -168,7 +168,7 @@ public class PreferencesMapTest {
 	public void serializableAdapter() {
 		Map<String, MovieDescriptor> map = PreferencesMap.map(temp, new SerializableAdapter<MovieDescriptor>());
 		
-		MovieDescriptor movie = new MovieDescriptor("The Hitchhiker's Guide to the Galaxy", 42);
+		MovieDescriptor movie = new MovieDescriptor("The Hitchhiker's Guide to the Galaxy", 1981, 42);
 		
 		map.put("movie", movie);