Commit 5ace4450 authored by Hugo Beauzée-Luyssen's avatar Hugo Beauzée-Luyssen

video_controller: Simplify media library callbacks handling

parent 48052a47
......@@ -42,25 +42,38 @@ struct video_controller
Eina_List* p_content;
};
static void
video_controller_add_item(video_controller* ctrl, const media_item* p_item)
{
media_item* p_new_item = media_item_copy( p_item );
if (p_new_item == NULL)
return;
video_list_item* p_view_item = video_view_append_item( ctrl->p_view, p_new_item );
if (p_view_item == NULL)
{
media_item_destroy(p_new_item);
return;
}
ctrl->p_content = eina_list_append(ctrl->p_content, p_view_item);
}
/* Called by the Media Library with updated video list
* Guaranteed to be called from the main loop
*/
void
video_controller_content_update_cb(Eina_List* p_content, void* p_data)
{
video_controller* ctrl = (video_controller*)p_data;
if (p_content == NULL)
return;
video_controller* ctrl = (video_controller*)p_data;
Eina_List* it;
media_item* p_item;
// If we get multiple content updates, p_ctrl->p_content can't be != NULL
assert( ctrl->p_content == NULL );
video_view_clear(ctrl->p_view);
EINA_LIST_FOREACH( p_content, it, p_item )
{
video_list_item* p_view_item = video_view_append_item( ctrl->p_view, p_item );
if (p_view_item == NULL)
continue;
ctrl->p_content = eina_list_append(ctrl->p_content, p_view_item);
video_controller_add_item(ctrl, p_item);
}
}
......@@ -68,45 +81,46 @@ video_controller_content_update_cb(Eina_List* p_content, void* p_data)
void
video_controller_content_refresh(video_controller* ctrl)
{
// If we already have some content, consider the view up to date
// In case content gets updated, media library will call video_controller_content_changed_cb
// causing us to clear the cached content.
// Discard previous content if any, and ask ML for the new content
if (ctrl->p_content != NULL)
return;
{
eina_list_free(ctrl->p_content);
ctrl->p_content = NULL;
}
// otherwise, update from media library
media_library* p_ml = (media_library*)application_get_media_library( ctrl->p_app );
media_library_get_video_files(p_ml, &video_controller_content_update_cb, ctrl);
}
/* Called when media library signals a content change */
/*
* Called when media library signals a content change
* Guaranteed to be called from the main loop
*/
void
video_controller_content_changed_cb(void* p_data)
{
LOGI("Media Library content changed");
video_controller* ctrl = (video_controller*)p_data;
// Discard previous content if any, and ask ML for the
// new content
if (ctrl->p_content != NULL)
{
eina_list_free(ctrl->p_content);
ctrl->p_content = NULL;
}
video_controller_content_refresh(ctrl);
}
static bool
video_controller_file_updated_cb( void* p_data, const media_item* p_new_media_item )
video_controller_file_updated_cb( void* p_data, const media_item* p_new_media_item, bool b_added )
{
LOGI("Updating: %s", p_new_media_item->psz_path);
if ( p_new_media_item->i_type != MEDIA_ITEM_TYPE_VIDEO )
return false;
video_controller* ctrl = (video_controller*)p_data;
if ( ctrl->p_content == NULL )
if ( b_added )
{
LOGI("No content, aborting");
return false;
video_controller_add_item(ctrl, p_new_media_item);
return true;
}
if ( ctrl->p_content == NULL )
return false;
Eina_List* it;
video_list_item* p_item;
EINA_LIST_FOREACH( ctrl->p_content, it, p_item )
{
const media_item* p_media_item = video_list_item_get_media_item(p_item);
......
......@@ -68,11 +68,6 @@ fileToMediaItem( FilePtr file )
mi->i_w = vtrack->width();
mi->i_h = vtrack->height();
}
else
{
// Assume a media library problem and just let it go.
LOGW( "Adding video file [%s] with no video tracks detected.", file->mrl().c_str() );
}
if (file->snapshot().length() > 0)
mi->psz_snapshot = strdup(file->snapshot().c_str());
}
......
......@@ -36,8 +36,6 @@
media_library::media_library()
: ml( MediaLibraryFactory::create() )
, m_nbDiscovery( 0 )
, m_nbElemChanged( 0 )
{
if ( ml == nullptr )
throw std::runtime_error( "Failed to initialize MediaLibrary" );
......@@ -46,54 +44,43 @@ media_library::media_library()
void
media_library::onFileAdded( FilePtr file )
{
//FIXME: This seems fishy if no discovery is in progress and some media gets updated.
//This is very unlikely to happen for a while though.
std::unique_lock<std::mutex> lock( m_mutex );
if ( ++m_nbElemChanged >= 50 )
{
LOGI("Enough changes to trigger an update.");
onChange();
m_nbElemChanged = 0;
}
sendFileUpdate( file, true );
}
void
media_library::onFileUpdated( FilePtr file )
{
sendFileUpdate( file, false );
}
void
media_library::sendFileUpdate( FilePtr file, bool added )
{
auto item = fileToMediaItem( file );
auto item_ptr = std::unique_ptr<media_item, void(*)(media_item*)> ( item, &media_item_destroy );
for ( auto& p : m_onItemUpdatedCb )
{
if ( p.first( p.second, item ) == true )
break;
}
LOGI("Updated file %s %d", item->psz_path, item->i_duration);
auto ctx = new FileUpdateCallbackCtx{this, item, added};
ecore_main_loop_thread_safe_call_async([](void* data) {
auto ctx = reinterpret_cast<FileUpdateCallbackCtx*>(data);
auto item_ptr = std::unique_ptr<media_item, void(*)(media_item*)> ( ctx->item, &media_item_destroy );
for ( auto& p : ctx->ml->m_onItemUpdatedCb )
{
if ( p.first( p.second, ctx->item, ctx->added ) == true )
break;
}
delete ctx;
}, ctx);
}
void
media_library::onDiscoveryStarted( const std::string& entryPoint )
{
LOGI( "Starting [%s] discovery", entryPoint.c_str() );
std::unique_lock<std::mutex> lock( m_mutex );
m_nbDiscovery++;
}
void
media_library::onDiscoveryCompleted( const std::string& entryPoint )
{
LOGI("Completed [%s] discovery", entryPoint.c_str() );
std::unique_lock<std::mutex> lock( m_mutex );
if ( --m_nbDiscovery == 0 )
{
// If this is the last discovery, and some files got updated, send a final update
if ( m_nbElemChanged != 0 )
{
m_nbElemChanged = 0;
LOGI("Changes detected, sending update to listeners");
onChange();
}
LOGI( "Completed all active discovery operations" );
}
}
void
......@@ -106,6 +93,10 @@ void
media_library::onReloadCompleted()
{
LOGI("Media library reload completed.");
for (auto &p : m_onChangeCb)
{
ecore_main_loop_thread_safe_call_async( p.first, p.second );
}
}
void
......@@ -128,15 +119,6 @@ media_library::unregisterOnChange(media_library_file_list_changed_cb cb, void* c
}
}
void
media_library::onChange()
{
for (auto &p : m_onChangeCb)
{
ecore_main_loop_thread_safe_call_async( p.first, p.second );
}
}
void
media_library::registerOnItemUpdated(media_library_item_updated_cb cb, void* userData)
{
......
......@@ -44,7 +44,7 @@ typedef void (*media_library_list_cb)( Eina_List*, void *p_user_data );
* looking to update.
* There is no warranty about which thread will call this callback.
*/
typedef bool (*media_library_item_updated_cb)( void *p_user_data, const media_item* p_item );
typedef bool (*media_library_item_updated_cb)( void *p_user_data, const media_item* p_item, bool b_new );
media_library*
media_library_create(application* p_app);
......
......@@ -84,17 +84,19 @@ public:
std::unique_ptr<IMediaLibrary> ml;
private:
void onChange();
void sendFileUpdate( FilePtr item, bool added );
private:
struct FileUpdateCallbackCtx
{
FileUpdateCallbackCtx(media_library* _ml, media_item* _item, bool _added)
: ml(_ml), item(_item), added(_added) {}
media_library* ml;
media_item* item;
bool added;
};
private:
// Holds the number of discoveries ongoing
// This gets incremented by the caller thread (most likely the main loop)
// and gets decremented by the discovery thread, hence the need for atomic
int m_nbDiscovery;
// Holds the number of changes since last call to fileListChangedCb.
// This can be accessed from both the discovery & metadata threads
int m_nbElemChanged;
std::mutex m_mutex;
std::vector<std::pair<media_library_file_list_changed_cb, void*>> m_onChangeCb;
std::vector<std::pair<media_library_item_updated_cb, void*>> m_onItemUpdatedCb;
};
......@@ -115,31 +115,11 @@ video_list_item_get_media_item(video_list_item* p_item)
void
video_list_item_set_media_item(video_list_item* p_item, const media_item* p_media_item)
{
bool b_changed = false;
if (p_item->p_media_item->i_duration != p_media_item->i_duration)
{
p_item->p_media_item->i_duration = p_media_item->i_duration;
b_changed = true;
}
if (p_media_item->psz_snapshot != NULL && (
p_item->p_media_item->psz_snapshot == NULL ||
strcmp( p_item->p_media_item->psz_snapshot, p_media_item->psz_snapshot)))
{
free(p_item->p_media_item->psz_snapshot);
p_item->p_media_item->psz_snapshot = strdup(p_media_item->psz_snapshot);
b_changed = true;
}
if ( p_item->p_media_item->i_w != p_media_item->i_w ||
p_item->p_media_item->i_h != p_media_item->i_h )
{
p_item->p_media_item->i_w = p_media_item->i_w;
p_item->p_media_item->i_h = p_media_item->i_h;
b_changed = true;
}
if (b_changed == true)
{
ecore_main_loop_thread_safe_call_async((Ecore_Cb)elm_genlist_item_update, p_item->p_object_item);
}
media_item* p_new = media_item_copy(p_media_item);
if (p_new == NULL)
return;
p_item->p_media_item = p_new;
ecore_main_loop_thread_safe_call_async((Ecore_Cb)elm_genlist_item_update, p_item->p_object_item);
}
static Evas_Object*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment