1 /**
2  * @file
3  * @brief Source file for Profile class
4  * @author Jonathan Thomas <jonathan@openshot.org>
5  *
6  * @ref License
7  */
8 
9 /* LICENSE
10  *
11  * Copyright (c) 2008-2019 OpenShot Studios, LLC
12  * <http://www.openshotstudios.com/>. This file is part of
13  * OpenShot Library (libopenshot), an open-source project dedicated to
14  * delivering high quality video editing and animation solutions to the
15  * world. For more information visit <http://www.openshot.org/>.
16  *
17  * OpenShot Library (libopenshot) is free software: you can redistribute it
18  * and/or modify it under the terms of the GNU Lesser General Public License
19  * as published by the Free Software Foundation, either version 3 of the
20  * License, or (at your option) any later version.
21  *
22  * OpenShot Library (libopenshot) is distributed in the hope that it will be
23  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25  * GNU Lesser General Public License for more details.
26  *
27  * You should have received a copy of the GNU Lesser General Public License
28  * along with OpenShot Library. If not, see <http://www.gnu.org/licenses/>.
29  */
30 
31 #include "Profiles.h"
32 #include "Exceptions.h"
33 
34 using namespace openshot;
35 
36 
37 // @brief Constructor for Profile.
38 // @param path 	The folder path / location of a profile file
Profile(std::string path)39 Profile::Profile(std::string path) {
40 
41 	bool read_file = false;
42 
43 	try
44 	{
45 		// Initialize info values
46 		info.description = "";
47 		info.height = 0;
48 		info.width = 0;
49 		info.pixel_format = 0;
50 		info.fps.num = 0;
51 		info.fps.den = 0;
52 		info.pixel_ratio.num = 0;
53 		info.pixel_ratio.den = 0;
54 		info.display_ratio.num = 0;
55 		info.display_ratio.den = 0;
56 		info.interlaced_frame = false;
57 
58 		QFile inputFile(path.c_str());
59 		if (inputFile.open(QIODevice::ReadOnly))
60 		{
61 			QTextStream in(&inputFile);
62 			while (!in.atEnd())
63 			{
64 				QString line = in.readLine();
65 
66 				if (line.length() <= 0)
67 					continue;
68 
69 				// Split current line
70 				QStringList parts = line.split( "=" );
71 				std::string setting = parts[0].toStdString();
72 				std::string value = parts[1].toStdString();
73 				int value_int = 0;
74 
75 				// update struct (based on line number)
76 				if (setting == "description")
77 					info.description = value;
78 				else if (setting == "frame_rate_num") {
79 					std::stringstream(value) >> value_int;
80 					info.fps.num = value_int;
81 				}
82 				else if (setting == "frame_rate_den") {
83 					std::stringstream(value) >> value_int;
84 					info.fps.den = value_int;
85 				}
86 				else if (setting == "width") {
87 					std::stringstream(value) >> value_int;
88 					info.width = value_int;
89 				}
90 				else if (setting == "height") {
91 					std::stringstream(value) >> value_int;
92 					info.height = value_int;
93 				}
94 				else if (setting == "progressive") {
95 					std::stringstream(value) >> value_int;
96 					info.interlaced_frame = !(bool)value_int;
97 				}
98 				else if (setting == "sample_aspect_num") {
99 					std::stringstream(value) >> value_int;
100 					info.pixel_ratio.num = value_int;
101 				}
102 				else if (setting == "sample_aspect_den") {
103 					std::stringstream(value) >> value_int;
104 					info.pixel_ratio.den = value_int;
105 				}
106 				else if (setting == "display_aspect_num") {
107 					std::stringstream(value) >> value_int;
108 					info.display_ratio.num = value_int;
109 				}
110 				else if (setting == "display_aspect_den") {
111 					std::stringstream(value) >> value_int;
112 					info.display_ratio.den = value_int;
113 				}
114 				else if (setting == "colorspace") {
115 					std::stringstream(value) >> value_int;
116 					info.pixel_format = value_int;
117 				}
118 			}
119             read_file = true;
120 			inputFile.close();
121 		}
122 
123 	}
124 	catch (const std::exception& e)
125 	{
126 		// Error parsing profile file
127 		throw InvalidFile("Profile could not be found or loaded (or is invalid).", path);
128 	}
129 
130 	// Throw error if file was not read
131 	if (!read_file)
132 		// Error parsing profile file
133 		throw InvalidFile("Profile could not be found or loaded (or is invalid).", path);
134 }
135 
136 // Generate JSON string of this object
Json() const137 std::string Profile::Json() const {
138 
139 	// Return formatted string
140 	return JsonValue().toStyledString();
141 }
142 
143 // Generate Json::Value for this object
JsonValue() const144 Json::Value Profile::JsonValue() const {
145 
146 	// Create root json object
147 	Json::Value root;
148 	root["height"] = info.height;
149 	root["width"] = info.width;
150 	root["pixel_format"] = info.pixel_format;
151 	root["fps"] = Json::Value(Json::objectValue);
152 	root["fps"]["num"] = info.fps.num;
153 	root["fps"]["den"] = info.fps.den;
154 	root["pixel_ratio"] = Json::Value(Json::objectValue);
155 	root["pixel_ratio"]["num"] = info.pixel_ratio.num;
156 	root["pixel_ratio"]["den"] = info.pixel_ratio.den;
157 	root["display_ratio"] = Json::Value(Json::objectValue);
158 	root["display_ratio"]["num"] = info.display_ratio.num;
159 	root["display_ratio"]["den"] = info.display_ratio.den;
160 	root["interlaced_frame"] = info.interlaced_frame;
161 
162 	// return JsonValue
163 	return root;
164 }
165 
166 // Load JSON string into this object
SetJson(const std::string value)167 void Profile::SetJson(const std::string value) {
168 
169 	// Parse JSON string into JSON objects
170 	try
171 	{
172 		const Json::Value root = openshot::stringToJson(value);
173 		// Set all values that match
174 		SetJsonValue(root);
175 	}
176 	catch (const std::exception& e)
177 	{
178 		// Error parsing JSON (or missing keys)
179 		throw InvalidJSON("JSON is invalid (missing keys or invalid data types)");
180 	}
181 }
182 
183 // Load Json::Value into this object
SetJsonValue(const Json::Value root)184 void Profile::SetJsonValue(const Json::Value root) {
185 
186 	if (!root["height"].isNull())
187 		info.height = root["height"].asInt();
188 	if (!root["width"].isNull())
189 		info.width = root["width"].asInt();
190 	if (!root["pixel_format"].isNull())
191 		info.pixel_format = root["pixel_format"].asInt();
192 	if (!root["fps"].isNull()) {
193 		info.fps.num = root["fps"]["num"].asInt();
194 		info.fps.den = root["fps"]["den"].asInt();
195 	}
196 	if (!root["pixel_ratio"].isNull()) {
197 		info.pixel_ratio.num = root["pixel_ratio"]["num"].asInt();
198 		info.pixel_ratio.den = root["pixel_ratio"]["den"].asInt();
199 	}
200 	if (!root["display_ratio"].isNull()) {
201 		info.display_ratio.num = root["display_ratio"]["num"].asInt();
202 		info.display_ratio.den = root["display_ratio"]["den"].asInt();
203 	}
204 	if (!root["interlaced_frame"].isNull())
205 		info.interlaced_frame = root["interlaced_frame"].asBool();
206 
207 }
208