Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/audioplayers/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 3.1.4

* Remove Ecore API.

## 3.1.3

* Adds compatibility with `http` 1.0 in example.
Expand Down
2 changes: 1 addition & 1 deletion packages/audioplayers/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ This package is not an _endorsed_ implementation of `audioplayers`. Therefore, y
```yaml
dependencies:
audioplayers: ^6.6.0
audioplayers_tizen: ^3.1.3
audioplayers_tizen: ^3.1.4

```

Expand Down
2 changes: 1 addition & 1 deletion packages/audioplayers/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: audioplayers_tizen
description: Tizen implementation of the audioplayers plugin.
homepage: https://github.com/flutter-tizen/plugins
repository: https://github.com/flutter-tizen/plugins/tree/master/packages/audioplayers
version: 3.1.3
version: 3.1.4

environment:
sdk: ^3.6.0
Expand Down
88 changes: 61 additions & 27 deletions packages/audioplayers/tizen/src/audio_player.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@
#include "audio_player_error.h"
#include "log.h"

namespace {

struct IdleData {
AudioPlayer *player;
std::shared_ptr<bool> is_alive;
};

} // namespace

AudioPlayer::AudioPlayer(const std::string &player_id,
PreparedListener prepared_listener,
DurationListener duration_listener,
Expand All @@ -30,10 +39,11 @@ AudioPlayer::~AudioPlayer() {
player_destroy(player_);
player_ = nullptr;
}
if (timer_) {
ecore_timer_del(timer_);
timer_ = nullptr;
if (timer_id_ != 0) {
g_source_remove(timer_id_);
timer_id_ = 0;
}
Comment thread
JSUYA marked this conversation as resolved.
*is_alive_ = false;
}

void AudioPlayer::Play() {
Expand Down Expand Up @@ -343,28 +353,34 @@ player_state_e AudioPlayer::GetPlayerState() {
}

void AudioPlayer::OnPrepared(void *data) {
auto *self = reinterpret_cast<AudioPlayer *>(data);
// On TV devices, callbacks are not executed on the main loop. Therefore
// we explicitly transfer the callback to the main loop to avoid any race
// conditions and to allow creating timer objects in StartPositionUpdates.
ecore_main_loop_thread_safe_call_async(
[](void *data) {
auto *player = reinterpret_cast<AudioPlayer *>(data);
g_idle_add_full(
G_PRIORITY_DEFAULT_IDLE,
[](gpointer data) -> gboolean {
auto *idle = static_cast<IdleData *>(data);
if (!*idle->is_alive) {
return G_SOURCE_REMOVE;
}
auto *player = idle->player;
player->preparing_ = false;

try {
player->duration_listener_(player->player_id_, player->GetDuration());
player->prepared_listener_(player->player_id_, true);
} catch (const AudioPlayerError &error) {
player->log_listener_(player->player_id_, error.code());
return;
return G_SOURCE_REMOVE;
}
player_set_playback_rate(player->player_, player->playback_rate_);

if (player->should_play_) {
int ret = player_start(player->player_);
if (ret != PLAYER_ERROR_NONE) {
player->log_listener_(player->player_id_, "player_start failed.");
return;
return G_SOURCE_REMOVE;
}
player->StartPositionUpdates();
player->should_play_ = false;
Expand All @@ -374,48 +390,66 @@ void AudioPlayer::OnPrepared(void *data) {
player->seeking_ = true;
int ret =
player_set_play_position(player->player_, player->should_seek_to_,
true, OnSeekCompleted, data);
true, OnSeekCompleted, player);
if (ret != PLAYER_ERROR_NONE) {
player->seeking_ = false;
player->log_listener_(player->player_id_,
"player_set_play_position failed.");
return;
return G_SOURCE_REMOVE;
}
player->should_seek_to_ = -1;
}
return G_SOURCE_REMOVE;
},
data);
new IdleData{self, self->is_alive_},
[](gpointer data) { delete static_cast<IdleData *>(data); });
}

void AudioPlayer::OnSeekCompleted(void *data) {
auto *self = reinterpret_cast<AudioPlayer *>(data);
// On TV devices, callbacks are not executed on the main loop. Therefore
// we explicitly transfer the callback to the main loop to avoid any race
// conditions.
ecore_main_loop_thread_safe_call_async(
[](void *data) {
auto *player = reinterpret_cast<AudioPlayer *>(data);
g_idle_add_full(
G_PRIORITY_DEFAULT_IDLE,
[](gpointer data) -> gboolean {
auto *idle = static_cast<IdleData *>(data);
if (!*idle->is_alive) {
return G_SOURCE_REMOVE;
}
auto *player = idle->player;
player->seek_completed_listener_(player->player_id_);
player->seeking_ = false;
return G_SOURCE_REMOVE;
},
data);
new IdleData{self, self->is_alive_},
[](gpointer data) { delete static_cast<IdleData *>(data); });
}

void AudioPlayer::OnPlayCompleted(void *data) {
auto *self = reinterpret_cast<AudioPlayer *>(data);
// On TV devices, callbacks are not executed on the main loop. Therefore
// we explicitly transfer the callback to the main loop to avoid any race
// conditions.
ecore_main_loop_thread_safe_call_async(
[](void *data) {
auto *player = reinterpret_cast<AudioPlayer *>(data);
g_idle_add_full(
G_PRIORITY_DEFAULT_IDLE,
[](gpointer data) -> gboolean {
auto *idle = static_cast<IdleData *>(data);
if (!*idle->is_alive) {
return G_SOURCE_REMOVE;
}
auto *player = idle->player;
try {
player->Seek(0);
player->Stop();
player->play_completed_listener_(player->player_id_);
} catch (const AudioPlayerError &error) {
player->log_listener_(player->player_id_, error.code());
}
return G_SOURCE_REMOVE;
},
data);
new IdleData{self, self->is_alive_},
[](gpointer data) { delete static_cast<IdleData *>(data); });
}

void AudioPlayer::OnInterrupted(player_interrupted_code_e code, void *data) {
Expand All @@ -433,27 +467,27 @@ void AudioPlayer::OnError(int code, void *data) {
}

void AudioPlayer::StartPositionUpdates() {
if (!timer_) {
if (timer_id_ == 0) {
// The audioplayers app facing package expects position
// update events to fire roughly every 200 milliseconds.
const double kTimeInterval = 0.2;
timer_ = ecore_timer_add(kTimeInterval, OnPositionUpdate, this);
if (!timer_) {
const guint kTimeInterval = 200;
timer_id_ = g_timeout_add(kTimeInterval, OnPositionUpdate, this);
if (timer_id_ == 0) {
log_listener_(player_id_, "Failed to add a position update timer.");
}
}
}

Eina_Bool AudioPlayer::OnPositionUpdate(void *data) {
gboolean AudioPlayer::OnPositionUpdate(gpointer data) {
auto *player = reinterpret_cast<AudioPlayer *>(data);
try {
if (player->IsPlaying()) {
player->duration_listener_(player->player_id_, player->GetDuration());
return ECORE_CALLBACK_RENEW;
return G_SOURCE_CONTINUE;
}
} catch (const AudioPlayerError &error) {
player->log_listener_(player->player_id_, "Failed to update position.");
}
player->timer_ = nullptr;
return ECORE_CALLBACK_CANCEL;
player->timer_id_ = 0;
return G_SOURCE_REMOVE;
}
8 changes: 5 additions & 3 deletions packages/audioplayers/tizen/src/audio_player.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
#ifndef FLUTTER_PLUGIN_AUDIO_PLAYER_H_
#define FLUTTER_PLUGIN_AUDIO_PLAYER_H_

#include <Ecore.h>
#include <glib.h>
#include <player.h>

#include <functional>
Comment thread
JSUYA marked this conversation as resolved.
#include <memory>
#include <string>
#include <vector>

Expand Down Expand Up @@ -71,7 +72,7 @@ class AudioPlayer {
static void OnPlayCompleted(void *data);
static void OnInterrupted(player_interrupted_code_e code, void *data);
static void OnError(int code, void *data);
static Eina_Bool OnPositionUpdate(void *data);
static gboolean OnPositionUpdate(gpointer data);

player_h player_ = nullptr;
const std::string player_id_;
Expand All @@ -84,7 +85,8 @@ class AudioPlayer {
bool preparing_ = false;
bool seeking_ = false;
bool should_play_ = false;
Ecore_Timer *timer_ = nullptr;
guint timer_id_ = 0;
Comment thread
JSUYA marked this conversation as resolved.
std::shared_ptr<bool> is_alive_ = std::make_shared<bool>(true);

PreparedListener prepared_listener_;
DurationListener duration_listener_;
Expand Down
Loading