@Override
	public final void loadMap(final File mapToLoad,
			final DndPluginCaller.LoadedMapEntry c) {
		final InputStream in = this.io.openIn(mapToLoad);
		in.registerProgressMonitor(this.io);
		class ParseState {
			private int state;

			final boolean comment() {
				return this.state < 0;
			}

			final void parseLine(final String line) {
				switch (this.state) {
				case 0x7000_0000:
					return;
				case 0:
					if (line.startsWith("Name: ")) {
						AbcCreator.this.TITLE.value(line.substring(6).trim());
					} else if (line.startsWith("Speedup: ")) {
						BruteParams.SPEED.value(line.substring(8).trim(),
								AbcCreator.this.io);
					} else if (line.startsWith("Pitch: ")) {
						BruteParams.PITCH.value(line.substring(6).trim(),
								AbcCreator.this.io);
					} else if (line.startsWith("Style: ")) {
						AbcCreator.this.STYLE.value(line.substring(7));
					} else if (line.startsWith("Volume: ")) {
						BruteParams.VOLUME.value(line.substring(7).trim(),
								AbcCreator.this.io);
					} else if (line.startsWith("Compress: ")) {
						BruteParams.DYNAMIC.value(line.substring(10).trim(),
								AbcCreator.this.io);
					} else if (line.startsWith("abctrack begin")) {
						++this.state;
					} else if (line.startsWith("fadeout length")) {
						BruteParams.FADEOUT.value(line.substring(14).trim(),
								AbcCreator.this.io);
					} else {
						return;
					}
					break;
				case 1:
					if (line.startsWith("duration ")) {
						// TODO support of duration
						break;
					} else if (line.startsWith("polyphony ")) {
						// TODO support of polyphony
						break;
					} else {
						if (line.startsWith("instrument ")) {
							this.state = 2;
							parseLine(line);
						}
						return;
					}
				case 2:
					if (!line.startsWith("instrument ")) {
						this.state = 0x7000_0000;
						return;
					}
					final String s0 = line.substring(11).trim();

					c.addPart(s0);

					this.state = 3;
					break;
				case 3:
					if (line.startsWith("miditrack")) {
						c.addEntry(line.substring(10));
					} else if (line.startsWith("abctrack end")) {
						this.state = 7;
					} else {
						return;
					}
					break;
				case 7:
					if (line.startsWith("abctrack begin")) {
						this.state = 1;
					} else {
						return;
					}
					break;
				default:
					break;
				}
				if (c.error()) {
					System.out.println(". " + line);
					return;
				}
				Debug.print(". %s", line);
			}

			final void toggleComment() {
				this.state = ~this.state;
			}
		}

		final ParseState state = new ParseState();
		Debug.print("loading map %s\n", mapToLoad);
		try {
			while (true) {
				if (c.error()) {
					break;
				}
				final String line = in.readLine();
				if (line == null) {
					break;
				}
				if (line.startsWith("%")) {
					continue;
				}
				if (line.trim().equals("*")) {
					state.toggleComment();
				}
				if (state.comment()) {
					continue;
				}
				state.parseLine(line);
			}
		} catch (final IOException e) {
			c.setError();
			System.err.println(e);
		} catch (final Exception e) {
			c.setError();
			e.printStackTrace();
		} finally {
			this.io.endProgress("Map loaded");
			this.io.close(in);
		}
		System.out.println("... completed");
	}