Problem:
Receiving a stream of command line warnings as video plays - deprecated pixel format used, make sure you did set range correctly
Question:
How can I stop the warnings from happening or being displayed?
Update - Fixed:
The solution was too override the logging callback and don't do anything in the logging call method. FFmpeg logging is then disabled.
The reason for the message from FFmpeg is because it is grabbing frames from an old video format so is unavoidable if playing older videos.
NOTE:
This solution completely disables all output from FFmpeg. Even FFmpeg errors are muted.
Code below (just frame grabbing, not timed playback).
package test.javacv;
import java.io.File;
import org.bytedeco.javacv.CanvasFrame;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.CustomLogCallback;
public class TestPlay implements Runnable {
private static String video_loc = null;
private static CanvasFrame canvas = new CanvasFrame("Test JavaCV player");
public static void main(String[] args) { new Thread(new TestPlay(args[0])).start(); }
static {
CustomLogCallback.set();
}
public void run() { play_video(video_loc); }
public TestPlay(String loc) {
video_loc = loc;
canvas.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
}
public static final void play_video(String vid_loc) {
try {
File file = new File(vid_loc);
FFmpegFrameGrabber ffmpeg_fg = new FFmpegFrameGrabber(file.getAbsolutePath());
Frame frm;
ffmpeg_fg.setAudioChannels(0);
ffmpeg_fg.start();
for(;;)
if((frm = ffmpeg_fg.grab()) != null) canvas.showImage(frm);
else {
ffmpeg_fg.setTimestamp(0);
break;
}
ffmpeg_fg.stop();
} catch(Exception ex) { ex("play_video vid_loc:" + vid_loc, ex); }
}
public static final void ex(String txt, Exception ex) {
System.out.println("EXCEPTION: " + txt + " stack..."); ex.printStackTrace(System.out); }
}
Logging class
// custom logger to override all logging output
package org.bytedeco.javacv;
import org.bytedeco.javacpp.BytePointer;
import static org.bytedeco.javacpp.avutil.LogCallback;
import static org.bytedeco.javacpp.avutil.setLogCallback;
public class CustomLogCallback extends LogCallback {
static final CustomLogCallback instance = new CustomLogCallback();
public static CustomLogCallback getInstance() { return instance; }
public static void set() { setLogCallback(getInstance()); }
#Override
public void call(int level, BytePointer msg) {}
}
You can adjust the logging level in JavaCV using org.bytedeco.javacpp.avutil.av_log_set_level().
calling avutil.av_log_set_level(avutil.AV_LOG_QUIET); will probably get you what you want.
Related
I am using the below code sample where I am calling the cancelWF method to cancel the execution of workflow. The onCatch method is successfully invoked with the RuntimeException("Simply cancel"), but on the Amazon SWF console the WF does not end immediately, it waits will timeout and ends with a WorkflowExecutionTerminated event.
The whole project is available here if you want more info.
package aws.swf;
import aws.swf.common.Constants;
import aws.swf.common.DelayRequest;
import aws.swf.common.MyActivityClient;
import aws.swf.common.MyActivityClientImpl;
import aws.swf.common.MyWorkflow;
import aws.swf.common.SWFClient;
import com.amazonaws.services.simpleworkflow.AmazonSimpleWorkflow;
import com.amazonaws.services.simpleworkflow.flow.WorkflowWorker;
import com.amazonaws.services.simpleworkflow.flow.annotations.Asynchronous;
import com.amazonaws.services.simpleworkflow.flow.core.Promise;
import com.amazonaws.services.simpleworkflow.flow.core.TryCatch;
import java.util.concurrent.CancellationException;
public class D_CancelWorkflow implements MyWorkflow {
private TryCatch tryCatch;
private final MyActivityClient activityClient = new MyActivityClientImpl();
#Override
public void sum() {
tryCatch = new TryCatch() {
#Override
protected void doTry() throws Throwable {
System.out.printf("[WF %s] Started exec\n", D_CancelWorkflow.this);
Promise<Integer> result = activityClient.getNumWithDelay(new DelayRequest("req1", 1));
cancelWF(result);
newDelayRequest(result);
}
#Override
protected void doCatch(Throwable e) throws Throwable {
if (e instanceof CancellationException) {
System.out.printf("[WF %s] Cancelled With message [%s]\n",
D_CancelWorkflow.this, e.getCause().getMessage());
} else {
e.printStackTrace();
}
rethrow(e);
}
};
}
#Asynchronous
private void newDelayRequest(Promise<Integer> num) {
activityClient.getNumWithDelay(new DelayRequest("req2", 1));
}
#Asynchronous
private void cancelWF(Promise<Integer> ignore) {
System.out.printf("[WF %s] Cancelling WF\n", D_CancelWorkflow.this);
this.tryCatch.cancel(new RuntimeException("Simply cancel"));
}
public static void main(String[] args) throws Exception {
AmazonSimpleWorkflow awsSwfClient = new SWFClient().getClient();
WorkflowWorker workflowWorker =
new WorkflowWorker(awsSwfClient, Constants.DOMAIN, Constants.TASK_LIST);
workflowWorker.addWorkflowImplementationType(D_CancelWorkflow.class);
workflowWorker.start();
}
}
This is the event history for one of my execution,
I'm using Cucumber, Selenium, Java, Maven and JUnit stack in my automation-test-project.
The goal is to take screenshots on fails and broken tests. I have found the solution for Java/Maven/JUnit stack:
#Rule
public TestWatcher screenshotOnFailure = new TestWatcher() {
#Override
protected void failed(Throwable e, Description description) {
makeScreenshotOnFailure();
}
#Attachment("Screenshot on failure")
public byte[] makeScreenshotOnFailure() {
return ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
}
};
But, of course it does not work in case of using Cucumber, because it does not use any #Test methods.
So, I've decided to change #Rule to #ClassRule, to make it listen to any fails, so here it is:
#ClassRule
public static TestWatcher screenshotOnFailure = new TestWatcher() {
#Override
protected void failed(Throwable e, Description description) {
makeScreenshotOnFailure();
}
#Attachment("Screenshot on failure")
public byte[] makeScreenshotOnFailure() {
logger.debug("Taking screenshot");
return ((TakesScreenshot) Application.getInstance().getWebDriver()).getScreenshotAs(OutputType.BYTES);
}
};
And this solution didn't help me.
So, the question is: "How to attach screenshots on fail, when I use Java/Selenium/Cucumber/JUnit/Maven in my test project?"
The solution is just to add following code to your definition classes:
#After
public void embedScreenshot(Scenario scenario) {
if (scenario.isFailed()) {
try {
byte[] screenshot = ((TakesScreenshot) Application.getInstance().getWebDriver())
.getScreenshotAs(OutputType.BYTES);
scenario.embed(screenshot, "image/png");
} catch (Exception e) {
e.printStackTrace();
}
}
}
In the GlobalGlue
public class GlobalGlue {
#Before
public void before(Scenario scenario) throws Exception {
CONTEXT.setScenario(scenario);
}
#After
public void after() {
WebDriverUtility.after(getDriver(), CONTEXT.getScenario());
}
}
Create another class WebDriverUtility and in that add method:
public static void after(WebDriver driver, Scenario scenario) {
getScreenshot(driver, scenario);
driver.close();
}
and
public static void getScreenshot(WebDriver driver, Scenario scenario) {
if (scenario.isFailed()) {
final byte[] screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
scenario.embed(screenshot, "image/png");
log.info("Thread: " + Thread.currentThread().getId() + " :: "
+ "Screenshot taken and inserted in scenario report");
}
}
the main part is you need to embed the screen shot in scenario when scenario is failed:
final byte[] screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
scenario.embed(screenshot, "image/png");
ExecutionContext.java
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import cucumber.api.Scenario;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.openqa.selenium.WebDriver;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
/**
* Maintains one webdriver per scenario and one scenario per thread.
* Can be used for parallel execution.
* Assumes that scenarios within one feature are not parallel.
* Can be rewritten using <code>ThreadLocal</code>.
*
* #author dkhvatov
*/
public enum ExecutionContext {
CONTEXT;
private static final Logger log = LogManager.getLogger(ExecutionContext.class);
private final LoadingCache<Scenario, WebDriver> webDrivers =
CacheBuilder.newBuilder()
.build(CacheLoader.from(scenario ->
WebDriverUtility.createDriver()));
private final Map<String, Scenario> scenarios = new ConcurrentHashMap<>();
/**
* Lazily gets a webdriver for the current scenario.
*
* #return webdriver
*/
public WebDriver getDriver() {
try {
Scenario scenario = getScenario();
if (scenario == null) {
throw new IllegalStateException("Scenario is not set for context. " +
"Please verify your glue settings. Either use GlobalGlue, or set " +
"scenario manually: CONTEXT.setScenario(scenario)");
}
return webDrivers.get(scenario);
} catch (ExecutionException e) {
log.error("Unable to start webdriver", e);
throw new RuntimeException(e);
}
}
/**
* Gets scenario for a current thread.
*
* #return scenario
*/
public Scenario getScenario() {
return scenarios.get(Thread.currentThread().getName());
}
/**
* Sets current scenario. Overwrites current scenario in a map.
*
* #param scenario scenario
*/
public void setScenario(Scenario scenario) {
scenarios.put(Thread.currentThread().getName(), scenario);
}
}
This way you can attach screens to your allure report.
Also use the Latest allure version in your pom file
import com.google.common.io.Files;
import io.qameta.allure.Attachment;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import java.io.File;
import java.io.IOException;
public class ScreenshotUtils {
#Attachment(type = "image/png")
public static byte[] screenshot(WebDriver driver)/* throws IOException */ {
try {
File screen = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
return Files.toByteArray(screen);
} catch (IOException e) {
return null;
}
}
}
Pom File :
<dependency>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-cucumber4-jvm</artifactId>
<version>${allure.version}</version>
</dependency>
<dependency>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-junit4</artifactId>
<version>${allure.version}</version>
<scope>test</scope>
</dependency>
public static void TakeScreenshot(string text)
{
byte[] content = ((ITakesScreenshot)driver).GetScreenshot().AsByteArray;
AllureLifecycle.Instance.AddAttachment(text, "image/png", content);
}
public static void Write(By by, string text)
{
try
{
driver.FindElement(by).SendKeys(text);
TakeScreenshot( "Write : " + text);
}
catch (Exception ex)
{
TakeScreenshot( "Write Failed : " + ex.ToString());
Assert.Fail();
}
}
I am trying to make a properties file in Java. Sadly, when I startup Minecraft (As this is a mod in Forge) the file is not created. I will be so thankful to anyone who helps me. Here is the code:
package mymod.properties;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
public class WriteToProperties {
public static void main(String[] args) {
Properties prop = new Properties();
try {
prop.setProperty("Test", "Yay");
prop.store(new FileOutputStream("Test.properties"), null);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Basically what you want is initialize(event.getSuggestedConfigurationFile());
Forge basically wishes to hand you the default settings to you. I also suggest you structure things logically, so it's nice, clean and accessible later on, and easier to manage.
I use this as a config loader
package tschallacka.magiccookies.init;
import java.io.File;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.common.config.Property;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import tschallacka.magiccookies.MagicCookies;
import tschallacka.magiccookies.api.ModHooks;
import tschallacka.magiccookies.api.Preferences;
public class ConfigLoader {
public static Configuration config;
public static final String CATEGORY_GENERAL = "GeneralSettings";
public static final String CATEGORY_SERVER = "ServerPerformance";
public static void init(FMLPreInitializationEvent event) {
ModHooks.MODID = MagicCookies.MODID;
ModHooks.MODNAME = MagicCookies.MODNAME;
ModHooks.VERSION = MagicCookies.VERSION;
try {
initialize(event.getSuggestedConfigurationFile());
}
catch (Exception e) {
MagicCookies.log.error("MagicCookie failed to load preferences. Reverting to default");
}
finally {
if (config != null) {
save();
}
}
}
private static void initialize(final File file) {
config = new Configuration(file);
config.addCustomCategoryComment(CATEGORY_GENERAL, "General Settings");
config.addCustomCategoryComment(CATEGORY_SERVER, "Server performance settings");
Preferences.magicCookieIsLoaded = true;
config.load();
syncConfigurable();
}
private static void save() {
config.save();
}
private static void syncConfigurable() {
final Property awesomeMod = config.get(Configuration.CATEGORY_GENERAL, "awesome_mod", Preferences.awesomeMod);
awesomeMod.comment = "Set this to yes if you think this mod is awesome, maybe it will at some time unlock a special thing.... or not... but that's only for people who think this is an wesome Mod ;-)";
Preferences.awesomeMod = awesomeMod.getString();
final Property numberOfBlocksPlacingPerTickByStripper = config.get(CATEGORY_SERVER,"number_of_blocks_placing_per_tick_by_stripper",Preferences.numberOfBlocksPlacingPerTickByStripper);
numberOfBlocksPlacingPerTickByStripper.comment = "This affects how many blocks will be placed per tick by the creative stripper tool per tick. The stripper tool will only place blocks if ticks are take less than 50ms. If you experience lag lower this number, if you don't experience lag and want faster copy pasting, make this number higher. For an awesome slowmo build of your caste set this to 1 ;-). Set to 0 to render everything in one go per chunk";
Preferences.numberOfBlocksPlacingPerTickByStripper = numberOfBlocksPlacingPerTickByStripper.getInt();
final Property averageTickTimeCalculationSpan = config.get(CATEGORY_SERVER,"number_of_ticks_used_for_average_time_per_tick_calculation",Preferences.averageTickTimeCalculationSpan);
averageTickTimeCalculationSpan.comment = "This number is the number of tick execution times are added together to calculation an average. The higher number means less lag by some things like the strippers, but can also lead to longer execution times for the strippers. Basically if your server is always running behind on server ticks set this value to 1, to at least get some work done when your server is running under 50ms tickspeed";
Preferences.averageTickTimeCalculationSpan = averageTickTimeCalculationSpan.getInt();
final Property acceptableTickduration = config.get(CATEGORY_SERVER,"acceptable_tick_duration",Preferences.acceptableTickduration);
acceptableTickduration.comment = "Define here what you see as acceptable tick speed where MagicCookies can do some of its magic. If average tick speed or current tick speed is higher than this value it won't perform some tasks to help manage server load.";
Preferences.acceptableTickduration = (long)acceptableTickduration.getDouble();
}
}
The value holder Preferences class.
This is purely so I can do Preferences.valuename everywhere.
package tschallacka.magiccookies.api;
/**
* Here the preferences of MagicCookies will be stored
* and kept after the config's are loaded.
* #author Tschallacka
*
*/
public class Preferences {
public static boolean magicCookieIsLoaded = false;
public static String awesomeMod = "Well?";
public static boolean isLoadedThaumcraft = false;
public static int numberOfBlocksPlacingPerTickByStripper = 0;
public static int averageTickTimeCalculationSpan = 60;
public static long acceptableTickduration = 50l;
public static int darkShrineFrequency = 0;
public static boolean darkShrineSpawnLogging = true;
public static boolean entropyTempleSpawnLogging = true;
public static int entropySize = 30;
}
In your main mod file:
#EventHandler
public void preInit(FMLPreInitializationEvent e) {
MagicCookies.log.warn("Preinit starting");
MinecraftForge.EVENT_BUS.register((Object)MagicCookies.instance);
ConfigLoader.init(e);
}
And after that you can just fetch all your preferences from the Preferences class
This file was created in root of your project. If you want some specific path to save, create folder in root of your project like props and change path in FileOutputStream constructor to "props\\Test.properties"
Asterisk 11.4.0
Asterisk-java: 1.0.0.CI-SNAPSHOT
I've try to run this code:
import org.asteriskjava.live.AsteriskChannel;
import org.asteriskjava.live.AsteriskQueue;
import org.asteriskjava.live.AsteriskQueueEntry;
import org.asteriskjava.live.internal.AsteriskAgentImpl;
import org.asteriskjava.live.AsteriskServer;
import org.asteriskjava.live.AsteriskServerListener;
import org.asteriskjava.live.DefaultAsteriskServer;
import org.asteriskjava.live.ManagerCommunicationException;
import org.asteriskjava.live.MeetMeRoom;
import org.asteriskjava.live.MeetMeUser;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
public class HelloLiveEverything implements AsteriskServerListener, PropertyChangeListener
{
private AsteriskServer asteriskServer;
public HelloLiveEverything()
{
asteriskServer = new DefaultAsteriskServer("localhost", "manager", "password");
}
public void run() throws ManagerCommunicationException
{
// listen for new events
asteriskServer.addAsteriskServerListener(this);
// add property change listeners to existing objects
for (AsteriskChannel asteriskChannel : asteriskServer.getChannels())
{
System.out.println(asteriskChannel);
asteriskChannel.addPropertyChangeListener(this);
}
}
public void onNewAsteriskChannel(AsteriskChannel channel)
{
System.out.println(channel);
channel.addPropertyChangeListener(this);
}
public void onNewMeetMeUser(MeetMeUser user)
{
System.out.println(user);
user.addPropertyChangeListener(this);
}
public void onNewQueueEntry(AsteriskQueueEntry user)
{
System.out.println(user);
user.addPropertyChangeListener(this);
}
public void onNewAgent(AsteriskAgentImpl user)
{
System.out.println(user);
user.addPropertyChangeListener(this);
}
public void propertyChange(PropertyChangeEvent propertyChangeEvent)
{
System.out.println(propertyChangeEvent);
}
public static void main(String[] args) throws Exception
{
HelloLiveEverything helloLiveEverything = new HelloLiveEverything();
helloLiveEverything.run();
while (true) {
}
}
}
When executed, connectios is OK. This code show me current channels but never show me new channels when callers make a calls.
I need to catch the events when new asterisk channels are opening.
What I made wrong?
Thank you
Try This:
Your Class HelloLiveEverything should implement ManagerEventListener
then override the onManagerEvent method
#Override
public void onManagerEvent(ManagerEvent event) {
String event_name = event.getClass().getSimpleName();
if (event_name.equals("DialEvent")) {
DialEvent e = (DialEvent) event;
System.out.println(e.getCallerIdNum());//caller number
System.out.println(e.getDestination());//Called number
//do something here
}
}
edit asterisk manager.conf :
[manager]
secret = password
deny=0.0.0.0/0.0.0.0
permit=209.16.236.73/255.255.255.0; change this ip with one your java app is using permit=127.0.0.1/255.255.255.0
read = system,call,log,verbose,command,agent,user,originate; add full permission
write = system,call,log,verbose,command,agent,user,originate; add full permission
I have one method whose return type is void and it prints directly on console.
However I need that output in a String so that I can work on it.
As I can't make any changes to the method with return type void I have to redirect that output to a String.
How can I redirect it in Java?
If the function is printing to System.out, you can capture that output by using the System.setOut method to change System.out to go to a PrintStream provided by you. If you create a PrintStream connected to a ByteArrayOutputStream, then you can capture the output as a String.
Example:
// Create a stream to hold the output
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(baos);
// IMPORTANT: Save the old System.out!
PrintStream old = System.out;
// Tell Java to use your special stream
System.setOut(ps);
// Print some output: goes to your special stream
System.out.println("Foofoofoo!");
// Put things back
System.out.flush();
System.setOut(old);
// Show what happened
System.out.println("Here: " + baos.toString());
This program prints just one line:
Here: Foofoofoo!
Here is a utility Class named ConsoleOutputCapturer. It allows the output to go to the existing console however behind the scene keeps capturing the output text. You can control what to capture with the start/stop methods. In other words call start to start capturing the console output and once you are done capturing you can call the stop method which returns a String value holding the console output for the time window between start-stop calls. This class is not thread-safe though.
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.List;
public class ConsoleOutputCapturer {
private ByteArrayOutputStream baos;
private PrintStream previous;
private boolean capturing;
public void start() {
if (capturing) {
return;
}
capturing = true;
previous = System.out;
baos = new ByteArrayOutputStream();
OutputStream outputStreamCombiner =
new OutputStreamCombiner(Arrays.asList(previous, baos));
PrintStream custom = new PrintStream(outputStreamCombiner);
System.setOut(custom);
}
public String stop() {
if (!capturing) {
return "";
}
System.setOut(previous);
String capturedValue = baos.toString();
baos = null;
previous = null;
capturing = false;
return capturedValue;
}
private static class OutputStreamCombiner extends OutputStream {
private List<OutputStream> outputStreams;
public OutputStreamCombiner(List<OutputStream> outputStreams) {
this.outputStreams = outputStreams;
}
public void write(int b) throws IOException {
for (OutputStream os : outputStreams) {
os.write(b);
}
}
public void flush() throws IOException {
for (OutputStream os : outputStreams) {
os.flush();
}
}
public void close() throws IOException {
for (OutputStream os : outputStreams) {
os.close();
}
}
}
}
Although this question is very old and has already very good answers I want to provide an alternative. I created a library specifically for this use case. It is called Console Captor and you can add it with the following snippet:
<dependency>
<groupId>io.github.hakky54</groupId>
<artifactId>consolecaptor</artifactId>
<version>1.0.0</version>
<scope>test</scope>
</dependency>
Example class
public class FooService {
public void sayHello() {
System.out.println("Keyboard not responding. Press any key to continue...");
System.err.println("Congratulations, you are pregnant!");
}
}
Unit test
import static org.assertj.core.api.Assertions.assertThat;
import nl.altindag.console.ConsoleCaptor;
import org.junit.jupiter.api.Test;
public class FooServiceTest {
#Test
public void captureStandardAndErrorOutput() {
ConsoleCaptor consoleCaptor = new ConsoleCaptor();
FooService fooService = new FooService();
fooService.sayHello();
assertThat(consoleCaptor.getStandardOutput()).contains("Keyboard not responding. Press any key to continue...");
assertThat(consoleCaptor.getErrorOutput()).contains("Congratulations, you are pregnant!");
consoleCaptor.close();
}
}
If you are using Spring Framework, there is a really easy way to do this with OutputCaptureExtension:
#ExtendWith(OutputCaptureExtension.class)
class MyTest {
#Test
void test(CapturedOutput output) {
System.out.println("ok");
assertThat(output).contains("ok");
System.err.println("error");
}
#AfterEach
void after(CapturedOutput output) {
assertThat(output.getOut()).contains("ok");
assertThat(output.getErr()).contains("error");
}
}