📄 gui_main.cpp
字号:
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is MPEG4IP. * * The Initial Developer of the Original Code is Cisco Systems Inc. * Portions created by Cisco Systems Inc. are * Copyright (C) Cisco Systems Inc. 2001-2005. All Rights Reserved. * * Contributor(s): * Dave Mackie dmackie@cisco.com * Bill May wmay@cisco.com *//* * gui_main.cpp - Contains the gtk based gui */#define __STDC_LIMIT_MACROS#include "mp4live.h"#include "mp4live_gui.h"#include "preview_flow.h"#include "gdk/gdkx.h"#include "support.h"#include "profile_video.h"#include "profile_audio.h"#include "profile_text.h"#include "mp4live_common.h"#include "rtp_transmitter.h"#include "text_source.h"#include "video_v4l_source.h"#define HAVE_TEXT 1//#define HAVE_TEXT_ENTRY 1CLiveConfig* MyConfig;CPreviewAVMediaFlow* AVFlow = NULL;/* Local variables */static bool started = false;GtkWidget *MainWindow;static GtkTooltips *tooltips;const char *SelectedStream;static Timestamp StartTime;static Timestamp StopTime;static Duration FlowDuration;static const u_int32_t durationUnitsValues[] = { 1, 60, 3600, 3600*24, 3600*24*365};//static u_int64_t StartFileSize;//static u_int64_t StopFileSize;static void on_VideoPreview(GtkToggleButton *togglebutton, gpointer user_data);CMediaStream *GetSelectedStream (void){ return AVFlow->m_stream_list->FindStream(SelectedStream);}static void DisplayFinishTime (Timestamp t){ time_t secs; struct tm local; char buffer[128]; secs = (time_t)GetSecsFromTimestamp(t); localtime_r(&secs, &local); strftime(buffer, sizeof(buffer), "%l:%M:%S", &local); GtkWidget *temp; temp = lookup_widget(MainWindow, "EndTimeLabel"); gtk_label_set_text(GTK_LABEL(temp), buffer); strftime(buffer, sizeof(buffer), "%p", &local); temp = lookup_widget(MainWindow, "EndTimeSuffix"); gtk_label_set_text(GTK_LABEL(temp), buffer);}#if 0static void on_audio_mute_button (GtkWidget *widget, gpointer *data){ AVFlow->SetAudioOutput( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));}#endifstatic const char *lockouts[] = { "new1", "open1", "save1", "generate_addresses", "generate_sdp", "preferences1", "AddStreamButton", "DeleteStreamButton", "StreamCaption", "StreamDescription", "VideoEnabled", "AudioEnabled",#ifdef HAVE_TEXT "TextEnabled", "TextSourceMenu",#endif //"VideoSourceMenu", // not if we want to switch sources mid stream "AudioSourceMenu", "Duration", "DurationType", NULL};static const char *lockins[] = { "restart_recording", NULL,}; static void LockoutChanges (bool lockout) { GtkWidget *temp; uint ix; for (ix = 0; lockouts[ix] != NULL; ix++) { temp = lookup_widget(MainWindow, lockouts[ix]); gtk_widget_set_sensitive(GTK_WIDGET(temp), !lockout); } for (ix = 0; lockins[ix] != NULL; ix++) { temp = lookup_widget(MainWindow, lockins[ix]); gtk_widget_set_sensitive(GTK_WIDGET(temp), lockout); }}static guint status_timer_id;static void status_start(){ time_t secs; struct tm local; char buffer[128]; GtkWidget *temp; // start time secs = (time_t)GetSecsFromTimestamp(StartTime); localtime_r(&secs, &local); strftime(buffer, sizeof(buffer), "%l:%M:%S", &local); temp = lookup_widget(MainWindow, "StartTimeLabel"); gtk_label_set_text(GTK_LABEL(temp), buffer); strftime(buffer, sizeof(buffer), "%p", &local); temp = lookup_widget(MainWindow, "StartTimeSuffix"); gtk_label_set_text(GTK_LABEL(temp), buffer); // finish time if (StopTime) { DisplayFinishTime(StopTime); }#if 0 // file size StartFileSize = 0; StopFileSize = 0; if (MyConfig->GetBoolValue(CONFIG_RECORD_ENABLE)) { snprintf(buffer, sizeof(buffer), " "U64, StartFileSize / TO_U64(1000000)); gtk_label_set_text(GTK_LABEL(current_size), buffer); gtk_widget_show(current_size); gtk_label_set_text(GTK_LABEL(current_size_units), "MB"); gtk_widget_show(current_size_units); StopFileSize = MyConfig->m_recordEstFileSize; snprintf(buffer, sizeof(buffer), " "U64, StopFileSize / TO_U64(1000000)); gtk_label_set_text(GTK_LABEL(final_size), buffer); gtk_widget_show(final_size); gtk_label_set_text(GTK_LABEL(final_size_units), "MB"); gtk_widget_show(final_size_units); }#endif}/* * Status timer routine */static gint status_timer (gpointer raw){ time_t secs; struct tm local; char buffer[80]; GtkWidget *temp; if (AVFlow->ProcessSDLEvents(false)) { on_VideoPreview(NULL, GINT_TO_POINTER(2)); } if (started == false) { return AVFlow->doingPreview(); } Timestamp now = GetTimestamp(); secs = (time_t)GetSecsFromTimestamp(now); localtime_r(&secs, &local); strftime(buffer, sizeof(buffer), "%l:%M:%S", &local); temp = lookup_widget(MainWindow, "CurrentTimeLabel"); gtk_label_set_text(GTK_LABEL(temp), buffer); strftime(buffer, sizeof(buffer), "%p", &local); temp = lookup_widget(MainWindow, "CurrentTimeSuffix"); gtk_label_set_text(GTK_LABEL(temp), buffer); time_t duration_secs = (time_t)GetSecsFromTimestamp(now - StartTime); snprintf(buffer, sizeof(buffer), "%lu:%02lu:%02lu", duration_secs / 3600, (duration_secs % 3600) / 60, duration_secs % 60); temp = lookup_widget(MainWindow, "CurrentDurationLabel"); gtk_label_set_text(GTK_LABEL(temp), buffer); CMediaStream *ms = GetSelectedStream(); if (ms->GetBoolValue(STREAM_RECORD)) { const char *fname; ms->GetStreamStatus(FLOW_STATUS_FILENAME, &fname); struct stat stats; if (stat(fname, &stats) == 0) { uint64_t size = stats.st_size; size /= TO_U64(1000000); snprintf(buffer, sizeof(buffer), " "U64"MB", size); } else { snprintf(buffer, sizeof(buffer), "BAD"); } temp = lookup_widget(MainWindow, "StreamRecording"); gtk_label_set_text(GTK_LABEL(temp), buffer);#if 0 if (MyConfig->GetIntegerValue(CONFIG_RECORD_MP4_FILE_STATUS) == FILE_MP4_CREATE_NEW) { DisplayRecordingSettings(); }#endif } if (!StopTime) { float progress; AVFlow->GetStatus(FLOW_STATUS_PROGRESS, &progress); if (progress > 0.0) { u_int32_t estDuration = (u_int32_t)(duration_secs / progress); DisplayFinishTime(StartTime + (estDuration * TimestampTicks)); } } if (ms->GetBoolValue(STREAM_VIDEO_ENABLED)) { u_int32_t encodedFrames; ms->GetStreamStatus(FLOW_STATUS_VIDEO_ENCODED_FRAMES, &encodedFrames); snprintf(buffer, sizeof(buffer), " %.2f fps", ((float)encodedFrames / (float)(now - StartTime)) * TimestampTicks); temp = lookup_widget(MainWindow, "StreamFps"); gtk_label_set_text(GTK_LABEL(temp), buffer); } bool stop = false; if (StopTime) { stop = (now >= StopTime); } if (!stop && duration_secs > 10) { AVFlow->GetStatus(FLOW_STATUS_DONE, &stop); } if (!stop) { Duration elapsedDuration; if (AVFlow->GetStatus(FLOW_STATUS_DURATION, &elapsedDuration)) { if (elapsedDuration >= FlowDuration) { stop = true; } } } if (stop) { // automatically "press" stop button DoStop(); if (MyConfig->m_appAutomatic) { // In automatic mode, time to exit app gtk_main_quit(); } else { // Make sure user knows that were done char *notice; notice = "Completed"; ShowMessage("Completed", notice, MainWindow); } return (FALSE); } return (TRUE); // keep timer going}static void ReadConfigFromWindow (void){ GtkWidget *temp; temp = lookup_widget(MainWindow, "Duration"); MyConfig->SetIntegerValue(CONFIG_APP_DURATION, gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(temp))); // read info that might not be saved from config CMediaStream *ms = GetSelectedStream(); if (ms != NULL) { temp = lookup_widget(MainWindow, "StreamRecordFileEntry"); ms->SetStringValue(STREAM_RECORD_MP4_FILE_NAME, gtk_entry_get_text(GTK_ENTRY(temp))); temp = lookup_widget(MainWindow, "StreamSdpFileEntry"); ms->SetStringValue(STREAM_SDP_FILE_NAME, gtk_entry_get_text(GTK_ENTRY(temp))); temp = lookup_widget(MainWindow, "StreamCaption"); ms->SetStringValue(STREAM_CAPTION, gtk_entry_get_text(GTK_ENTRY(temp))); temp = lookup_widget(MainWindow, "StreamDescription"); ms->SetStringValue(STREAM_DESCRIPTION, gtk_entry_get_text(GTK_ENTRY(temp))); }}/* * MainWindowDisplaySources - update the sources labels */void MainWindowDisplaySources (void) { GtkWidget *temp; char buffer[128]; temp = lookup_widget(MainWindow, "VideoSourceLabel"); if (MyConfig->m_videoCapabilities != NULL) MyConfig->m_videoCapabilities->Display(MyConfig, buffer, 128); else snprintf(buffer, sizeof(buffer), "no video"); gtk_label_set_text(GTK_LABEL(temp), buffer); temp = lookup_widget(MainWindow, "AudioSourceLabel"); if (MyConfig->m_audioCapabilities != NULL) { MyConfig->m_audioCapabilities->Display(MyConfig, buffer, 128); } else { snprintf(buffer, sizeof(buffer), "no audio"); } gtk_label_set_text(GTK_LABEL(temp), buffer); // need to do text#ifdef HAVE_TEXT temp = lookup_widget(MainWindow, "TextSourceLabel"); DisplayTextSource(MyConfig, buffer, sizeof(buffer)); gtk_label_set_text(GTK_LABEL(temp), buffer);#endif}static const char *add_profile_string = "Add Profile";static const char *customize_profile_string = "Change Profile Settings";// load_profiles will create a menu of the profiles - in alphabetical// order. Should only be called at start, and if a profile is addedstatic void DisplayProfiles (GtkWidget *option_menu, CConfigList *clist, const char ***pOptions, uint32_t *pCount){ if (clist == NULL) return; uint32_t count = clist->GetCount(); uint32_t count_on = 0; const char **options = (const char **)malloc(sizeof(char *) * (count + 4)); CConfigEntry *ce = clist->GetHead(); *pOptions = NULL; // so we don't activate when we create the menu while (ce != NULL) { const char *name = ce->GetName(); options[count_on++] = strdup(name); ce = ce->GetNext(); } // sort list in alphabetical order for (uint32_t ix = 0; ix < count_on - 1; ix++) { for (uint32_t jx = ix; jx < count_on; jx++) { if (strcmp(options[ix], options[jx]) > 0) { const char *temp = options[ix]; options[ix] = options[jx]; options[jx] = temp; } } } options[count_on++] = NULL; // add seperator options[count_on++] = strdup(add_profile_string); options[count_on++] = NULL; options[count_on++] = strdup(customize_profile_string); CreateOptionMenu(option_menu, options, count_on, 0); *pOptions = options; *pCount = count_on;}static const char **audio_profile_names = NULL;static uint32_t audio_profile_names_count = 0;static const char **video_profile_names = NULL;static uint32_t video_profile_names_count = 0;#ifdef HAVE_TEXTstatic const char **text_profile_names = NULL;static uint32_t text_profile_names_count = 0;#endifstatic void free_profile_names (const char **arr, uint32_t count){ for (uint32_t ix = 0; ix < count; ix++) { CHECK_AND_FREE(arr[ix]); } CHECK_AND_FREE(arr);}static uint32_t get_index_from_profile_list (const char **list,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -