xref: /haiku/src/servers/media_addon/MediaFilePlayer.cpp (revision a3e794ae459fec76826407f8ba8c94cd3535f128)
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 
16 BObjectList<MediaFilePlayer> list;
17 
18 
19 MediaFilePlayer*
20 FindMediaFilePlayer(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 
28 void
29 PlayMediaFile(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 
61 MediaFilePlayer::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 	memset(&fPlayFormat, 0, sizeof(fPlayFormat));
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->SetVolume(1.0f);
104 	fSoundPlayer->SetHasData(true);
105 	fSoundPlayer->Start();
106 }
107 
108 
109 MediaFilePlayer::~MediaFilePlayer()
110 {
111 	delete fSoundPlayer;
112 	delete fPlayFile;
113 }
114 
115 
116 status_t
117 MediaFilePlayer::InitCheck()
118 {
119 	return fInitCheck;
120 }
121 
122 
123 const char*
124 MediaFilePlayer::Name()
125 {
126 	return fName;
127 }
128 
129 
130 const entry_ref*
131 MediaFilePlayer::Ref()
132 {
133 	return &fRef;
134 }
135 
136 
137 bool
138 MediaFilePlayer::IsPlaying()
139 {
140 	return (fSoundPlayer != NULL && fSoundPlayer->HasData());
141 }
142 
143 void
144 MediaFilePlayer::Restart()
145 {
146 	fSoundPlayer->Stop();
147 	int64 frame = 0;
148 	fPlayTrack->SeekToFrame(&frame);
149 	fSoundPlayer->SetHasData(true);
150 	fSoundPlayer->Start();
151 }
152 
153 
154 void
155 MediaFilePlayer::Stop()
156 {
157 	fSoundPlayer->Stop();
158 }
159 
160 
161 void
162 MediaFilePlayer::PlayFunction(void* cookie, void* buffer,
163 	size_t size, const media_raw_audio_format& format)
164 {
165 	MediaFilePlayer* player = (MediaFilePlayer*)cookie;
166 	int64 frames = 0;
167 	player->fPlayTrack->ReadFrames(buffer, &frames);
168 
169 	if (frames <= 0)
170 		player->fSoundPlayer->SetHasData(false);
171 }
172