local t = Def.ActorFrame{
	Name="BPMSection";
	CurrentSongChangedMessageCommand=cmd(playcommand,"Set");
	CurrentCourseChangedMessageCommand=cmd(playcommand,"Set");
	SetCommand=function(self)
		-- check for a song or course. if there isn't one, hide it.
		local song = GAMESTATE:GetCurrentSong();
		local course = GAMESTATE:GetCurrentCourse();

		if song or course then self:visible(true)
		else self:visible(false);
		end;
	end;

	Def.BPMDisplay{
		File=THEME:GetPathF("","BPMDisplay");
		Name="BPMDisplay";
		InitCommand=cmd(horizalign,right;shadowlength,0;);
		OnCommand=cmd(stoptweening;playcommand,"Set");
		OffCommand=cmd(linear,0.2;diffusealpha,0);
		SetCommand=function(self)
			self:SetFromGameState();
		end;
		CurrentSongChangedMessageCommand=cmd(playcommand,"Set");
		CurrentCourseChangedMessageCommand=cmd(playcommand,"Set");
	};

	-- label
	LoadActor( THEME:GetPathG("_bpm","label") )..{
		InitCommand=cmd(horizalign,left);
		SetCommand=function(self)
			local song = GAMESTATE:GetCurrentSong();
			local course = GAMESTATE:GetCurrentCourse();
			local commandGrab;
			if song or course then
				-- check if extra stage
				local curStage = GAMESTATE:GetCurrentStage();
				if curStage == 'Stage_Extra1' or curStage == 'Stage_Extra2' then
					commandGrab = THEME:GetMetric("BPMDisplay","SetExtraCommand");
					commandGrab(self)
					return;
				else
					-- check for bpm changes (lol)
					if song then
						local timing = song:GetTimingData();
						if vFlag then
							local bConstantDisplay = song:IsDisplayBpmConstant();
							-- todo: use the DisplayBPM for this check if possible
							if timing:HasBPMChanges() and song:HasSignificantBPMChangesOrStops() and not bConstantDisplay then
								commandGrab = THEME:GetMetric("BPMDisplay","SetChangeCommand");
								commandGrab(self)
								return;
							else
								commandGrab = THEME:GetMetric("BPMDisplay","SetNormalCommand");
								commandGrab(self)
								return;
							end;
						else
							commandGrab = THEME:GetMetric("BPMDisplay","SetNormalCommand");
							commandGrab(self)
							return;
						end;
					else
						commandGrab = THEME:GetMetric("BPMDisplay","SetNoBpmCommand");
						commandGrab(self)
						return;
					end;
				end;
			else
				commandGrab = THEME:GetMetric("BPMDisplay","SetNoBpmCommand");
				commandGrab(self)
				return;
			end;
		end;
		CurrentSongChangedMessageCommand=cmd(playcommand,"Set");
		CurrentCourseChangedMessageCommand=cmd(playcommand,"Set");
	};
};

return t;