1/*
2 * Copyright (c) 2004, Marcus Overhagen <marcus@overhagen.de>. All rights reserved.
3 * Copyright (c) 2007, J��r��me Duval. All rights reserved.
4 * Distributed under the terms of the MIT License.
5 */
6
7
8#include "MediaFilePlayer.h"
9
10#include <MediaFiles.h>
11#include <ObjectList.h>
12
13#include <stdlib.h>
14
15
16BObjectList<MediaFilePlayer> list;
17
18
19MediaFilePlayer*
20FindMediaFilePlayer(MediaFilePlayer* player, void* media_name)
21{
22	if (strcmp(player->Name(), (const char*)media_name) == 0)
23		return player;
24	return NULL;
25}
26
27
28void
29PlayMediaFile(const char* media_type, const char* media_name)
30{
31	entry_ref ref;
32	if (BMediaFiles().GetRefFor(media_type, media_name, &ref) != B_OK
33		|| !BEntry(&ref).Exists())
34		return;
35
36	MediaFilePlayer* player = list.EachElement(FindMediaFilePlayer,
37		(void*)media_name);
38
39	if (player != NULL) {
40		if (*(player->Ref()) == ref) {
41			player->Restart();
42			return;
43		}
44
45		list.RemoveItem(player);
46		delete player;
47		player = NULL;
48	}
49
50	if (player == NULL) {
51		player = new MediaFilePlayer(media_type, media_name, &ref);
52		if (player->InitCheck() == B_OK)
53			list.AddItem(player);
54		else
55			delete player;
56	}
57}
58
59
60
61MediaFilePlayer::MediaFilePlayer(const char* media_type,
62	const char* media_name, entry_ref* ref)
63	:
64	fName(media_name),
65	fInitCheck(B_ERROR),
66	fRef(*ref),
67	fSoundPlayer(NULL),
68	fPlayTrack(NULL)
69{
70	fPlayFile = new BMediaFile(&fRef);
71	fInitCheck = fPlayFile->InitCheck();
72	if (fInitCheck != B_OK)
73		return;
74
75	fPlayFormat.Clear();
76
77	for (int i=0; i < fPlayFile->CountTracks(); i++) {
78		BMediaTrack* track = fPlayFile->TrackAt(i);
79		if (track == NULL)
80			continue;
81		fPlayFormat.type = B_MEDIA_RAW_AUDIO;
82		fPlayFormat.u.raw_audio.buffer_size = 256;
83		if ((track->DecodedFormat(&fPlayFormat) == B_OK)
84			&& (fPlayFormat.type == B_MEDIA_RAW_AUDIO)) {
85			fPlayTrack = track;
86			break;
87		}
88		fPlayFile->ReleaseTrack(track);
89	}
90
91	if (fPlayTrack == NULL) {
92		fInitCheck = B_BAD_VALUE;
93		return;
94	}
95
96	fSoundPlayer = new BSoundPlayer(&fPlayFormat.u.raw_audio,
97		media_name, PlayFunction, NULL, this);
98
99	fInitCheck = fSoundPlayer->InitCheck();
100	if (fInitCheck != B_OK)
101		return;
102
103	fSoundPlayer->SetHasData(true);
104	fSoundPlayer->Start();
105}
106
107
108MediaFilePlayer::~MediaFilePlayer()
109{
110	delete fSoundPlayer;
111	delete fPlayFile;
112}
113
114
115status_t
116MediaFilePlayer::InitCheck()
117{
118	return fInitCheck;
119}
120
121
122const char*
123MediaFilePlayer::Name()
124{
125	return fName;
126}
127
128
129const entry_ref*
130MediaFilePlayer::Ref()
131{
132	return &fRef;
133}
134
135
136bool
137MediaFilePlayer::IsPlaying()
138{
139	return (fSoundPlayer != NULL && fSoundPlayer->HasData());
140}
141
142void
143MediaFilePlayer::Restart()
144{
145	fSoundPlayer->Stop();
146	int64 frame = 0;
147	fPlayTrack->SeekToFrame(&frame);
148	fSoundPlayer->SetHasData(true);
149	fSoundPlayer->Start();
150}
151
152
153void
154MediaFilePlayer::Stop()
155{
156	fSoundPlayer->Stop();
157}
158
159
160void
161MediaFilePlayer::PlayFunction(void* cookie, void* buffer,
162	size_t size, const media_raw_audio_format& format)
163{
164	MediaFilePlayer* player = (MediaFilePlayer*)cookie;
165	int64 frames = 0;
166	player->fPlayTrack->ReadFrames(buffer, &frames);
167
168	if (frames <= 0)
169		player->fSoundPlayer->SetHasData(false);
170}
171