summaryrefslogtreecommitdiff
path: root/src/playlist/cue/CueParser.hxx
blob: 7e040169b84cedc4eeb6050d28922c640c84245a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*
 * Copyright (C) 2003-2014 The Music Player Daemon Project
 * http://www.musicpd.org
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifndef MPD_CUE_PARSER_HXX
#define MPD_CUE_PARSER_HXX

#include "check.h"
#include "tag/TagBuilder.hxx"
#include "Compiler.h"

#include <string>

class DetachedSong;
struct Tag;

class CueParser {
	enum {
		/**
		 * Parsing the CUE header.
		 */
		HEADER,

		/**
		 * Parsing a "FILE ... WAVE".
		 */
		WAVE,

		/**
		 * Ignore everything until the next "FILE".
		 */
		IGNORE_FILE,

		/**
		 * Parsing a "TRACK ... AUDIO".
		 */
		TRACK,

		/**
		 * Ignore everything until the next "TRACK".
		 */
		IGNORE_TRACK,
	} state;

	/**
	 * Tags read from the CUE header.
	 */
	TagBuilder header_tag;

	/**
	 * Tags read for the current song (attribute #current).  When
	 * #current gets moved to #previous, TagBuilder::Commit() will
	 * be called.
	 */
	TagBuilder song_tag;

	std::string filename;

	/**
	 * The song currently being edited.
	 */
	DetachedSong *current;

	/**
	 * The previous song.  It is remembered because its end_time
	 * will be set to the current song's start time.
	 */
	DetachedSong *previous;

	/**
	 * A song that is completely finished and can be returned to
	 * the caller via cue_parser_get().
	 */
	DetachedSong *finished;

	/**
	 * Set to true after previous.end_time has been updated to the
	 * start time of the current song.
	 */
	bool last_updated;

	/**
	 * Tracks whether cue_parser_finish() has been called.  If
	 * true, then all remaining (partial) results will be
	 * delivered by cue_parser_get().
	 */
	bool end;

public:
	CueParser();
	~CueParser();

	/**
	 * Feed a text line from the CUE file into the parser.  Call
	 * cue_parser_get() after this to see if a song has been finished.
	 */
	void Feed(const char *line);

	/**
	 * Tell the parser that the end of the file has been reached.  Call
	 * cue_parser_get() after this to see if a song has been finished.
	 * This procedure must be done twice!
	 */
	void Finish();

	/**
	 * Check if a song was finished by the last cue_parser_feed() or
	 * cue_parser_finish() call.
	 *
	 * @return a song object that must be freed by the caller, or NULL if
	 * no song was finished at this time
	 */
	DetachedSong *Get();

private:
	gcc_pure
	TagBuilder *GetCurrentTag();

	/**
	 * Commit the current song.  It will be moved to "previous",
	 * so the next song may soon edit its end time (using the next
	 * song's start time).
	 */
	void Commit();

	void Feed2(char *p);
};

#endif