Spaces:
Sleeping
Sleeping
/* poppler-media.cc: glib interface to MediaRendition | |
* | |
* Copyright (C) 2010 Carlos Garcia Campos <carlosgc@gnome.org> | |
* | |
* This program is free software; you can redistribute it and/or modify | |
* it under the terms of the GNU General Public License as published by | |
* the Free Software Foundation; either version 2, or (at your option) | |
* any later version. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License | |
* along with this program; if not, write to the Free Software | |
* Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. | |
*/ | |
/** | |
* SECTION: poppler-media | |
* @short_description: Media | |
* @title: PopplerMedia | |
*/ | |
typedef struct _PopplerMediaClass PopplerMediaClass; | |
struct _PopplerMedia | |
{ | |
GObject parent_instance; | |
gchar *filename; | |
gboolean auto_play; | |
gboolean show_controls; | |
gfloat repeat_count; | |
gchar *mime_type; | |
Object stream; | |
}; | |
struct _PopplerMediaClass | |
{ | |
GObjectClass parent_class; | |
}; | |
G_DEFINE_TYPE(PopplerMedia, poppler_media, G_TYPE_OBJECT) | |
static void poppler_media_finalize(GObject *object) | |
{ | |
PopplerMedia *media = POPPLER_MEDIA(object); | |
if (media->filename) { | |
g_free(media->filename); | |
media->filename = nullptr; | |
} | |
if (media->mime_type) { | |
g_free(media->mime_type); | |
media->mime_type = nullptr; | |
} | |
media->stream = Object(); | |
G_OBJECT_CLASS(poppler_media_parent_class)->finalize(object); | |
} | |
static void poppler_media_class_init(PopplerMediaClass *klass) | |
{ | |
GObjectClass *gobject_class = G_OBJECT_CLASS(klass); | |
gobject_class->finalize = poppler_media_finalize; | |
} | |
static void poppler_media_init(PopplerMedia *media) { } | |
PopplerMedia *_poppler_media_new(const MediaRendition *poppler_media) | |
{ | |
PopplerMedia *media; | |
g_assert(poppler_media != nullptr); | |
media = POPPLER_MEDIA(g_object_new(POPPLER_TYPE_MEDIA, nullptr)); | |
if (poppler_media->getIsEmbedded()) { | |
const GooString *mime_type; | |
media->stream = poppler_media->getEmbbededStreamObject()->copy(); | |
mime_type = poppler_media->getContentType(); | |
if (mime_type) { | |
media->mime_type = g_strdup(mime_type->c_str()); | |
} | |
} else { | |
media->filename = g_strdup(poppler_media->getFileName()->c_str()); | |
} | |
const MediaParameters *mp = poppler_media->getBEParameters(); | |
mp = mp ? mp : poppler_media->getMHParameters(); | |
media->auto_play = mp ? mp->autoPlay : false; | |
media->show_controls = mp ? mp->showControls : false; | |
media->repeat_count = mp ? mp->repeatCount : 1.f; | |
return media; | |
} | |
/** | |
* poppler_media_get_filename: | |
* @poppler_media: a #PopplerMedia | |
* | |
* Returns the media clip filename, in case of non-embedded media. filename might be | |
* a local relative or absolute path or a URI | |
* | |
* Return value: a filename, return value is owned by #PopplerMedia and should not be freed | |
* | |
* Since: 0.14 | |
*/ | |
const gchar *poppler_media_get_filename(PopplerMedia *poppler_media) | |
{ | |
g_return_val_if_fail(POPPLER_IS_MEDIA(poppler_media), NULL); | |
g_return_val_if_fail(!poppler_media->stream.isStream(), NULL); | |
return poppler_media->filename; | |
} | |
/** | |
* poppler_media_is_embedded: | |
* @poppler_media: a #PopplerMedia | |
* | |
* Whether the media clip is embedded in the PDF. If the result is %TRUE, the embedded stream | |
* can be saved with poppler_media_save() or poppler_media_save_to_callback() function. | |
* If the result is %FALSE, the media clip filename can be retrieved with | |
* poppler_media_get_filename() function. | |
* | |
* Return value: %TRUE if media clip is embedded, %FALSE otherwise | |
* | |
* Since: 0.14 | |
*/ | |
gboolean poppler_media_is_embedded(PopplerMedia *poppler_media) | |
{ | |
g_return_val_if_fail(POPPLER_IS_MEDIA(poppler_media), FALSE); | |
return poppler_media->stream.isStream(); | |
} | |
/** | |
* poppler_media_get_auto_play: | |
* @poppler_media: a #PopplerMedia | |
* | |
* Returns the auto-play parameter. | |
* | |
* Return value: %TRUE if media should auto-play, %FALSE otherwise | |
* | |
* Since: 20.04.0 | |
*/ | |
gboolean poppler_media_get_auto_play(PopplerMedia *poppler_media) | |
{ | |
g_return_val_if_fail(POPPLER_IS_MEDIA(poppler_media), FALSE); | |
return poppler_media->auto_play; | |
} | |
/** | |
* poppler_media_get_show_controls: | |
* @poppler_media: a #PopplerMedia | |
* | |
* Returns the show controls parameter. | |
* | |
* Return value: %TRUE if media should show controls, %FALSE otherwise | |
* | |
* Since: 20.04.0 | |
*/ | |
gboolean poppler_media_get_show_controls(PopplerMedia *poppler_media) | |
{ | |
g_return_val_if_fail(POPPLER_IS_MEDIA(poppler_media), FALSE); | |
return poppler_media->show_controls; | |
} | |
/** | |
* poppler_media_get_repeat_count: | |
* @poppler_media: a #PopplerMedia | |
* | |
* Returns the repeat count parameter. | |
* | |
* Return value: Repeat count parameter (float) | |
* | |
* Since: 20.04.0 | |
*/ | |
gfloat poppler_media_get_repeat_count(PopplerMedia *poppler_media) | |
{ | |
g_return_val_if_fail(POPPLER_IS_MEDIA(poppler_media), FALSE); | |
return poppler_media->repeat_count; | |
} | |
/** | |
* poppler_media_get_mime_type: | |
* @poppler_media: a #PopplerMedia | |
* | |
* Returns the media clip mime-type | |
* | |
* Return value: the mime-type, return value is owned by #PopplerMedia and should not be freed | |
* | |
* Since: 0.14 | |
*/ | |
const gchar *poppler_media_get_mime_type(PopplerMedia *poppler_media) | |
{ | |
g_return_val_if_fail(POPPLER_IS_MEDIA(poppler_media), NULL); | |
return poppler_media->mime_type; | |
} | |
static gboolean save_helper(const gchar *buf, gsize count, gpointer data, GError **error) | |
{ | |
FILE *f = (FILE *)data; | |
gsize n; | |
n = fwrite(buf, 1, count, f); | |
if (n != count) { | |
int errsv = errno; | |
g_set_error(error, G_FILE_ERROR, g_file_error_from_errno(errsv), "Error writing to media file: %s", g_strerror(errsv)); | |
return FALSE; | |
} | |
return TRUE; | |
} | |
/** | |
* poppler_media_save: | |
* @poppler_media: a #PopplerMedia | |
* @filename: name of file to save | |
* @error: (allow-none): return location for error, or %NULL. | |
* | |
* Saves embedded stream of @poppler_media to a file indicated by @filename. | |
* If @error is set, %FALSE will be returned. | |
* Possible errors include those in the #G_FILE_ERROR domain | |
* and whatever the save function generates. | |
* | |
* Return value: %TRUE, if the file successfully saved | |
* | |
* Since: 0.14 | |
*/ | |
gboolean poppler_media_save(PopplerMedia *poppler_media, const char *filename, GError **error) | |
{ | |
gboolean result; | |
FILE *f; | |
g_return_val_if_fail(POPPLER_IS_MEDIA(poppler_media), FALSE); | |
g_return_val_if_fail(poppler_media->stream.isStream(), FALSE); | |
f = openFile(filename, "wb"); | |
if (f == nullptr) { | |
gchar *display_name = g_filename_display_name(filename); | |
g_set_error(error, G_FILE_ERROR, g_file_error_from_errno(errno), "Failed to open '%s' for writing: %s", display_name, g_strerror(errno)); | |
g_free(display_name); | |
return FALSE; | |
} | |
result = poppler_media_save_to_callback(poppler_media, save_helper, f, error); | |
if (fclose(f) < 0) { | |
gchar *display_name = g_filename_display_name(filename); | |
g_set_error(error, G_FILE_ERROR, g_file_error_from_errno(errno), "Failed to close '%s', all data may not have been saved: %s", display_name, g_strerror(errno)); | |
g_free(display_name); | |
return FALSE; | |
} | |
return result; | |
} | |
/** | |
* poppler_media_save_to_fd: | |
* @poppler_media: a #PopplerMedia | |
* @fd: a valid file descriptor open for writing | |
* @error: (allow-none): return location for error, or %NULL. | |
* | |
* Saves embedded stream of @poppler_media to a file referred to by @fd. | |
* If @error is set, %FALSE will be returned. | |
* Possible errors include those in the #G_FILE_ERROR domain | |
* and whatever the save function generates. | |
* Note that this function takes ownership of @fd; you must not operate on it | |
* again, nor close it. | |
* | |
* Return value: %TRUE, if the file successfully saved | |
* | |
* Since: 21.12.0 | |
*/ | |
gboolean poppler_media_save_to_fd(PopplerMedia *poppler_media, int fd, GError **error) | |
{ | |
gboolean result; | |
FILE *f; | |
g_return_val_if_fail(POPPLER_IS_MEDIA(poppler_media), FALSE); | |
g_return_val_if_fail(poppler_media->stream.isStream(), FALSE); | |
f = fdopen(fd, "wb"); | |
if (f == nullptr) { | |
int errsv = errno; | |
g_set_error(error, G_FILE_ERROR, g_file_error_from_errno(errsv), "Failed to open FD %d for writing: %s", fd, g_strerror(errsv)); | |
close(fd); | |
return FALSE; | |
} | |
result = poppler_media_save_to_callback(poppler_media, save_helper, f, error); | |
if (fclose(f) < 0) { | |
int errsv = errno; | |
g_set_error(error, G_FILE_ERROR, g_file_error_from_errno(errsv), "Failed to close FD %d, all data may not have been saved: %s", fd, g_strerror(errsv)); | |
return FALSE; | |
} | |
return result; | |
} | |
/** | |
* poppler_media_save_to_callback: | |
* @poppler_media: a #PopplerMedia | |
* @save_func: (scope call): a function that is called to save each block of data that the save routine generates. | |
* @user_data: user data to pass to the save function. | |
* @error: (allow-none): return location for error, or %NULL. | |
* | |
* Saves embedded stream of @poppler_media by feeding the produced data to @save_func. Can be used | |
* when you want to store the media clip stream to something other than a file, such as | |
* an in-memory buffer or a socket. If @error is set, %FALSE will be | |
* returned. Possible errors include those in the #G_FILE_ERROR domain and | |
* whatever the save function generates. | |
* | |
* Return value: %TRUE, if the save successfully completed | |
* | |
* Since: 0.14 | |
*/ | |
gboolean poppler_media_save_to_callback(PopplerMedia *poppler_media, PopplerMediaSaveFunc save_func, gpointer user_data, GError **error) | |
{ | |
Stream *stream; | |
gchar buf[BUF_SIZE]; | |
int i; | |
gboolean eof_reached = FALSE; | |
g_return_val_if_fail(POPPLER_IS_MEDIA(poppler_media), FALSE); | |
g_return_val_if_fail(poppler_media->stream.isStream(), FALSE); | |
stream = poppler_media->stream.getStream(); | |
stream->reset(); | |
do { | |
int data; | |
for (i = 0; i < BUF_SIZE; i++) { | |
data = stream->getChar(); | |
if (data == EOF) { | |
eof_reached = TRUE; | |
break; | |
} | |
buf[i] = data; | |
} | |
if (i > 0) { | |
if (!(save_func)(buf, i, user_data, error)) { | |
stream->close(); | |
return FALSE; | |
} | |
} | |
} while (!eof_reached); | |
stream->close(); | |
return TRUE; | |
} | |